From 790ac680a66c837fe8f6ce62b511b1dea5ffa78c Mon Sep 17 00:00:00 2001 From: wenshao Date: Wed, 30 Oct 2024 08:28:25 +0800 Subject: [PATCH] improved big query sql parser --- .../druid/sql/ast/expr/SQLCastExpr.java | 12 +++++++++++ .../bigquery/parser/BigQueryExprParser.java | 10 ++++++++++ .../bigquery/parser/BigQueryLexer.java | 20 +++++++++++++++++++ .../visitor/BigQueryOutputVisitor.java | 7 +++++++ .../druid/sql/parser/SQLExprParser.java | 9 +++++++++ .../test/resources/bvt/parser/bigquery/0.txt | 11 ++++++++++ 6 files changed, 69 insertions(+) diff --git a/core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLCastExpr.java b/core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLCastExpr.java index 6292757bdb..36d072af5f 100644 --- a/core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLCastExpr.java +++ b/core/src/main/java/com/alibaba/druid/sql/ast/expr/SQLCastExpr.java @@ -26,6 +26,7 @@ public class SQLCastExpr extends SQLExprImpl implements SQLObjectWithDataType, S protected boolean isTry; protected SQLExpr expr; protected SQLDataType dataType; + protected SQLExpr format; public SQLCastExpr() { } @@ -46,6 +47,17 @@ public void setExpr(SQLExpr expr) { this.expr = expr; } + public SQLExpr getFormat() { + return format; + } + + public void setFormat(SQLExpr format) { + if (format != null) { + format.setParent(this); + } + this.format = format; + } + public SQLDataType getDataType() { return this.dataType; } diff --git a/core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/parser/BigQueryExprParser.java b/core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/parser/BigQueryExprParser.java index 465580b3c2..6164b3ad14 100644 --- a/core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/parser/BigQueryExprParser.java +++ b/core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/parser/BigQueryExprParser.java @@ -333,4 +333,14 @@ public SQLExpr exprRest(SQLExpr expr) { } return super.exprRest(expr); } + + @Override + protected SQLCastExpr parseCastFormat(SQLCastExpr cast) { + if (lexer.nextIfIdentifier("FORMAT")) { + cast.setFormat( + this.expr() + ); + } + return cast; + } } diff --git a/core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/parser/BigQueryLexer.java b/core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/parser/BigQueryLexer.java index 563430e92b..f26c128fc9 100644 --- a/core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/parser/BigQueryLexer.java +++ b/core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/parser/BigQueryLexer.java @@ -168,6 +168,26 @@ public void scanComment() { @Override protected void scanString() { + if (pos + 2 < text.length() + && text.charAt(pos + 1) == '\'' + && text.charAt(pos + 2) == '\'' + ) { + for (int i = pos + 3; i < text.length(); i++) { + char c = text.charAt(i); + if (c == '\'' + && i + 2 < text.length() + && text.charAt(i + 1) == '\'' + && text.charAt(i + 2) == '\'' + ) { + stringVal = text.substring(pos + 3, i); + token = Token.LITERAL_TEXT_BLOCK; + pos = i + 2; + scanChar(); + return; + } + } + } + { boolean hasSpecial = false; int startIndex = pos + 1; diff --git a/core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/visitor/BigQueryOutputVisitor.java b/core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/visitor/BigQueryOutputVisitor.java index e8d7e8e707..88f12c9e6a 100644 --- a/core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/visitor/BigQueryOutputVisitor.java +++ b/core/src/main/java/com/alibaba/druid/sql/dialect/bigquery/visitor/BigQueryOutputVisitor.java @@ -234,6 +234,13 @@ public boolean visit(SQLCastExpr x) { x.getExpr().accept(this); print0(ucase ? " AS " : " as "); x.getDataType().accept(this); + + SQLExpr format = x.getFormat(); + if (format != null) { + print0(ucase ? " FORMAT " : " format "); + format.accept(this); + } + print0(")"); tryPrintRparen(x); return false; diff --git a/core/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java b/core/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java index aace548b91..312a9197c4 100644 --- a/core/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/core/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -1270,6 +1270,10 @@ && dialectFeatureEnabled(SQLTimestampExpr)) { sqlExpr = array; break; } + case LITERAL_TEXT_BLOCK: + sqlExpr = new SQLCharExpr(lexer.stringVal()); + lexer.nextToken(); + break; default: throw new ParserException("ERROR. " + lexer.info()); } @@ -1307,11 +1311,16 @@ protected SQLExpr parseCast() { } arrayDataType.setUsedForCast(true); } + cast = parseCastFormat(cast); accept(Token.RPAREN); return cast; } } + protected SQLCastExpr parseCastFormat(SQLCastExpr cast) { + return cast; + } + protected SQLExpr parseQueryExpr() { return new SQLQueryExpr( createSelectParser() diff --git a/core/src/test/resources/bvt/parser/bigquery/0.txt b/core/src/test/resources/bvt/parser/bigquery/0.txt index d68feb9ef8..1aa29311b3 100644 --- a/core/src/test/resources/bvt/parser/bigquery/0.txt +++ b/core/src/test/resources/bvt/parser/bigquery/0.txt @@ -1,3 +1,14 @@ +SELECT CAST(b'\x48\x65\x6c\x6c\x6f' AS STRING FORMAT 'ASCII') AS bytes_to_string; +-------------------- +SELECT CAST(b'\x48\x65\x6c\x6c\x6f' AS STRING FORMAT 'ASCII') AS bytes_to_string; +------------------------------------------------------------------------------------------------------------------------ +select """abc""", '''it's''', '''Title:"Boy"''', '''two + lines''', '''why\?''' +-------------------- +SELECT 'abc', 'it''s', 'Title:"Boy"' + , 'two + lines', 'why\?' +------------------------------------------------------------------------------------------------------------------------ UPDATE `p1` main SET