diff --git a/src/main/java/com/alibaba/druid/sql/dialect/hive/ast/HiveStatementImpl.java b/src/main/java/com/alibaba/druid/sql/dialect/hive/ast/HiveStatementImpl.java new file mode 100644 index 0000000000..9e2a9dd1a1 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/hive/ast/HiveStatementImpl.java @@ -0,0 +1,7 @@ +package com.alibaba.druid.sql.dialect.hive.ast; + +public abstract class HiveStatementImpl extends HiveSQLObjectImpl implements HiveStatement { + + private static final long serialVersionUID = 1L; + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/hive/ast/stmt/HiveCreateTableStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/hive/ast/stmt/HiveCreateTableStatement.java index 0e0a2edc71..aaa217164a 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/hive/ast/stmt/HiveCreateTableStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/hive/ast/stmt/HiveCreateTableStatement.java @@ -60,7 +60,10 @@ public class HiveCreateTableStatement extends SQLCreateTableStatement implements @Override public void accept0(HiveASTVisitor visitor) { - + if (visitor.visit(this)) { + acceptChild(visitor, type); + } + visitor.endVisit(this); } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/hive/ast/stmt/HiveShowTablesStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/hive/ast/stmt/HiveShowTablesStatement.java new file mode 100644 index 0000000000..9232301b5c --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/hive/ast/stmt/HiveShowTablesStatement.java @@ -0,0 +1,29 @@ +package com.alibaba.druid.sql.dialect.hive.ast.stmt; + +import com.alibaba.druid.sql.ast.expr.SQLCharExpr; +import com.alibaba.druid.sql.dialect.hive.ast.HiveStatementImpl; +import com.alibaba.druid.sql.dialect.hive.visitor.HiveASTVisitor; + +public class HiveShowTablesStatement extends HiveStatementImpl { + + private static final long serialVersionUID = 1L; + private SQLCharExpr pattern; + + + public SQLCharExpr getPattern() { + return pattern; + } + + public void setPattern(SQLCharExpr pattern) { + this.pattern = pattern; + } + + @Override + public void accept0(HiveASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, pattern); + } + visitor.endVisit(this); + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveCreateTableParser.java b/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveCreateTableParser.java new file mode 100644 index 0000000000..5b51060a23 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveCreateTableParser.java @@ -0,0 +1,44 @@ +package com.alibaba.druid.sql.dialect.hive.parser; + +import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; +import com.alibaba.druid.sql.dialect.hive.ast.stmt.HiveCreateTableStatement; +import com.alibaba.druid.sql.dialect.hive.ast.stmt.HiveCreateTableStatement.PartitionedBy; +import com.alibaba.druid.sql.parser.Lexer; +import com.alibaba.druid.sql.parser.SQLCreateTableParser; +import com.alibaba.druid.sql.parser.Token; + +public class HiveCreateTableParser extends SQLCreateTableParser { + + public HiveCreateTableParser(String sql){ + super(new HiveLexer(sql)); + this.lexer.nextToken(); + } + + public HiveCreateTableParser(Lexer lexer){ + super(lexer); + } + + protected HiveCreateTableStatement newCreateStatement() { + return new HiveCreateTableStatement(); + } + + public SQLCreateTableStatement parseCrateTable(boolean acceptCreate) { + HiveCreateTableStatement stmt = (HiveCreateTableStatement) super.parseCrateTable(acceptCreate); + + if (lexer.token() == Token.PARTITIONED) { + lexer.nextToken(); + accept(Token.BY); + accept(Token.LPAREN); + + PartitionedBy partitionedBy = new PartitionedBy(); + partitionedBy.setName(exprParser.name().toString()); + partitionedBy.setType(exprParser.parseDataType()); + + accept(Token.RPAREN); + + stmt.setPartitionedBy(partitionedBy); + } + + return stmt; + } +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveLexer.java index 3b35eaf5d5..958886258c 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveLexer.java @@ -83,8 +83,9 @@ public class HiveLexer extends Lexer { map.put("ANY", Token.ANY); map.put("WITH", Token.WITH); - map.put("CURSOR", Token.CURSOR); - map.put("TOP", Token.TOP); + map.put("PARTITIONED", Token.PARTITIONED); + map.put("SHOW", Token.SHOW); + map.put("TABLES", Token.TABLES); DEFAULT_SQL_SERVER_KEYWORDS = new Keywords(map); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveStatementParser.java index 15b411cff0..36e1e95ea6 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveStatementParser.java @@ -1,8 +1,14 @@ package com.alibaba.druid.sql.dialect.hive.parser; -import com.alibaba.druid.sql.parser.Lexer; -import com.alibaba.druid.sql.parser.SQLStatementParser; +import java.util.List; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.expr.SQLCharExpr; +import com.alibaba.druid.sql.dialect.hive.ast.stmt.HiveShowTablesStatement; +import com.alibaba.druid.sql.parser.Lexer; +import com.alibaba.druid.sql.parser.ParserException; +import com.alibaba.druid.sql.parser.SQLStatementParser; +import com.alibaba.druid.sql.parser.Token; public class HiveStatementParser extends SQLStatementParser { @@ -15,4 +21,29 @@ public class HiveStatementParser extends SQLStatementParser { this.lexer.nextToken(); } + public HiveCreateTableParser getSQLCreateTableParser() { + return new HiveCreateTableParser(lexer); + } + + public boolean parseStatementListDialect(List statementList) { + if (lexer.token() == Token.SHOW) { + lexer.nextToken(); + + if (lexer.token() == Token.TABLES) { + lexer.nextToken(); + + HiveShowTablesStatement stmt = new HiveShowTablesStatement(); + + if (lexer.token() == Token.LITERAL_CHARS) { + stmt.setPattern((SQLCharExpr) exprParser.primary()); + } + + statementList.add(stmt); + return true; + } + + throw new ParserException("TODO " + lexer.token()); + } + return false; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveASTVisitor.java index c1d391ecb3..92fb760731 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveASTVisitor.java @@ -1,11 +1,20 @@ package com.alibaba.druid.sql.dialect.hive.visitor; import com.alibaba.druid.sql.dialect.hive.ast.stmt.HiveCreateTableStatement; +import com.alibaba.druid.sql.dialect.hive.ast.stmt.HiveShowTablesStatement; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public interface HiveASTVisitor extends SQLASTVisitor { - void endVisit(HiveCreateTableStatement x); + void endVisit(HiveShowTablesStatement x); + boolean visit(HiveShowTablesStatement x); + + void endVisit(HiveCreateTableStatement x); + boolean visit(HiveCreateTableStatement x); + + void endVisit(HiveCreateTableStatement.PartitionedBy x); + + boolean visit(HiveCreateTableStatement.PartitionedBy x); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveASTVisitorAdapter.java index 1aa4653e89..9652b56dfe 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveASTVisitorAdapter.java @@ -1,14 +1,14 @@ package com.alibaba.druid.sql.dialect.hive.visitor; import com.alibaba.druid.sql.dialect.hive.ast.stmt.HiveCreateTableStatement; +import com.alibaba.druid.sql.dialect.hive.ast.stmt.HiveShowTablesStatement; import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter; - public class HiveASTVisitorAdapter extends SQLASTVisitorAdapter implements HiveASTVisitor { @Override public void endVisit(HiveCreateTableStatement x) { - + } @Override @@ -16,4 +16,24 @@ public class HiveASTVisitorAdapter extends SQLASTVisitorAdapter implements HiveA return true; } + @Override + public void endVisit(HiveCreateTableStatement.PartitionedBy x) { + + } + + @Override + public boolean visit(HiveCreateTableStatement.PartitionedBy x) { + return true; + } + + @Override + public void endVisit(HiveShowTablesStatement x) { + + } + + @Override + public boolean visit(HiveShowTablesStatement x) { + return true; + } + } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveOutputVisitor.java index 674ed2fe35..e0d7a2c04a 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveOutputVisitor.java @@ -2,6 +2,8 @@ package com.alibaba.druid.sql.dialect.hive.visitor; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.dialect.hive.ast.stmt.HiveCreateTableStatement; +import com.alibaba.druid.sql.dialect.hive.ast.stmt.HiveCreateTableStatement.PartitionedBy; +import com.alibaba.druid.sql.dialect.hive.ast.stmt.HiveShowTablesStatement; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; public class HiveOutputVisitor extends SQLASTOutputVisitor implements HiveASTVisitor { @@ -18,6 +20,42 @@ public class HiveOutputVisitor extends SQLASTOutputVisitor implements HiveASTVis @Override public boolean visit(HiveCreateTableStatement x) { visit((SQLCreateTableStatement) x); + + if (x.getPartitionedBy() != null) { + println(); + x.getPartitionedBy().accept(this); + } + return false; + } + + @Override + public void endVisit(PartitionedBy x) { + + } + + @Override + public boolean visit(PartitionedBy x) { + print("PARTITIONED BY ("); + print(x.getName()); + print(" "); + x.getType().accept(this); + print(")"); + + return false; + } + + @Override + public void endVisit(HiveShowTablesStatement x) { + + } + + @Override + public boolean visit(HiveShowTablesStatement x) { + print("SHOW TABLES"); + if (x.getPattern() != null) { + print(" "); + x.getPattern().accept(this); + } return false; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveSchemaStatVisitor.java index 4ee83e710c..b536b66268 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveSchemaStatVisitor.java @@ -1,6 +1,8 @@ package com.alibaba.druid.sql.dialect.hive.visitor; +import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.dialect.hive.ast.stmt.HiveCreateTableStatement; +import com.alibaba.druid.sql.dialect.hive.ast.stmt.HiveShowTablesStatement; import com.alibaba.druid.sql.visitor.SchemaStatVisitor; public class HiveSchemaStatVisitor extends SchemaStatVisitor implements HiveASTVisitor { @@ -12,7 +14,26 @@ public class HiveSchemaStatVisitor extends SchemaStatVisitor implements HiveASTV @Override public boolean visit(HiveCreateTableStatement x) { + return visit((SQLCreateTableStatement) x); + } + + @Override + public void endVisit(HiveCreateTableStatement.PartitionedBy x) { + + } + + @Override + public boolean visit(HiveCreateTableStatement.PartitionedBy x) { return false; } + @Override + public void endVisit(HiveShowTablesStatement x) { + + } + + @Override + public boolean visit(HiveShowTablesStatement x) { + return false; + } } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLCreateTableParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLCreateTableParser.java index dbbfe87b0e..fccd6e20d9 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLCreateTableParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLCreateTableParser.java @@ -37,7 +37,7 @@ public class SQLCreateTableParser extends SQLDDLParser { accept(Token.CREATE); } - SQLCreateTableStatement createTable = new SQLCreateTableStatement(); + SQLCreateTableStatement createTable = newCreateStatement(); if (lexer.token() == Token.IDENTIFIER && lexer.stringVal().equalsIgnoreCase("GLOBAL")) { lexer.nextToken(); @@ -97,4 +97,8 @@ public class SQLCreateTableParser extends SQLDDLParser { return createTable; } + + protected SQLCreateTableStatement newCreateStatement() { + return new SQLCreateTableStatement(); + } } diff --git a/src/main/java/com/alibaba/druid/sql/parser/Token.java b/src/main/java/com/alibaba/druid/sql/parser/Token.java index 6088615b19..413807a546 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Token.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Token.java @@ -154,6 +154,11 @@ public enum Token { // transact-sql TOP("TOP"), + + // hive + PARTITIONED("PARTITIONED"), + SHOW("SHOW"), + TABLES("TABLES"), EOF, ERROR, diff --git a/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest2.java b/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest2.java new file mode 100644 index 0000000000..04e619ff09 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveCreateTableTest2.java @@ -0,0 +1,40 @@ +package com.alibaba.druid.bvt.sql.hive; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.hive.parser.HiveStatementParser; +import com.alibaba.druid.sql.dialect.hive.visitor.HiveSchemaStatVisitor; +import com.alibaba.druid.sql.hive.HiveTest; +import com.alibaba.druid.stat.TableStat; + +public class HiveCreateTableTest2 extends HiveTest { + + public void test_hive() throws Exception { + String sql = "CREATE TABLE invites (foo INT, bar STRING) PARTITIONED BY (ds STRING);"; + + HiveStatementParser parser = new HiveStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + System.out.println(output(statementList)); + + Assert.assertEquals(1, statementList.size()); + + HiveSchemaStatVisitor visitor = new HiveSchemaStatVisitor(); + statemen.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("invites"))); + + Assert.assertEquals(2, visitor.getColumns().size()); + + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("invites", "foo"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("invites", "bar"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveShowTableTest.java b/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveShowTableTest.java new file mode 100644 index 0000000000..a911cf1128 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveShowTableTest.java @@ -0,0 +1,40 @@ +package com.alibaba.druid.bvt.sql.hive; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.hive.parser.HiveStatementParser; +import com.alibaba.druid.sql.dialect.hive.visitor.HiveSchemaStatVisitor; +import com.alibaba.druid.sql.hive.HiveTest; +import com.alibaba.druid.stat.TableStat; + +public class HiveShowTableTest extends HiveTest { + + public void test_hive() throws Exception { + String sql = "SHOW TABLES"; + + HiveStatementParser parser = new HiveStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + System.out.println(output(statementList)); + + Assert.assertEquals(1, statementList.size()); + + HiveSchemaStatVisitor visitor = new HiveSchemaStatVisitor(); + statemen.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("invites"))); + + Assert.assertEquals(0, visitor.getColumns().size()); + +// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("invites", "foo"))); +// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("invites", "bar"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveShowTableTest2.java b/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveShowTableTest2.java new file mode 100644 index 0000000000..819e0df98e --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveShowTableTest2.java @@ -0,0 +1,39 @@ +package com.alibaba.druid.bvt.sql.hive; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.hive.parser.HiveStatementParser; +import com.alibaba.druid.sql.dialect.hive.visitor.HiveSchemaStatVisitor; +import com.alibaba.druid.sql.hive.HiveTest; + +public class HiveShowTableTest2 extends HiveTest { + + public void test_hive() throws Exception { + String sql = "SHOW TABLES '.*s';"; + + HiveStatementParser parser = new HiveStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + System.out.println(output(statementList)); + + Assert.assertEquals(1, statementList.size()); + + HiveSchemaStatVisitor visitor = new HiveSchemaStatVisitor(); + statemen.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("invites"))); + + Assert.assertEquals(0, visitor.getColumns().size()); + +// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("invites", "foo"))); +// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("invites", "bar"))); + } +}