Skip to content

Commit d1d15f7

Browse files
committed
feat(parser): add BIGQUERY, DATABRICKS and SNOWFLAKE dialect presets
Three warehouse presets for the lexer feature switches, each row taken from the vendor docs: BIGQUERY carries double quoted strings, # line comments, backslash escapes and the any-whitespace adjacent literal rule (GoogleSQL lexical structure; identifiers are backticked); DATABRICKS the same minus # comments (Spark literals; the double quoted identifiers switch is a non-default conf); SNOWFLAKE backslash escape sequences only, double quotes stay quoted identifiers (string and binary data types). Redshift was surveyed too and stays with the defaults on every switch, so it gains no preset entry. Follows up on the four warehouses named in #2512.
1 parent 9f58f3d commit d1d15f7

3 files changed

Lines changed: 56 additions & 7 deletions

File tree

src/main/java/net/sf/jsqlparser/parser/AbstractJSqlParser.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,15 @@ public enum Dialect {
3737
Feature.allowHashLineComments,
3838
Feature.allowDoubleQuotedStrings), SQLSERVER(AdjacentStringLiterals.OFF,
3939
Feature.allowSquareBracketQuotation), POSTGRESQL(
40-
AdjacentStringLiterals.NEWLINE), H2, EXASOL;
40+
AdjacentStringLiterals.NEWLINE), H2, EXASOL, BIGQUERY(
41+
AdjacentStringLiterals.WHITESPACE,
42+
Feature.allowDoubleQuotedStrings,
43+
Feature.allowHashLineComments,
44+
Feature.allowBackslashEscapeCharacter), DATABRICKS(
45+
AdjacentStringLiterals.WHITESPACE,
46+
Feature.allowDoubleQuotedStrings,
47+
Feature.allowBackslashEscapeCharacter), SNOWFLAKE(
48+
Feature.allowBackslashEscapeCharacter);
4149

4250
private final Set<Feature> lexerFeatures;
4351
private final AdjacentStringLiterals adjacentStringLiterals;

src/site/sphinx/usage.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ Additionally there are Features to control the Parser's effort at the cost of th
319319
.withBackslashEscapeCharacter(true)
320320
);
321321
322-
Instead of turning the individual Parser Features on one by one, a ``Dialect`` preset selects the features of that database dialect: ``withDialect(Dialect.MYSQL)`` turns on ``withBackslashEscapeCharacter``, ``withHashLineComments`` and ``withDoubleQuotedStrings`` (MySQL and MariaDB syntax, the latter for the default sql_mode), ``withDialect(Dialect.SQLSERVER)`` turns on ``withSquareBracketQuotation``. ``withDialect(Dialect.POSTGRESQL)`` and ``withDialect(Dialect.ANSI_SQL)`` turn on the newline rule for adjacent String Literals. Features set explicitly after the dialect preset win over the preset.
322+
Instead of turning the individual Parser Features on one by one, a ``Dialect`` preset selects the features of that database dialect: ``withDialect(Dialect.MYSQL)`` turns on ``withBackslashEscapeCharacter``, ``withHashLineComments`` and ``withDoubleQuotedStrings`` (MySQL and MariaDB syntax, the latter for the default sql_mode), ``withDialect(Dialect.SQLSERVER)`` turns on ``withSquareBracketQuotation``. ``withDialect(Dialect.POSTGRESQL)`` and ``withDialect(Dialect.ANSI_SQL)`` turn on the newline rule for adjacent String Literals. ``withDialect(Dialect.BIGQUERY)`` and ``withDialect(Dialect.DATABRICKS)`` turn on ``withDoubleQuotedStrings`` and ``withBackslashEscapeCharacter`` plus the any-whitespace rule for adjacent String Literals, the BigQuery preset additionally ``withHashLineComments``; ``withDialect(Dialect.SNOWFLAKE)`` turns on ``withBackslashEscapeCharacter`` only, keeping double quotes as quoted identifiers. Features set explicitly after the dialect preset win over the preset.
323323

324324
.. code-block:: java
325325

src/test/java/net/sf/jsqlparser/parser/CCJSqlParserUtilTest.java

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -641,19 +641,51 @@ public void testDoubleQuotedStringsFeature() throws Exception {
641641
.parse("SELECT * FROM \"t\"", p -> p.withDoubleQuotedStrings(true)).toString());
642642
}
643643

