diff --git a/src/main/java/com/alibaba/druid/DbType.java b/src/main/java/com/alibaba/druid/DbType.java index 744e067aab..e4be38f1c2 100644 --- a/src/main/java/com/alibaba/druid/DbType.java +++ b/src/main/java/com/alibaba/druid/DbType.java @@ -56,6 +56,8 @@ public enum DbType { */ gaussdb (1 << 38), + trino (1 << 39), + ingres (0), cloudscape (0), diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDateExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDateExpr.java index ead67b9984..0d3981d16f 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDateExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDateExpr.java @@ -206,6 +206,7 @@ public class SQLDateExpr extends SQLExprImpl implements SQLLiteralExpr, SQLValua public static long supportDbTypes = DbType.of(DbType.mysql , DbType.oracle , DbType.presto + , DbType.trino , DbType.postgresql , DbType.ads , DbType.hive diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDateTimeExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDateTimeExpr.java index b5371ddb6c..de3ce41376 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDateTimeExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLDateTimeExpr.java @@ -144,7 +144,12 @@ public class SQLDateTimeExpr extends SQLExprImpl implements SQLLiteralExpr, SQLV return Collections.emptyList(); } - public static long supportDbTypes = DbType.of(DbType.mysql, DbType.oracle, DbType.presto, DbType.postgresql); + public static long supportDbTypes = DbType.of(DbType.mysql + , DbType.oracle + , DbType.presto + , DbType.trino + , DbType.postgresql + ); public static boolean isSupport(DbType dbType) { return (dbType.mask & supportDbTypes) != 0; diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLExprUtils.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLExprUtils.java index 7436f777aa..af4b157c6b 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLExprUtils.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLExprUtils.java @@ -131,7 +131,7 @@ public class SQLExprUtils { if (quote == '`') { expr = new SQLIdentifierExpr(str); } else if (quote == '"') { - if (dbType == DbType.oracle || dbType == DbType.presto) { + if (dbType == DbType.oracle || dbType == DbType.presto || dbType == DbType.trino) { expr = new SQLIdentifierExpr(str); } else { diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLTimeExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLTimeExpr.java index 3c80b5caaf..40e74eaf46 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLTimeExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLTimeExpr.java @@ -145,7 +145,12 @@ public class SQLTimeExpr extends SQLExprImpl implements SQLLiteralExpr, SQLValua return Collections.emptyList(); } - public static long supportDbTypes = DbType.of(DbType.mysql, DbType.oracle, DbType.presto, DbType.postgresql); + public static long supportDbTypes = DbType.of(DbType.mysql + , DbType.oracle + , DbType.presto + , DbType.trino + , DbType.postgresql + ); public static boolean isSupport(DbType dbType) { return (dbType.mask & supportDbTypes) != 0; diff --git a/src/main/java/com/alibaba/druid/sql/builder/SQLFunctionBuilder.java b/src/main/java/com/alibaba/druid/sql/builder/SQLFunctionBuilder.java index 26760d833e..e701853dab 100644 --- a/src/main/java/com/alibaba/druid/sql/builder/SQLFunctionBuilder.java +++ b/src/main/java/com/alibaba/druid/sql/builder/SQLFunctionBuilder.java @@ -62,6 +62,7 @@ public class SQLFunctionBuilder { switch (dbType) { case ads: case presto: + case trino: case odps: return new SQLMethodInvokeExpr("coalesce", null, expr1, expr2); case oracle: diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java index 8e4833cd32..ca9af04753 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java @@ -2447,6 +2447,7 @@ public class MySqlStatementParser extends SQLStatementParser { case mysql: case ads: case presto: + case trino: Lexer.SavePoint mark = lexer.mark(); if (lexer.token() == Token.LPAREN) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/presto/parser/PrestoLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/presto/parser/PrestoLexer.java index 359ac9816e..bdadd47718 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/presto/parser/PrestoLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/presto/parser/PrestoLexer.java @@ -29,6 +29,7 @@ public class PrestoLexer extends Lexer { map.put("USING", Token.USING); map.put("MATCHED", Token.MATCHED); map.put("UPSERT", Token.UPSERT); + map.put("ARRAY", Token.ARRAY); DEFAULT_PHOENIX_KEYWORDS = new Keywords(map); } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java index 3877091c9f..262691fe11 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -1296,6 +1296,17 @@ public class SQLExprParser extends SQLParser { break; } throw new ParserException("ERROR. " + lexer.info()); + case ARRAY: { + SQLArrayExpr array = new SQLArrayExpr(); + array.setExpr(new SQLIdentifierExpr("ARRAY")); + lexer.nextToken(); + + accept(Token.LBRACKET); + this.exprList(array.getValues(), array); + accept(Token.RBRACKET); + sqlExpr = array; + break; + } default: throw new ParserException("ERROR. " + lexer.info()); } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLParserUtils.java b/src/main/java/com/alibaba/druid/sql/parser/SQLParserUtils.java index 567e40df00..681618bfa6 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLParserUtils.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLParserUtils.java @@ -130,6 +130,7 @@ public class SQLParserUtils { case hive: return new HiveStatementParser(sql, features); case presto: + case trino: return new PrestoStatementParser(sql); case ads: return new AdsStatementParser(sql); @@ -173,6 +174,7 @@ public class SQLParserUtils { case phoenix: return new PhoenixExprParser(sql, features); case presto: + case trino: return new PrestoExprParser(sql, features); case hive: return new HiveExprParser(sql, features); @@ -213,6 +215,7 @@ public class SQLParserUtils { case phoenix: return new PhoenixLexer(sql); case presto: + case trino: return new PrestoLexer(sql); case antspark: return new AntsparkLexer(sql); diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java index 3667f3a7c9..bcafeb4d36 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -4793,7 +4793,7 @@ public class SQLStatementParser extends SQLParser { } } - if (DbType.mysql == dbType || DbType.ads == dbType || DbType.presto == dbType) { + if (DbType.mysql == dbType || DbType.ads == dbType || DbType.presto == dbType || DbType.trino == dbType) { if (lexer.token == Token.LPAREN) { lexer.nextToken(); diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java index c91054f817..718ae0c77b 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -2314,6 +2314,16 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet this.indentCount--; } else if (parent instanceof SQLOpenStatement) { visit(subQuery); + } else if (parent instanceof SQLMethodInvokeExpr + && ((SQLMethodInvokeExpr) parent).getArguments().size() == 1 + && (((SQLMethodInvokeExpr) parent).methodNameHashCode64() == FnvHash.Constants.LATERAL + || ((SQLMethodInvokeExpr) parent).methodNameHashCode64() == FnvHash.Constants.ARRAY) + ) { + this.indentCount++; + println(); + visit(subQuery); + this.indentCount--; + println(); } else { print('('); this.indentCount++; @@ -4752,7 +4762,11 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } if (x.getDbProperties().size() > 0) { - if (dbType == DbType.mysql || dbType == DbType.presto || dbType == DbType.ads || dbType == DbType.mariadb) { + if (dbType == DbType.mysql + || dbType == DbType.presto + || dbType == DbType.trino + || dbType == DbType.ads + || dbType == DbType.mariadb) { println(); print0(ucase ? "WITH (" : "with ("); } else if (dbType == DbType.hive) { diff --git a/src/main/java/com/alibaba/druid/util/JdbcUtils.java b/src/main/java/com/alibaba/druid/util/JdbcUtils.java index 16e87cc278..7e8f57fb4b 100644 --- a/src/main/java/com/alibaba/druid/util/JdbcUtils.java +++ b/src/main/java/com/alibaba/druid/util/JdbcUtils.java @@ -626,6 +626,8 @@ public final class JdbcUtils implements JdbcConstants { return DbType.clickhouse; } else if (rawUrl.startsWith("jdbc:presto:")) { return DbType.presto; + } else if (rawUrl.startsWith("jdbc:trino:")) { + return DbType.trino; } else if (rawUrl.startsWith("jdbc:inspur:")) { return DbType.kdb; } else if (rawUrl.startsWith("jdbc:polardb")) { diff --git a/src/main/java/com/alibaba/druid/wall/WallFilter.java b/src/main/java/com/alibaba/druid/wall/WallFilter.java index 53b09e4a87..e7ca867f91 100644 --- a/src/main/java/com/alibaba/druid/wall/WallFilter.java +++ b/src/main/java/com/alibaba/druid/wall/WallFilter.java @@ -136,6 +136,7 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean { case mariadb: case h2: case presto: + case trino: if (config == null) { config = new WallConfig(MySqlWallProvider.DEFAULT_CONFIG_DIR); } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_292_lateral.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_292_lateral.java index 93b1b6e6ff..ddaa179554 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_292_lateral.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_292_lateral.java @@ -31,9 +31,9 @@ public class MySqlSelectTest_292_lateral extends MysqlTest { assertEquals("SELECT *\n" + "FROM t\n" + - "\tCROSS JOIN LATERAL((\n" + + "\tCROSS JOIN LATERAL(\n" + "\t\tVALUES (1)\n" + - "\t))", stmt.toString()); + "\t)", stmt.toString()); System.out.println(stmt.toString()); } @@ -46,9 +46,9 @@ public class MySqlSelectTest_292_lateral extends MysqlTest { assertEquals("SELECT *\n" + "FROM t\n" + - "\tFULL JOIN LATERAL((\n" + + "\tFULL JOIN LATERAL(\n" + "\t\tVALUES (1)\n" + - "\t)) ON true", stmt.toString()); + "\t) ON true", stmt.toString()); System.out.println(stmt.toString()); } @@ -60,9 +60,9 @@ public class MySqlSelectTest_292_lateral extends MysqlTest { .parseSingleStatement(sql, DbType.mysql); assertEquals("SELECT *\n" + - "FROM t, LATERAL((\n" + + "FROM t, LATERAL(\n" + "\t\tVALUES (1)\n" + - "\t)) AS a (x)", stmt.toString()); + "\t) AS a (x)", stmt.toString()); System.out.println(stmt.toString()); } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest62_json.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest62_json.java index ca68decca8..b76f2257ed 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest62_json.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest62_json.java @@ -33,13 +33,13 @@ public class PGSelectTest62_json extends TestCase { List stmtList = SQLUtils.parseStatements(sql, dbType); SQLStatement stmt = stmtList.get(0); - assertEquals("SELECT array_to_string(array((\n" + + assertEquals("SELECT array_to_string(array(\n" + "\t\tSELECT jsonb_array_elements('[{\"aa\":\"123\",\"bb\":\"123\"},{\"aa\":\"12356\",\"bb\":\"12356\"}]') ->> 'aa'\n" + - "\t)), ',') AS aa", SQLUtils.toPGString(stmt)); + "\t), ',') AS aa", SQLUtils.toPGString(stmt)); - assertEquals("select array_to_string(array((\n" + + assertEquals("select array_to_string(array(\n" + "\t\tselect jsonb_array_elements('[{\"aa\":\"123\",\"bb\":\"123\"},{\"aa\":\"12356\",\"bb\":\"12356\"}]') ->> 'aa'\n" + - "\t)), ',') as aa", SQLUtils.toPGString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + "\t), ',') as aa", SQLUtils.toPGString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); assertEquals(1, stmtList.size()); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest68.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest68.java index f62ae47a1d..847482e041 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest68.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest68.java @@ -53,13 +53,13 @@ public class PGSelectTest68 extends TestCase { "\t\tELSE -1\n" + "\tEND\n" + "FROM (\n" + - "\t(SELECT ARRAY_TO_STRING(ARRAY((\n" + + "\t(SELECT ARRAY_TO_STRING(ARRAY(\n" + "\t\t\tSELECT DISTINCT area_info\n" + "\t\t\tFROM md_mesh\n" + "\t\t\tWHERE mesh IN (\n" + "\t\t\t\tSELECT regexp_split_to_table(?, ',')\n" + "\t\t\t)\n" + - "\t\t)), ',') AS area_string)\n" + + "\t\t), ',') AS area_string)\n" + ") t", SQLUtils.toPGString(stmt)); assertEquals("select case \n" + @@ -69,13 +69,13 @@ public class PGSelectTest68 extends TestCase { "\t\telse -1\n" + "\tend\n" + "from (\n" + - "\t(select ARRAY_TO_STRING(ARRAY((\n" + + "\t(select ARRAY_TO_STRING(ARRAY(\n" + "\t\t\tselect distinct area_info\n" + "\t\t\tfrom md_mesh\n" + "\t\t\twhere mesh in (\n" + "\t\t\t\tselect regexp_split_to_table(?, ',')\n" + "\t\t\t)\n" + - "\t\t)), ',') as area_string)\n" + + "\t\t), ',') as area_string)\n" + ") t", SQLUtils.toPGString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); assertEquals(1, stmtList.size()); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/presto/PrestoSelect_0.java b/src/test/java/com/alibaba/druid/bvt/sql/presto/PrestoSelect_0.java new file mode 100644 index 0000000000..ff8c940f73 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/presto/PrestoSelect_0.java @@ -0,0 +1,190 @@ +package com.alibaba.druid.bvt.sql.presto; + +import com.alibaba.druid.DbType; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.parser.SQLParserUtils; +import com.alibaba.druid.sql.parser.SQLStatementParser; +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import org.junit.Test; + +import java.util.Map; + +import static org.junit.Assert.*; + +public class PrestoSelect_0 { + protected final DbType dbType = DbType.presto; + + @Test + public void test_with() throws Exception { + String sql = "WITH RECURSIVE t(n) AS (\n" + + " VALUES (1)\n" + + " UNION ALL\n" + + " SELECT n + 1 FROM t WHERE n < 4\n" + + ")\n" + + "SELECT sum(n) FROM t;"; + SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType); + SQLStatement stmt = parser.parseStatement(); + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType); + stmt.accept(visitor); + Map tableMap = visitor.getTables(); + assertTrue(tableMap.isEmpty()); + assertEquals("WITH RECURSIVE t (n) AS (\n" + + "\t\tVALUES (1)\n" + + "\t\tUNION ALL\n" + + "\t\tSELECT n + 1\n" + + "\t\tFROM t\n" + + "\t\tWHERE n < 4\n" + + "\t)\n" + + "SELECT sum(n)\n" + + "FROM t", stmt.toString()); + } + + @Test + public void test_unnest_0() throws Exception { + String sql = "SELECT student, score\n" + + "FROM tests\n" + + "CROSS JOIN UNNEST(scores) AS t (score);"; + SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType); + SQLStatement stmt = parser.parseStatement(); + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType); + stmt.accept(visitor); + Map tableMap = visitor.getTables(); + assertFalse(tableMap.isEmpty()); + assertEquals("SELECT student, score\n" + + "FROM tests\n" + + "\tCROSS JOIN UNNEST(scores) AS t (score)", stmt.toString()); + } + + @Test + public void test_unnest_1() throws Exception { + String sql = "SELECT numbers, animals, n, a\n" + + "FROM (\n" + + " VALUES\n" + + " (ARRAY[2, 5], ARRAY['dog', 'cat', 'bird']),\n" + + " (ARRAY[7, 8, 9], ARRAY['cow', 'pig'])\n" + + ") AS x (numbers, animals)\n" + + "CROSS JOIN UNNEST(numbers, animals) AS t (n, a);"; + SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType); + SQLStatement stmt = parser.parseStatement(); + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType); + stmt.accept(visitor); + Map tableMap = visitor.getTables(); + assertTrue(tableMap.isEmpty()); + assertEquals("SELECT numbers, animals, n, a\n" + + "FROM (VALUES (ARRAY[2, 5], ARRAY['dog', 'cat', 'bird']), (ARRAY[7, 8, 9], ARRAY['cow', 'pig'])) AS x (numbers, animals)\n" + + "\tCROSS JOIN UNNEST(numbers, animals) AS t (n, a)", stmt.toString()); + } + + @Test + public void test_unnest_2() throws Exception { + String sql = "SELECT numbers, n, a\n" + + "FROM (\n" + + " VALUES\n" + + " (ARRAY[2, 5]),\n" + + " (ARRAY[7, 8, 9])\n" + + ") AS x (numbers)\n" + + "CROSS JOIN UNNEST(numbers) WITH ORDINALITY AS t (n, a);"; + SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType); + SQLStatement stmt = parser.parseStatement(); + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType); + stmt.accept(visitor); + Map tableMap = visitor.getTables(); + assertTrue(tableMap.isEmpty()); + assertEquals("SELECT numbers, n, a\n" + + "FROM (VALUES (ARRAY[2, 5]), (ARRAY[7, 8, 9])) AS x (numbers)\n" + + "\tCROSS JOIN UNNEST(numbers) WITH ORDINALITY AS t (n, a)", stmt.toString()); + } + + @Test + public void test_lateral() throws Exception { + String sql = "SELECT name, x, y\n" + + "FROM nation\n" + + "CROSS JOIN LATERAL (SELECT name || ' :-' AS x)\n" + + "CROSS JOIN LATERAL (SELECT x || ')' AS y);"; + SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType); + SQLStatement stmt = parser.parseStatement(); + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType); + stmt.accept(visitor); + Map tableMap = visitor.getTables(); + assertFalse(tableMap.isEmpty()); + assertEquals("SELECT name, x, y\n" + + "FROM nation\n" + + "\tCROSS JOIN LATERAL(\n" + + "\t\tSELECT name || ' :-' AS x\n" + + "\t)\n" + + "\tCROSS JOIN LATERAL(\n" + + "\t\tSELECT x || ')' AS y\n" + + "\t)", stmt.toString()); + } + + @Test + public void test_exists() throws Exception { + String sql = "SELECT name\n" + + "FROM nation\n" + + "WHERE EXISTS (\n" + + " SELECT *\n" + + " FROM region\n" + + " WHERE region.regionkey = nation.regionkey\n" + + ");"; + SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType); + SQLStatement stmt = parser.parseStatement(); + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType); + stmt.accept(visitor); + Map tableMap = visitor.getTables(); + assertFalse(tableMap.isEmpty()); + assertEquals("SELECT name\n" + + "FROM nation\n" + + "WHERE EXISTS (\n" + + "\tSELECT *\n" + + "\tFROM region\n" + + "\tWHERE region.regionkey = nation.regionkey\n" + + ")", stmt.toString()); + } + + @Test + public void test_in() throws Exception { + String sql = "SELECT name\n" + + "FROM nation\n" + + "WHERE regionkey IN (\n" + + " SELECT regionkey\n" + + " FROM region\n" + + " WHERE name = 'AMERICA' OR name = 'AFRICA'\n" + + ");"; + SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType); + SQLStatement stmt = parser.parseStatement(); + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType); + stmt.accept(visitor); + Map tableMap = visitor.getTables(); + assertFalse(tableMap.isEmpty()); + assertEquals("SELECT name\n" + + "FROM nation\n" + + "WHERE regionkey IN (\n" + + "\tSELECT regionkey\n" + + "\tFROM region\n" + + "\tWHERE name = 'AMERICA'\n" + + "\t\tOR name = 'AFRICA'\n" + + ")", stmt.toString()); + } + + @Test + public void test_scalar() throws Exception { + String sql = "SELECT name\n" + + "FROM nation\n" + + "WHERE regionkey = (SELECT max(regionkey) FROM region);"; + SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType); + SQLStatement stmt = parser.parseStatement(); + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType); + stmt.accept(visitor); + Map tableMap = visitor.getTables(); + assertFalse(tableMap.isEmpty()); + assertEquals("SELECT name\n" + + "FROM nation\n" + + "WHERE regionkey = (\n" + + "\tSELECT max(regionkey)\n" + + "\tFROM region\n" + + ")", stmt.toString()); + } + +}