FB-1739: Add ability to add a description to a table on creation (#2332)

* FB-1739: Add ability to add a description to a table on creation

- Added CommentOption to handle text after COMMENT option.
- added description field in the createtable plan.
- The description is stored in the existing index metadata.
This commit is contained in:
rachithrr 2022-12-07 21:05:54 +05:30 • committed by GitHub
parent 969bf055b2
commit ad350c2d49
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 75 additions and 5 deletions

View file

@ -93,6 +93,7 @@ func (*UsingConstraint) node() {}
func (*Window) node() {}
func (*WindowDefinition) node() {}
func (*WithClause) node() {}
func (*CommentOption) node() {}
type Statement interface {
Node
@ -771,6 +772,7 @@ type TableOption interface {
func (*KeyPartitionsOption) option() {}
func (*ShardWidthOption) option() {}
func (*CommentOption) option() {}
type KeyPartitionsOption struct {
KeyPartitions Pos // position of KEYPARTITIONS keyword
@ -798,6 +800,19 @@ func (o *ShardWidthOption) String() string {
return buf.String()
}
type CommentOption struct {
Comment Pos // position of COMMENT keyword
Expr Expr // expression
}
func (o *CommentOption) String() string {
var buf bytes.Buffer
buf.WriteString("COMMENT (")
buf.WriteString(o.Expr.String())
buf.WriteString(")")
return buf.String()
}
type Constraint interface {
Node
constraint()

View file

@ -445,12 +445,30 @@ func (p *Parser) parseTableOption() (_ TableOption, err error) {
switch p.peek() {
case KEYPARTITIONS:
return p.parseKeyPartitionsOption(optionPos)
case COMMENT:
return p.parseCommentOption(optionPos)
default:
assert(p.peek() == SHARDWIDTH)
return p.parseShardWidthOption(optionPos)
}
}
func (p *Parser) parseCommentOption(optionPos Pos) (_ *CommentOption, err error) {
assert(p.peek() == COMMENT)
var opt CommentOption
opt.Comment, _, _ = p.scan()
if isLiteralToken(p.peek()) {
opt.Expr = p.mustParseLiteral()
} else {
return &opt, p.errorExpected(p.pos, p.tok, "literal")
}
return &opt, nil
}
func (p *Parser) parseKeyPartitionsOption(optionPos Pos) (_ *KeyPartitionsOption, err error) {
assert(p.peek() == KEYPARTITIONS)
@ -3418,7 +3436,7 @@ func (e Error) Error() string {
// isTableOptionStartToken returns true if tok is the initial token of a table option.
func isTableOptionStartToken(tok Token) bool {
switch tok {
case KEYPARTITIONS, SHARDWIDTH:
case KEYPARTITIONS, SHARDWIDTH, COMMENT:
return true
default:
return false

View file

@ -28,7 +28,6 @@ const (
// Special tokens
ILLEGAL Token = iota
EOF
COMMENT
SPACE
literal_beg
@ -103,6 +102,7 @@ const (
COLUMNS
COLUMNKW
COMMIT
COMMENT
CONFLICT
CONSTRAINT
CREATE
@ -256,7 +256,6 @@ const (
var tokens = [...]string{
ILLEGAL: "ILLEGAL",
EOF: "EOF",
COMMENT: "COMMENT",
SPACE: "SPACE",
IDENT: "IDENT",
@ -326,6 +325,7 @@ var tokens = [...]string{
COLUMNS: "COLUMNS",
COLUMNKW: "COLUMNKW",
COMMIT: "COMMIT",
COMMENT: "COMMENT",
CONFLICT: "CONFLICT",
CONSTRAINT: "CONSTRAINT",
CREATE: "CREATE",

View file

@ -30,6 +30,7 @@ func (p *ExecutionPlanner) compileCreateTableStatement(stmt *parser.CreateTableS
// apply table options
keyPartitions := 0
description := ""
for _, option := range stmt.Options {
switch o := option.(type) {
case *parser.KeyPartitionsOption:
@ -39,6 +40,9 @@ func (p *ExecutionPlanner) compileCreateTableStatement(stmt *parser.CreateTableS
return nil, err
}
keyPartitions = int(i)
case *parser.CommentOption:
e := o.Expr.(*parser.StringLit)
description = e.Value
}
}
@ -63,7 +67,7 @@ func (p *ExecutionPlanner) compileCreateTableStatement(stmt *parser.CreateTableS
columns = append(columns, column)
}
return NewPlanOpQuery(p, NewPlanOpCreateTable(p, tableName, failIfExists, isKeyed, keyPartitions, columns), p.sql), nil
return NewPlanOpQuery(p, NewPlanOpCreateTable(p, tableName, failIfExists, isKeyed, keyPartitions, description, columns), p.sql), nil
}
// compiles a column def
@ -301,6 +305,13 @@ func (p *ExecutionPlanner) analyzeCreateTableStatement(stmt *parser.CreateTableS
return sql3.NewErrInvalidShardWidthValue(o.Expr.Pos().Line, o.Expr.Pos().Column, i)
}
case *parser.CommentOption:
_, ok := o.Expr.(*parser.StringLit)
if !ok {
return sql3.NewErrStringLiteral(o.Expr.Pos().Line, o.Expr.Pos().Column)
}
default:
return sql3.NewErrInternalf("unhandled table option type '%T'", option)
}

View file

@ -18,11 +18,13 @@ type PlanOpCreateTable struct {
failIfExists bool
isKeyed bool
keyPartitions int
description string
columns []*createTableField
warnings []string
}
func NewPlanOpCreateTable(p *ExecutionPlanner, tableName string, failIfExists bool, isKeyed bool, keyPartitions int, columns []*createTableField) *PlanOpCreateTable {
// NewPlanOpCreateTable returns a new PlanOpCreateTable planoperator
func NewPlanOpCreateTable(p *ExecutionPlanner, tableName string, failIfExists bool, isKeyed bool, keyPartitions int, description string, columns []*createTableField) *PlanOpCreateTable {
return &PlanOpCreateTable{
planner: p,
tableName: tableName,
@ -30,6 +32,7 @@ func NewPlanOpCreateTable(p *ExecutionPlanner, tableName string, failIfExists bo
isKeyed: isKeyed,
keyPartitions: keyPartitions,
columns: columns,
description: description,
warnings: make([]string, 0),
}
}
@ -75,6 +78,7 @@ func (p *PlanOpCreateTable) Iterator(ctx context.Context, row types.Row) (types.
isKeyed: p.isKeyed,
keyPartitions: p.keyPartitions,
columns: p.columns,
description: p.description,
}, nil
}
@ -88,6 +92,7 @@ type createTableRowIter struct {
failIfExists bool
isKeyed bool
keyPartitions int
description string
columns []*createTableField
}
@ -99,6 +104,7 @@ func (i *createTableRowIter) Next(ctx context.Context) (types.Row, error) {
Keys: i.isKeyed,
TrackExistence: true,
PartitionN: i.keyPartitions,
Description: i.description,
}
fields := make([]pilosa.CreateFieldObj, len(i.columns))

View file

@ -44,6 +44,26 @@ var createTable = TableTest{
"create table foo (_id id, i1 int) shardwidth 131072",
),
},
{
name: "commentInt",
SQLs: sqls(
"create table foo (_id id, i1 int) comment 34",
),
ExpErr: "string literal expected",
},
{
name: "commentStringNoQuote",
SQLs: sqls(
"create table foo (_id id, i1 int) comment bad",
),
ExpErr: "expected literal, found bad",
},
{
name: "commentString",
SQLs: sqls(
"create table bar (_id id, i1 int) comment 'this should work'",
),
},
},
}