From 68ed2574f39ea8d7570cb437efe19d9776d6916e Mon Sep 17 00:00:00 2001 From: erezrokah Date: Tue, 7 Oct 2025 15:08:48 +0100 Subject: [PATCH] fix: Handle select keyword inside functions --- parser/parser_column.go | 2 + .../query/format/select_case_when_exists.sql | 16 ++ .../select_case_when_exists.sql.golden.json | 210 ++++++++++++++++++ .../query/select_case_when_exists.sql | 11 + 4 files changed, 239 insertions(+) create mode 100644 parser/testdata/query/format/select_case_when_exists.sql create mode 100644 parser/testdata/query/output/select_case_when_exists.sql.golden.json create mode 100644 parser/testdata/query/select_case_when_exists.sql diff --git a/parser/parser_column.go b/parser/parser_column.go index 5312319..64b8942 100644 --- a/parser/parser_column.go +++ b/parser/parser_column.go @@ -366,6 +366,8 @@ func (p *Parser) parseColumnExpr(pos Pos) (Expr, error) { //nolint:funlen return p.parseColumnCastExpr(pos) case p.matchKeyword(KeywordCase): return p.parseColumnCaseExpr(pos) + case p.matchKeyword(KeywordSelect): + return p.parseSelectQuery(pos) case p.matchKeyword(KeywordExtract): return p.parseColumnExtractExpr(pos) case p.matchTokenKind(TokenKindIdent): diff --git a/parser/testdata/query/format/select_case_when_exists.sql b/parser/testdata/query/format/select_case_when_exists.sql new file mode 100644 index 0000000..3dff954 --- /dev/null +++ b/parser/testdata/query/format/select_case_when_exists.sql @@ -0,0 +1,16 @@ +-- Origin SQL: +SELECT + *, + CASE + WHEN EXISTS(SELECT 1 + FROM table_name + WHERE col1 = '999999999') + THEN 'then' + ELSE 'else' + END as check_result +FROM table_name +WHERE col1 = '123456789' + + +-- Format SQL: +SELECT *, CASE WHEN EXISTS(SELECT 1 FROM table_name WHERE col1 = '999999999') THEN 'then' ELSE 'else' END AS check_result FROM table_name WHERE col1 = '123456789'; diff --git a/parser/testdata/query/output/select_case_when_exists.sql.golden.json b/parser/testdata/query/output/select_case_when_exists.sql.golden.json new file mode 100644 index 0000000..5a8fa71 --- /dev/null +++ b/parser/testdata/query/output/select_case_when_exists.sql.golden.json @@ -0,0 +1,210 @@ +[ + { + "SelectPos": 0, + "StatementEnd": 205, + "With": null, + "Top": null, + "HasDistinct": false, + "DistinctOn": null, + "SelectItems": [ + { + "Expr": { + "Name": "*", + "QuoteType": 0, + "NamePos": 11, + "NameEnd": 11 + }, + "Modifiers": [], + "Alias": null + }, + { + "Expr": { + "CasePos": 18, + "EndPos": 0, + "Expr": null, + "Whens": [ + { + "WhenPos": 31, + "ThenPos": 110, + "When": { + "Name": { + "Name": "EXISTS", + "QuoteType": 1, + "NamePos": 36, + "NameEnd": 42 + }, + "Params": { + "LeftParenPos": 42, + "RightParenPos": 100, + "Items": { + "ListPos": 43, + "ListEnd": 99, + "HasDistinct": false, + "Items": [ + { + "Expr": { + "SelectPos": 43, + "StatementEnd": 99, + "With": null, + "Top": null, + "HasDistinct": false, + "DistinctOn": null, + "SelectItems": [ + { + "Expr": { + "NumPos": 50, + "NumEnd": 51, + "Literal": "1", + "Base": 10 + }, + "Modifiers": [], + "Alias": null + } + ], + "From": { + "FromPos": 56, + "Expr": { + "Table": { + "TablePos": 61, + "TableEnd": 71, + "Alias": null, + "Expr": { + "Database": null, + "Table": { + "Name": "table_name", + "QuoteType": 1, + "NamePos": 61, + "NameEnd": 71 + } + }, + "HasFinal": false + }, + "StatementEnd": 71, + "SampleRatio": null, + "HasFinal": false + } + }, + "ArrayJoin": null, + "Window": null, + "Prewhere": null, + "Where": { + "WherePos": 76, + "Expr": { + "LeftExpr": { + "Name": "col1", + "QuoteType": 1, + "NamePos": 82, + "NameEnd": 86 + }, + "Operation": "=", + "RightExpr": { + "LiteralPos": 90, + "LiteralEnd": 99, + "Literal": "999999999" + }, + "HasGlobal": false, + "HasNot": false + } + }, + "GroupBy": null, + "WithTotal": false, + "Having": null, + "OrderBy": null, + "LimitBy": null, + "Limit": null, + "Settings": null, + "Format": null, + "UnionAll": null, + "UnionDistinct": null, + "Except": null + }, + "Alias": null + } + ] + }, + "ColumnArgList": null + } + }, + "Then": { + "LiteralPos": 116, + "LiteralEnd": 120, + "Literal": "then" + }, + "ElsePos": 0, + "Else": null + } + ], + "ElsePos": 130, + "Else": { + "LiteralPos": 136, + "LiteralEnd": 140, + "Literal": "else" + } + }, + "Modifiers": [], + "Alias": { + "Name": "check_result", + "QuoteType": 1, + "NamePos": 153, + "NameEnd": 165 + } + } + ], + "From": { + "FromPos": 166, + "Expr": { + "Table": { + "TablePos": 171, + "TableEnd": 181, + "Alias": null, + "Expr": { + "Database": null, + "Table": { + "Name": "table_name", + "QuoteType": 1, + "NamePos": 171, + "NameEnd": 181 + } + }, + "HasFinal": false + }, + "StatementEnd": 181, + "SampleRatio": null, + "HasFinal": false + } + }, + "ArrayJoin": null, + "Window": null, + "Prewhere": null, + "Where": { + "WherePos": 182, + "Expr": { + "LeftExpr": { + "Name": "col1", + "QuoteType": 1, + "NamePos": 188, + "NameEnd": 192 + }, + "Operation": "=", + "RightExpr": { + "LiteralPos": 196, + "LiteralEnd": 205, + "Literal": "123456789" + }, + "HasGlobal": false, + "HasNot": false + } + }, + "GroupBy": null, + "WithTotal": false, + "Having": null, + "OrderBy": null, + "LimitBy": null, + "Limit": null, + "Settings": null, + "Format": null, + "UnionAll": null, + "UnionDistinct": null, + "Except": null + } +] \ No newline at end of file diff --git a/parser/testdata/query/select_case_when_exists.sql b/parser/testdata/query/select_case_when_exists.sql new file mode 100644 index 0000000..a54b68e --- /dev/null +++ b/parser/testdata/query/select_case_when_exists.sql @@ -0,0 +1,11 @@ +SELECT + *, + CASE + WHEN EXISTS(SELECT 1 + FROM table_name + WHERE col1 = '999999999') + THEN 'then' + ELSE 'else' + END as check_result +FROM table_name +WHERE col1 = '123456789'