diff --git a/src/main/java/com/alibaba/druid/sql/dialect/h2/parser/H2ExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/h2/parser/H2ExprParser.java index f19c9defbd..92d0ef7c79 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/h2/parser/H2ExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/h2/parser/H2ExprParser.java @@ -15,9 +15,14 @@ */ package com.alibaba.druid.sql.dialect.h2.parser; +import com.alibaba.druid.sql.ast.expr.SQLDefaultExpr; +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; +import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; +import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.SQLExprParser; import com.alibaba.druid.sql.parser.SQLParserFeature; +import com.alibaba.druid.sql.parser.Token; import com.alibaba.druid.util.FnvHash; import java.util.Arrays; @@ -50,7 +55,42 @@ public class H2ExprParser extends SQLExprParser { public H2ExprParser(Lexer lexer){ super(lexer); + dbType = lexer.getDbType(); this.aggregateFunctions = AGGREGATE_FUNCTIONS; this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES; } + + public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) { + column = super.parseColumnRest(column); + + if (lexer.identifierEquals(FnvHash.Constants.GENERATED)) { + lexer.nextToken(); + if (lexer.token() == Token.BY) { + lexer.nextToken(); + accept(Token.DEFAULT); + column.setGeneratedAlawsAs(new SQLDefaultExpr()); + } else { + acceptIdentifier("ALWAYS"); + column.setGeneratedAlawsAs(new SQLIdentifierExpr("ALWAYS")); + } + accept(Token.AS); + acceptIdentifier("IDENTITY"); + + SQLColumnDefinition.Identity identity = new SQLColumnDefinition.Identity(); + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + + SQLIntegerExpr seed = (SQLIntegerExpr) this.primary(); + accept(Token.COMMA); + SQLIntegerExpr increment = (SQLIntegerExpr) this.primary(); + accept(Token.RPAREN); + + identity.setSeed((Integer) seed.getNumber()); + identity.setIncrement((Integer) increment.getNumber()); + } + column.setIdentity(identity); + } + + return column; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/h2/parser/H2Lexer.java b/src/main/java/com/alibaba/druid/sql/dialect/h2/parser/H2Lexer.java index 4aad3ba518..e23a84453d 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/h2/parser/H2Lexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/h2/parser/H2Lexer.java @@ -15,6 +15,7 @@ */ package com.alibaba.druid.sql.dialect.h2.parser; +import com.alibaba.druid.DbType; import com.alibaba.druid.sql.parser.Keywords; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.SQLParserFeature; @@ -45,12 +46,12 @@ public class H2Lexer extends Lexer { } public H2Lexer(String input){ - super(input); + super(input, null, DbType.h2); super.keywods = DEFAULT_H2_KEYWORDS; } public H2Lexer(String input, SQLParserFeature... features){ - super(input); + super(input, null, DbType.h2); super.keywods = DEFAULT_H2_KEYWORDS; for (SQLParserFeature feature : features) { config(feature, true); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/h2/visitor/H2OutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/h2/visitor/H2OutputVisitor.java index 4a06d94086..8315bebdba 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/h2/visitor/H2OutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/h2/visitor/H2OutputVisitor.java @@ -26,7 +26,7 @@ import java.util.List; public class H2OutputVisitor extends SQLASTOutputVisitor implements H2ASTVisitor { public H2OutputVisitor(Appendable appender) { - super(appender); + super(appender, DbType.h2); } public H2OutputVisitor(Appendable appender, DbType dbType) { @@ -35,6 +35,7 @@ public class H2OutputVisitor extends SQLASTOutputVisitor implements H2ASTVisitor public H2OutputVisitor(Appendable appender, boolean parameterized) { super(appender, parameterized); + dbType = DbType.h2; } public boolean visit(SQLReplaceStatement x) { 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 17b88115fb..05eeb39180 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLCreateTableParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLCreateTableParser.java @@ -33,6 +33,7 @@ public class SQLCreateTableParser extends SQLDDLParser { public SQLCreateTableParser(SQLExprParser exprParser) { super(exprParser); + dbType = exprParser.dbType; } public SQLCreateTableStatement parseCreateTable() { @@ -51,6 +52,7 @@ public class SQLCreateTableParser extends SQLDDLParser { public SQLCreateTableStatement parseCreateTable(boolean acceptCreate) { SQLCreateTableStatement createTable = newCreateStatement(); + createTable.setDbType(getDbType()); if (acceptCreate) { if (lexer.hasComment() && lexer.isKeepComments()) { @@ -108,7 +110,7 @@ public class SQLCreateTableParser extends SQLDDLParser { createTable.getTableElementList().add(element); } else if (token == Token.IDENTIFIER // || token == Token.LITERAL_ALIAS) { - SQLColumnDefinition column = this.exprParser.parseColumn(); + SQLColumnDefinition column = this.exprParser.parseColumn(createTable); column.setParent(createTable); createTable.getTableElementList().add(column); } else if (token == Token.PRIMARY // 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 d2241f6c4f..3f291f5e59 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -3229,7 +3229,11 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet SQLColumnDefinition.Identity identity = x.getIdentity(); if (identity != null) { - print(' '); + if (dbType == DbType.h2) { + print0(ucase ? " AS " : " as "); + } else { + print(' '); + } identity.accept(this); } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/h2/H2_CreateTableTest_1.java b/src/test/java/com/alibaba/druid/bvt/sql/h2/H2_CreateTableTest_1.java new file mode 100644 index 0000000000..d9583b60b1 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/h2/H2_CreateTableTest_1.java @@ -0,0 +1,47 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.h2; + +import com.alibaba.druid.DbType; +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; +import org.junit.Assert; + +import java.util.List; + +public class H2_CreateTableTest_1 extends OracleTest { + + public void test_0() throws Exception { + String sql = // + "CREATE TABLE tutorials_tbl ( \n" + + " id bigint generated by default as identity, \n" + + " title VARCHAR(50) NOT NULL, \n" + + " author VARCHAR(20) NOT NULL, \n" + + " submission_date DATE \n" + + ");"; // + + SQLStatement stmt = SQLUtils.parseSingleStatement(sql, DbType.h2); + assertEquals("CREATE TABLE tutorials_tbl (\n" + + "\tid bigint GENERATED ALWAYS AS DEFAULT AS IDENTITY,\n" + + "\ttitle VARCHAR(50) NOT NULL,\n" + + "\tauthor VARCHAR(20) NOT NULL,\n" + + "\tsubmission_date DATE\n" + + ");", stmt.toString()); + } +}