diff --git a/parser/parser_column.go b/parser/parser_column.go index e273d60..32439d2 100644 --- a/parser/parser_column.go +++ b/parser/parser_column.go @@ -640,7 +640,7 @@ func (p *Parser) parseColumnCastExpr(pos Pos) (Expr, error) { return nil, err } - columnExpr, err := p.parseColumnExpr(p.Pos()) + columnExpr, err := p.parseExpr(p.Pos()) if err != nil { return nil, err } diff --git a/parser/parser_table.go b/parser/parser_table.go index 809d588..10d3f8d 100644 --- a/parser/parser_table.go +++ b/parser/parser_table.go @@ -698,20 +698,24 @@ func (p *Parser) parseTableColumnExpr(pos Pos) (*ColumnDef, error) { columnEnd = notNull.End() } + var valueExpr Expr switch { case p.tryConsumeKeywords(KeywordDefault): column.DefaultExpr, err = p.parseExpr(p.Pos()) - columnEnd = column.DefaultExpr.End() + valueExpr = column.DefaultExpr case p.tryConsumeKeywords(KeywordMaterialized): column.MaterializedExpr, err = p.parseExpr(p.Pos()) - columnEnd = column.MaterializedExpr.End() + valueExpr = column.MaterializedExpr case p.tryConsumeKeywords(KeywordAlias): column.AliasExpr, err = p.parseExpr(p.Pos()) - columnEnd = column.AliasExpr.End() + valueExpr = column.AliasExpr } if err != nil { return nil, err } + if valueExpr != nil { + columnEnd = valueExpr.End() + } comment, err := p.tryParseColumnComment(p.Pos()) if err != nil { diff --git a/parser/parser_test.go b/parser/parser_test.go index 268ca1d..d670f59 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -188,6 +188,10 @@ func TestParser_InvalidSyntax(t *testing.T) { // CREATE TABLE and the next clause in ALTER TABLE. "CREATE TABLE t (a DateTime, b String) ENGINE = MergeTree ORDER BY a, b", "ALTER TABLE t MODIFY ORDER BY a, b", + // A broken column value must report an error, not stop the parser + "CREATE TABLE t (x String DEFAULT CAST(a +, 'String'))", + "CREATE TABLE t (x String MATERIALIZED a +)", + "CREATE TABLE t (x String ALIAS a +)", // Invalid ARRAY JOIN types (only ARRAY JOIN, LEFT ARRAY JOIN, and INNER ARRAY JOIN are valid) "SELECT * FROM t RIGHT ARRAY JOIN arr AS a", // RIGHT ARRAY JOIN not supported "SELECT * FROM t FULL ARRAY JOIN arr AS a", // FULL ARRAY JOIN not supported diff --git a/parser/testdata/query/format/beautify/select_cast.sql b/parser/testdata/query/format/beautify/select_cast.sql index 075439f..e4a278a 100644 --- a/parser/testdata/query/format/beautify/select_cast.sql +++ b/parser/testdata/query/format/beautify/select_cast.sql @@ -3,6 +3,10 @@ select cast(1 as Float64) as value; select cast(1, 'Float64') as value; select (1 as Float64) as value; select 1::Float64 as value; +select cast(a + 1 as String) as value; +select cast(a + 1, 'String') as value; +select cast(-1 as Int8) as value; + -- Beautify SQL: SELECT @@ -13,3 +17,9 @@ SELECT (1 AS Float64) AS value; SELECT 1::Float64 AS value; +SELECT + CAST(a + 1 AS String) AS value; +SELECT + CAST(a + 1, 'String') AS value; +SELECT + CAST(-1 AS Int8) AS value; diff --git a/parser/testdata/query/format/select_cast.sql b/parser/testdata/query/format/select_cast.sql index 523582c..e79bcb3 100644 --- a/parser/testdata/query/format/select_cast.sql +++ b/parser/testdata/query/format/select_cast.sql @@ -3,9 +3,16 @@ select cast(1 as Float64) as value; select cast(1, 'Float64') as value; select (1 as Float64) as value; select 1::Float64 as value; +select cast(a + 1 as String) as value; +select cast(a + 1, 'String') as value; +select cast(-1 as Int8) as value; + -- Format SQL: SELECT CAST(1 AS Float64) AS value; SELECT CAST(1, 'Float64') AS value; SELECT (1 AS Float64) AS value; SELECT 1::Float64 AS value; +SELECT CAST(a + 1 AS String) AS value; +SELECT CAST(a + 1, 'String') AS value; +SELECT CAST(-1 AS Int8) AS value; diff --git a/parser/testdata/query/output/select_cast.sql.golden.json b/parser/testdata/query/output/select_cast.sql.golden.json index 0cdcd6f..81a9910 100644 --- a/parser/testdata/query/output/select_cast.sql.golden.json +++ b/parser/testdata/query/output/select_cast.sql.golden.json @@ -216,5 +216,186 @@ "UnionDistinct": null, "Except": null, "Intersect": null + }, + { + "SelectPos": 132, + "StatementEnd": 169, + "With": null, + "Top": null, + "HasDistinct": false, + "DistinctOn": null, + "SelectItems": [ + { + "Expr": { + "CastPos": 139, + "Expr": { + "LeftExpr": { + "Name": "a", + "QuoteType": 1, + "NamePos": 144, + "NameEnd": 145 + }, + "Operation": "+", + "RightExpr": { + "NumPos": 148, + "NumEnd": 149, + "Literal": "1", + "Base": 10 + }, + "HasGlobal": false, + "HasNot": false + }, + "Separator": "as", + "AsPos": 150, + "AsType": { + "Name": { + "Name": "String", + "QuoteType": 1, + "NamePos": 153, + "NameEnd": 159 + } + } + }, + "Modifiers": [], + "Alias": { + "Name": "value", + "QuoteType": 1, + "NamePos": 164, + "NameEnd": 169 + } + } + ], + "From": null, + "Window": null, + "Prewhere": null, + "Where": null, + "GroupBy": null, + "WithTotal": false, + "Having": null, + "OrderBy": null, + "LimitBy": null, + "Limit": null, + "Settings": null, + "Format": null, + "UnionAll": null, + "UnionDistinct": null, + "Except": null, + "Intersect": null + }, + { + "SelectPos": 171, + "StatementEnd": 208, + "With": null, + "Top": null, + "HasDistinct": false, + "DistinctOn": null, + "SelectItems": [ + { + "Expr": { + "CastPos": 178, + "Expr": { + "LeftExpr": { + "Name": "a", + "QuoteType": 1, + "NamePos": 183, + "NameEnd": 184 + }, + "Operation": "+", + "RightExpr": { + "NumPos": 187, + "NumEnd": 188, + "Literal": "1", + "Base": 10 + }, + "HasGlobal": false, + "HasNot": false + }, + "Separator": ",", + "AsPos": 188, + "AsType": { + "LiteralPos": 191, + "LiteralEnd": 197, + "Literal": "String" + } + }, + "Modifiers": [], + "Alias": { + "Name": "value", + "QuoteType": 1, + "NamePos": 203, + "NameEnd": 208 + } + } + ], + "From": null, + "Window": null, + "Prewhere": null, + "Where": null, + "GroupBy": null, + "WithTotal": false, + "Having": null, + "OrderBy": null, + "LimitBy": null, + "Limit": null, + "Settings": null, + "Format": null, + "UnionAll": null, + "UnionDistinct": null, + "Except": null, + "Intersect": null + }, + { + "SelectPos": 210, + "StatementEnd": 242, + "With": null, + "Top": null, + "HasDistinct": false, + "DistinctOn": null, + "SelectItems": [ + { + "Expr": { + "CastPos": 217, + "Expr": { + "NumPos": 222, + "NumEnd": 224, + "Literal": "-1", + "Base": 10 + }, + "Separator": "as", + "AsPos": 225, + "AsType": { + "Name": { + "Name": "Int8", + "QuoteType": 1, + "NamePos": 228, + "NameEnd": 232 + } + } + }, + "Modifiers": [], + "Alias": { + "Name": "value", + "QuoteType": 1, + "NamePos": 237, + "NameEnd": 242 + } + } + ], + "From": null, + "Window": null, + "Prewhere": null, + "Where": null, + "GroupBy": null, + "WithTotal": false, + "Having": null, + "OrderBy": null, + "LimitBy": null, + "Limit": null, + "Settings": null, + "Format": null, + "UnionAll": null, + "UnionDistinct": null, + "Except": null, + "Intersect": null } ] \ No newline at end of file diff --git a/parser/testdata/query/select_cast.sql b/parser/testdata/query/select_cast.sql index 899e269..6144d76 100644 --- a/parser/testdata/query/select_cast.sql +++ b/parser/testdata/query/select_cast.sql @@ -1,4 +1,7 @@ select cast(1 as Float64) as value; select cast(1, 'Float64') as value; select (1 as Float64) as value; -select 1::Float64 as value; \ No newline at end of file +select 1::Float64 as value; +select cast(a + 1 as String) as value; +select cast(a + 1, 'String') as value; +select cast(-1 as Int8) as value;