644+
@Test
645+
public void testDialectPresetsWarehouses() throws Exception {
646+
// BIGQUERY: double quoted strings, # line comments and backslash
647+
// escapes (GoogleSQL "Lexical structure and syntax", identifiers are
648+
// backticked), backticks stay unconditional
649+
assertEquals("SELECT `col` FROM t WHERE a = 'x\\'yz' AND b = 42", CCJSqlParserUtil
650+
.parse("SELECT `col` FROM t WHERE a = 'x\\'yz' AND b = 42#24",
651+
p -> p.withDialect(AbstractJSqlParser.Dialect.BIGQUERY))
652+
.toString());
653+
// DATABRICKS: double quoted strings and backslash escapes (Spark
654+
// "Literals"), `#` stays the #2507 operator
655+
assertEquals("SELECT \"a\" FROM t WHERE x = 'it\\'s'", CCJSqlParserUtil
656+
.parse("SELECT \"a\" FROM t WHERE x = 'it\\'s'",
657+
p -> p.withDialect(AbstractJSqlParser.Dialect.DATABRICKS))
658+
.toString());
659+
assertEquals("SELECT 42 # 24", CCJSqlParserUtil.parse("SELECT 42 # 24",
660+
p -> p.withDialect(AbstractJSqlParser.Dialect.DATABRICKS)).toString());
661+
// SNOWFLAKE: backslash escape sequences ("String & binary data
662+
// types"), `#` stays the operator
663+
assertEquals("SELECT col FROM t WHERE a = 'x\\'yz'", CCJSqlParserUtil
664+
.parse("SELECT col FROM t WHERE a = 'x\\'yz'",
665+
p -> p.withDialect(AbstractJSqlParser.Dialect.SNOWFLAKE))
666+
.toString());
667+
assertEquals("SELECT 42 # 24", CCJSqlParserUtil.parse("SELECT 42 # 24",
668+
p -> p.withDialect(AbstractJSqlParser.Dialect.SNOWFLAKE)).toString());
669+
}
670+
644671
@Test
645672
public void testDoubleQuotedStringsPreset() throws Exception {
646-
// MYSQL and MARIADB presets carry the switch (default sql_mode reading)
673+
// the string-default dialects: MYSQL and MARIADB (default sql_mode),
674+
// BIGQUERY and DATABRICKS (string literals, identifiers are backticked)
647675
for (AbstractJSqlParser.Dialect dialect : new AbstractJSqlParser.Dialect[] {
648-
AbstractJSqlParser.Dialect.MYSQL, AbstractJSqlParser.Dialect.MARIADB}) {
676+
AbstractJSqlParser.Dialect.MYSQL, AbstractJSqlParser.Dialect.MARIADB,
677+
AbstractJSqlParser.Dialect.BIGQUERY, AbstractJSqlParser.Dialect.DATABRICKS}) {
649678
PlainSelect select = (PlainSelect) ((Select) CCJSqlParserUtil
650679
.parse("SELECT \"abc\"", p -> p.withDialect(dialect))).getSelectBody();
651680
assertTrue(select.getSelectItems().get(0).getExpression() instanceof StringValue);
652681
}
653682
// the identifier-default dialects keep the quoted identifier reading
654-
PlainSelect select = (PlainSelect) ((Select) CCJSqlParserUtil.parse("SELECT \"abc\"",
655-
p -> p.withDialect(AbstractJSqlParser.Dialect.SQLSERVER))).getSelectBody();
656-
assertTrue(select.getSelectItems().get(0).getExpression() instanceof Column);
683+
for (AbstractJSqlParser.Dialect dialect : new AbstractJSqlParser.Dialect[] {
684+
AbstractJSqlParser.Dialect.SQLSERVER, AbstractJSqlParser.Dialect.SNOWFLAKE}) {
685+
PlainSelect select = (PlainSelect) ((Select) CCJSqlParserUtil.parse("SELECT \"abc\"",
686+
p -> p.withDialect(dialect))).getSelectBody();
687+
assertTrue(select.getSelectItems().get(0).getExpression() instanceof Column);
688+
}
657689
}
658690

659691
@Test
@@ -717,5 +749,14 @@ public void testAdjacentStringLiteralsWhitespace() throws Exception {
717749
p -> p.withDoubleQuotedStrings(true).withAdjacentStringLiterals(
718750
AbstractJSqlParser.AdjacentStringLiterals.WHITESPACE))
719751
.toString());
752+
// the BigQuery and Databricks presets carry it, the Snowflake preset
753+
// does not (no adjacent-literal concatenation documented)
754+
for (AbstractJSqlParser.Dialect dialect : new AbstractJSqlParser.Dialect[] {
755+
AbstractJSqlParser.Dialect.BIGQUERY, AbstractJSqlParser.Dialect.DATABRICKS}) {
756+
assertEquals("SELECT 'ab'", CCJSqlParserUtil.parse("SELECT 'a' 'b'",
757+
p -> p.withDialect(dialect)).toString());
758+
}
759+
assertEquals("SELECT 'a' 'b'", CCJSqlParserUtil.parse("SELECT 'a' 'b'",
760+
p -> p.withDialect(AbstractJSqlParser.Dialect.SNOWFLAKE)).toString());
720761
}
721762
}

0 commit comments

Comments
 (0)