Skip to content

Commit

Permalink
Merge #49525
Browse files Browse the repository at this point in the history
49525: sql: add the `GENERATED ALWAYS` alias for computed columns r=knz a=rohany

Fixes #42418.

This PR adds an alias to create computed columns with the Postgres
syntax that uses `GENERATED ALWAYS`. Due an unfortunate ambiguity caused
by the `CREATE FAMILY` column qualifications, the parser cannot tell
with a single lookahead token what to do in the case of

```
CREATE TABLE t (x INT CREATE FAMILY GENERATED...)
```

Here, with only 1 token of lookahead, we don't know whether GENERATED is
that start of the generated computed clause, or the name of the family.
To rectify this, we use the same trick used in other cases, where the
lexer will generate a new `GENERATED_ALWAYS` token that allows us to get
past the ambiguity here.

Release note (sql change): Add the Postgres syntax `GENERATED ALWAYS`
alias for computed column construction.

Co-authored-by: Rohan Yadav <[email protected]>
  • Loading branch information
craig[bot] and rohany committed May 25, 2020
2 parents 533095b + 43f6b2c commit 8f7cd61
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 4 deletions.
1 change: 1 addition & 0 deletions docs/generated/sql/bnf/stmt_block.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -2503,6 +2503,7 @@ opt_name_parens ::=

generated_as ::=
'AS'
| 'GENERATED_ALWAYS' 'ALWAYS' 'AS'

reference_action ::=
'NO' 'ACTION'
Expand Down
1 change: 1 addition & 0 deletions pkg/sql/lex/predicates.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func init() {
"ordinality",
"similar",
"time",
"generated",
} {
reservedOrLookaheadKeywords[s] = struct{}{}
}
Expand Down
14 changes: 14 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/computed
Original file line number Diff line number Diff line change
Expand Up @@ -776,3 +776,17 @@ query TT
SELECT * FROM t34901
----
a ab

# Regression test for #42418.
statement ok
CREATE TABLE t42418 (x INT GENERATED ALWAYS AS (1) STORED);
ALTER TABLE t42418 ADD COLUMN y INT GENERATED ALWAYS AS (1) STORED

query TT
SHOW CREATE t42418
----
t42418 CREATE TABLE t42418 (
x INT8 NULL AS (1) STORED,
y INT8 NULL AS (1) STORED,
FAMILY "primary" (x, rowid, y)
)
7 changes: 6 additions & 1 deletion pkg/sql/parser/lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func (l *lexer) Lex(lval *sqlSymType) int {
*lval = l.tokens[l.lastPos]

switch lval.id {
case NOT, WITH, AS:
case NOT, WITH, AS, GENERATED:
nextID := int32(0)
if l.lastPos+1 < len(l.tokens) {
nextID = l.tokens[l.lastPos+1].id
Expand All @@ -98,6 +98,11 @@ func (l *lexer) Lex(lval *sqlSymType) int {
case BETWEEN, IN, LIKE, ILIKE, SIMILAR:
lval.id = NOT_LA
}
case GENERATED:
switch nextID {
case ALWAYS:
lval.id = GENERATED_ALWAYS
}

case WITH:
switch nextID {
Expand Down
1 change: 1 addition & 0 deletions pkg/sql/parser/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2328,6 +2328,7 @@ $function$`,
`CREATE TABLE a (b INT8, c STRING, FOREIGN KEY (b, c) REFERENCES other (x, y) MATCH SIMPLE ON DELETE CASCADE ON UPDATE SET NULL)`,
`CREATE TABLE a (b INT8, c STRING, FOREIGN KEY (b, c) REFERENCES other (x, y) ON DELETE CASCADE ON UPDATE SET NULL)`,
},
{`CREATE TABLE a (b INT8 GENERATED ALWAYS AS (a + b) STORED)`, `CREATE TABLE a (b INT8 AS (a + b) STORED)`},

{`ALTER TABLE a ALTER b DROP STORED`, `ALTER TABLE a ALTER COLUMN b DROP STORED`},
{`ALTER TABLE a ADD b INT8`, `ALTER TABLE a ADD COLUMN b INT8`},
Expand Down
8 changes: 5 additions & 3 deletions pkg/sql/parser/sql.y
Original file line number Diff line number Diff line change
Expand Up @@ -647,8 +647,10 @@ func (u *sqlSymUnion) alterTypeAddValuePlacement() *tree.AlterTypeAddValuePlacem
// NOT_LA exists so that productions such as NOT LIKE can be given the same
// precedence as LIKE; otherwise they'd effectively have the same precedence as
// NOT, at least with respect to their left-hand subexpression. WITH_LA is
// needed to make the grammar LALR(1).
%token NOT_LA WITH_LA AS_LA
// needed to make the grammar LALR(1). GENERATED_ALWAYS is needed to support
// the Postgres syntax for computed columns along with our family related
// extensions (CREATE FAMILY/CREATE FAMILY family_name).
%token NOT_LA WITH_LA AS_LA GENERATED_ALWAYS

%union {
id int32
Expand Down Expand Up @@ -4987,7 +4989,7 @@ col_qualification_elem:
// GENERATED ALWAYS is a noise word for compatibility with Postgres.
generated_as:
AS {}
// GENERATED ALWAYS AS {}
| GENERATED_ALWAYS ALWAYS AS {}


index_def:
Expand Down

0 comments on commit 8f7cd61

Please sign in to comment.