improved hive sql parser. for issue #2051

This commit is contained in:
wenshao
2017-10-20 16:16:28 +08:00
parent bb2bbd833c
commit 9167fc7cf4
8 changed files with 242 additions and 5 deletions
@@ -27,6 +27,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.MySqlUnique;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlTableIndex;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
import com.alibaba.druid.util.FnvHash;
import com.alibaba.druid.util.JdbcConstants;
import com.alibaba.druid.util.ListDG;
import com.alibaba.druid.util.lang.Consumer;
@@ -52,6 +53,7 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS
protected SQLName tablespace;
protected SQLPartitionBy partitioning;
protected SQLName storedAs;
public SQLCreateTableStatement(){
@@ -978,6 +980,17 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS
}
}
public SQLName getStoredAs() {
return storedAs;
}
public void setStoredAs(SQLName x) {
if (x != null) {
x.setParent(this);
}
this.storedAs = x;
}
public SQLCreateTableStatement clone() {
SQLCreateTableStatement x = new SQLCreateTableStatement(dbType);
cloneTo(x);
@@ -0,0 +1,127 @@
package com.alibaba.druid.sql.dialect.hive.parser;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.dialect.hive.stmt.HiveCreateTableStatement;
import com.alibaba.druid.sql.parser.*;
import com.alibaba.druid.util.FnvHash;
import com.alibaba.druid.util.JdbcConstants;
public class HiveCreateTableParser extends SQLCreateTableParser {
public HiveCreateTableParser(SQLExprParser exprParser) {
super(exprParser);
}
public SQLCreateTableStatement parseCreateTable(boolean acceptCreate) {
HiveCreateTableStatement stmt = newCreateStatement();
if (acceptCreate) {
if (lexer.hasComment() && lexer.isKeepComments()) {
stmt.addBeforeComment(lexer.readAndResetComments());
}
accept(Token.CREATE);
}
if (lexer.identifierEquals("GLOBAL")) {
lexer.nextToken();
if (lexer.identifierEquals("TEMPORARY")) {
lexer.nextToken();
stmt.setType(SQLCreateTableStatement.Type.GLOBAL_TEMPORARY);
} else {
throw new ParserException("syntax error " + lexer.info());
}
} else if (lexer.token() == Token.IDENTIFIER && lexer.stringVal().equalsIgnoreCase("LOCAL")) {
lexer.nextToken();
if (lexer.token() == Token.IDENTIFIER && lexer.stringVal().equalsIgnoreCase("TEMPORAY")) {
lexer.nextToken();
stmt.setType(SQLCreateTableStatement.Type.LOCAL_TEMPORARY);
} else {
throw new ParserException("syntax error. " + lexer.info());
}
}
accept(Token.TABLE);
if (lexer.token() == Token.IF || lexer.identifierEquals("IF")) {
lexer.nextToken();
accept(Token.NOT);
accept(Token.EXISTS);
stmt.setIfNotExiists(true);
}
stmt.setName(this.exprParser.name());
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
for (; ; ) {
Token token = lexer.token();
if (token == Token.IDENTIFIER
&& lexer.stringVal().equalsIgnoreCase("SUPPLEMENTAL")
&& JdbcConstants.ORACLE.equals(dbType)) {
this.parseCreateTableSupplementalLogingProps(stmt);
} else if (token == Token.IDENTIFIER //
|| token == Token.LITERAL_ALIAS) {
SQLColumnDefinition column = this.exprParser.parseColumn();
stmt.getTableElementList().add(column);
} else if (token == Token.PRIMARY //
|| token == Token.UNIQUE //
|| token == Token.CHECK //
|| token == Token.CONSTRAINT
|| token == Token.FOREIGN) {
SQLConstraint constraint = this.exprParser.parseConstaint();
constraint.setParent(stmt);
stmt.getTableElementList().add((SQLTableElement) constraint);
} else if (token == Token.TABLESPACE) {
throw new ParserException("TODO " + lexer.info());
} else {
SQLColumnDefinition column = this.exprParser.parseColumn();
stmt.getTableElementList().add(column);
}
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
if (lexer.token() == Token.RPAREN) { // compatible for sql server
break;
}
continue;
}
break;
}
accept(Token.RPAREN);
if (lexer.identifierEquals("INHERITS")) {
lexer.nextToken();
accept(Token.LPAREN);
SQLName inherits = this.exprParser.name();
stmt.setInherits(new SQLExprTableSource(inherits));
accept(Token.RPAREN);
}
}
if (lexer.identifierEquals(FnvHash.Constants.STORED)) {
lexer.nextToken();
accept(Token.AS);
SQLName name = this.exprParser.name();
stmt.setStoredAs(name);
}
if (lexer.token() == Token.AS) {
lexer.nextToken();
SQLSelect select = this.createSQLSelectParser().select();
stmt.setSelect(select);
}
return stmt;
}
protected HiveCreateTableStatement newCreateStatement() {
return new HiveCreateTableStatement();
}
}
@@ -20,10 +20,7 @@ import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
import com.alibaba.druid.sql.ast.statement.SQLReplaceStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.SQLParserFeature;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import com.alibaba.druid.sql.parser.Token;
import com.alibaba.druid.sql.parser.*;
import com.alibaba.druid.util.JdbcConstants;
public class HiveStatementParser extends SQLStatementParser {
@@ -75,4 +72,8 @@ public class HiveStatementParser extends SQLStatementParser {
return stmt;
}
public SQLCreateTableParser getSQLCreateTableParser() {
return new HiveCreateTableParser(this.exprParser);
}
}
@@ -0,0 +1,12 @@
package com.alibaba.druid.sql.dialect.hive.stmt;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
import com.alibaba.druid.util.JdbcConstants;
public class HiveCreateTableStatement extends SQLCreateTableStatement {
public HiveCreateTableStatement() {
this.dbType = JdbcConstants.HIVE;
}
}
@@ -15,6 +15,9 @@
*/
package com.alibaba.druid.sql.dialect.hive.visitor;
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;
import java.util.List;
@@ -31,5 +34,4 @@ public class HiveOutputVisitor extends SQLASTOutputVisitor implements HiveASTVis
public HiveOutputVisitor(Appendable appender, boolean parameterized) {
super(appender, parameterized);
}
}
@@ -15,6 +15,9 @@
*/
package com.alibaba.druid.sql.parser;
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
import com.alibaba.druid.sql.dialect.hive.stmt.HiveCreateTableStatement;
public class SQLParser {
protected final Lexer lexer;
protected String dbType;
@@ -323,4 +326,8 @@ public class SQLParser {
public final boolean isEnabled(SQLParserFeature feature) {
return lexer.isEnabled(feature);
}
protected SQLCreateTableStatement newCreateStatement() {
return new SQLCreateTableStatement(getDbType());
}
}
@@ -2537,6 +2537,12 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
print(')');
}
SQLName storedAs = x.getStoredAs();
if (storedAs != null) {
print0(ucase ? " STORE AS " : " store as ");
printExpr(storedAs);
}
SQLSelect select = x.getSelect();
if (printSelect && select != null) {
println();