improved sql parser.

This commit is contained in:
wenshao
2017-06-29 21:06:21 +08:00
parent f5cbc026b1
commit 2c52661fe9
11 changed files with 457 additions and 41 deletions
@@ -40,9 +40,12 @@ public class SQLCreateViewStatement extends SQLStatementImpl implements SQLDDLSt
protected SQLExprTableSource tableSource;
protected final List<Column> columns = new ArrayList<Column>();
protected final List<SQLTableElement> columns = new ArrayList<SQLTableElement>();
private Level with;
private boolean withCheckOption;
private boolean withCascaded;
private boolean withLocal;
private boolean withReadOnly;
private SQLLiteralExpr comment;
@@ -85,12 +88,36 @@ public class SQLCreateViewStatement extends SQLStatementImpl implements SQLDDLSt
this.tableSource = tableSource;
}
public Level getWith() {
return with;
public boolean isWithCheckOption() {
return withCheckOption;
}
public void setWith(Level with) {
this.with = with;
public void setWithCheckOption(boolean withCheckOption) {
this.withCheckOption = withCheckOption;
}
public boolean isWithCascaded() {
return withCascaded;
}
public void setWithCascaded(boolean withCascaded) {
this.withCascaded = withCascaded;
}
public boolean isWithLocal() {
return withLocal;
}
public void setWithLocal(boolean withLocal) {
this.withLocal = withLocal;
}
public boolean isWithReadOnly() {
return withReadOnly;
}
public void setWithReadOnly(boolean withReadOnly) {
this.withReadOnly = withReadOnly;
}
public SQLSelect getSubQuery() {
@@ -98,14 +125,17 @@ public class SQLCreateViewStatement extends SQLStatementImpl implements SQLDDLSt
}
public void setSubQuery(SQLSelect subQuery) {
if (subQuery != null) {
subQuery.setParent(this);
}
this.subQuery = subQuery;
}
public List<Column> getColumns() {
public List<SQLTableElement> getColumns() {
return columns;
}
public void addColumn(Column column) {
public void addColumn(SQLTableElement column) {
if (column != null) {
column.setParent(this);
}
@@ -22,12 +22,13 @@ import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.statement.SQLPrimaryKey;
import com.alibaba.druid.sql.ast.statement.SQLPrimaryKeyImpl;
import com.alibaba.druid.sql.ast.statement.SQLTableConstraint;
import com.alibaba.druid.sql.ast.statement.SQLTableElement;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class OraclePrimaryKey extends SQLPrimaryKeyImpl implements OracleConstraint, SQLPrimaryKey, SQLTableElement {
public class OraclePrimaryKey extends SQLPrimaryKeyImpl implements OracleConstraint, SQLPrimaryKey, SQLTableElement, SQLTableConstraint {
private OracleUsingIndexClause using;
private SQLName exceptionsInto;
@@ -1026,6 +1026,31 @@ public class OracleExprParser extends SQLExprParser {
OracleUsingIndexClause using = parseUsingIndex();
primaryKey.setUsing(using);
}
for (;;) {
if (lexer.token() == Token.ENABLE) {
lexer.nextToken();
primaryKey.setEnable(Boolean.TRUE);
} else if (lexer.token() == Token.DISABLE) {
lexer.nextToken();
primaryKey.setEnable(Boolean.FALSE);
} else if (identifierEquals("VALIDATE")) {
lexer.nextToken();
primaryKey.setValidate(Boolean.TRUE);
} else if (identifierEquals("NOVALIDATE")) {
lexer.nextToken();
primaryKey.setValidate(Boolean.FALSE);
} else if (identifierEquals("RELY")) {
lexer.nextToken();
primaryKey.setRely(Boolean.TRUE);
} else if (identifierEquals("NORELY")) {
lexer.nextToken();
primaryKey.setRely(Boolean.FALSE);
} else {
break;
}
}
return primaryKey;
}
@@ -1088,25 +1113,29 @@ public class OracleExprParser extends SQLExprParser {
public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) {
column = super.parseColumnRest(column);
if (lexer.token() == Token.ENABLE) {
lexer.nextToken();
column.setEnable(Boolean.TRUE);
} else if (lexer.token() == Token.ENABLE) {
lexer.nextToken();
column.setEnable(true);
} else if (identifierEquals("VALIDATE")) {
lexer.nextToken();
column.setValidate(Boolean.TRUE);
} else if (identifierEquals("NOVALIDATE")) {
lexer.nextToken();
column.setValidate(Boolean.FALSE);
} else if (identifierEquals("RELY")) {
lexer.nextToken();
column.setRely(Boolean.TRUE);
} else if (identifierEquals("NORELY")) {
lexer.nextToken();
column.setRely(Boolean.FALSE);
for (;;) {
if (lexer.token() == Token.ENABLE) {
lexer.nextToken();
column.setEnable(Boolean.TRUE);
} else if (lexer.token() == Token.DISABLE) {
lexer.nextToken();
column.setEnable(Boolean.FALSE);
} else if (identifierEquals("VALIDATE")) {
lexer.nextToken();
column.setValidate(Boolean.TRUE);
} else if (identifierEquals("NOVALIDATE")) {
lexer.nextToken();
column.setValidate(Boolean.FALSE);
} else if (identifierEquals("RELY")) {
lexer.nextToken();
column.setRely(Boolean.TRUE);
} else if (identifierEquals("NORELY")) {
lexer.nextToken();
column.setRely(Boolean.FALSE);
} else {
break;
}
}
return column;
@@ -236,7 +236,8 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
query.accept(this);
if (x.getRestriction() != null) {
print(' ');
println();
print("WITH ");
x.getRestriction().accept(this);
}
@@ -2006,8 +2007,24 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
printAndAccept(x.getColumns(), ", ");
print(')');
Boolean rely = x.getRely();
if (rely != null) {
if (rely.booleanValue()) {
print0(ucase ? " RELY" : " rely");
}
}
printConstraintState(x);
Boolean validate = x.getValidate();
if (validate != null) {
if (validate.booleanValue()) {
print0(ucase ? " VALIDATE" : " validate");
} else {
print0(ucase ? " NOVALIDATE" : " novalidate");
}
}
return false;
}
@@ -2024,8 +2041,9 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
x.getExceptionsInto().accept(this);
}
if (x.getEnable() != null) {
if (x.getEnable().booleanValue()) {
Boolean enable = x.getEnable();
if (enable != null) {
if (enable.booleanValue()) {
print0(ucase ? " ENABLE" : " enable");
} else {
print0(ucase ? " DIABLE" : " diable");
@@ -1998,6 +1998,7 @@ public class SQLExprParser extends SQLParser {
lexer.nextToken();
SQLColumnUniqueKey uk = new SQLColumnUniqueKey();
uk.setName(name);
column.addConstraint(uk);
return parseColumnRest(column);
}
@@ -2103,6 +2104,26 @@ public class SQLExprParser extends SQLParser {
exprList(unique.getColumns(), unique);
accept(Token.RPAREN);
if (lexer.token() == Token.DISABLE) {
lexer.nextToken();
unique.setEnable(false);
} else if (lexer.token() == Token.ENABLE) {
lexer.nextToken();
unique.setEnable(true);
} else if (identifierEquals("VALIDATE")) {
lexer.nextToken();
unique.setValidate(Boolean.TRUE);
} else if (identifierEquals("NOVALIDATE")) {
lexer.nextToken();
unique.setValidate(Boolean.FALSE);
} else if (identifierEquals("RELY")) {
lexer.nextToken();
unique.setRely(Boolean.TRUE);
} else if (identifierEquals("NORELY")) {
lexer.nextToken();
unique.setRely(Boolean.FALSE);
}
return unique;
}
@@ -2139,18 +2139,26 @@ public class SQLStatementParser extends SQLParser {
lexer.nextToken();
for (;;) {
SQLCreateViewStatement.Column column = new SQLCreateViewStatement.Column();
SQLExpr expr = this.exprParser.expr();
column.setExpr(expr);
if (lexer.token() == Token.COMMENT) {
lexer.nextToken();
column.setComment((SQLCharExpr) exprParser.primary());
if (lexer.token() == Token.CONSTRAINT) {
SQLTableConstraint constraint = (SQLTableConstraint) this.exprParser.parseConstaint();
createView.addColumn(constraint);
} else {
SQLColumnDefinition column = new SQLColumnDefinition();
SQLName expr = this.exprParser.name();
column.setName(expr);
this.exprParser.parseColumnRest(column);
if (lexer.token() == Token.COMMENT) {
lexer.nextToken();
column.setComment((SQLCharExpr) exprParser.primary());
}
column.setParent(createView);
createView.addColumn(column);
}
column.setParent(createView);
createView.addColumn(column);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
} else {
@@ -2171,6 +2179,28 @@ public class SQLStatementParser extends SQLParser {
SQLSelectParser selectParser = this.createSQLSelectParser();
createView.setSubQuery(selectParser.select());
if (lexer.token() == Token.WITH) {
lexer.nextToken();
if (identifierEquals("CASCADED")) {
createView.setWithCascaded(true);
lexer.nextToken();
} else if (identifierEquals("LOCAL")){
createView.setWithLocal(true);
lexer.nextToken();
} else if (identifierEquals("READ")) {
lexer.nextToken();
accept(Token.ONLY);
createView.setWithReadOnly(true);
}
if (lexer.token() == Token.CHECK) {
lexer.nextToken();
createView.setWithCheckOption(true);
}
}
return createView;
}
@@ -2542,6 +2542,12 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
println();
x.getSubQuery().accept(this);
if (x.isWithCheckOption()) {
println();
print0(ucase ? "WITH CHECK OPTION" : "with check option");
}
return false;
}
@@ -3227,7 +3233,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
print0(ucase ? "CREATE " : "create ");
if (x.isOrReplace()) {
print0(ucase ? "OR REPLEACE " : "or repleace ");
print0(ucase ? "OR REPLACE " : "or replace ");
}
print0(ucase ? "TRIGGER " : "trigger ");
@@ -0,0 +1,70 @@
/*
* 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.oracle.create;
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.parser.OracleStatementParser;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;
import com.alibaba.druid.stat.TableStat;
import com.alibaba.druid.util.JdbcConstants;
import java.util.List;
public class OracleCreateViewTest10_with_read_only extends OracleTest {
public void test_types() throws Exception {
String sql = //
"CREATE VIEW customer_ro (name, language, credit)\n" +
" AS SELECT cust_last_name, nls_language, credit_limit\n" +
" FROM customers\n" +
" WITH READ ONLY;";
OracleStatementParser parser = new OracleStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
SQLStatement stmt = statementList.get(0);
print(statementList);
assertEquals(1, statementList.size());
assertEquals("CREATE VIEW customer_ro (\n" +
"\tname, \n" +
"\tlanguage, \n" +
"\tcredit\n" +
")\n" +
"AS\n" +
"SELECT cust_last_name, nls_language, credit_limit\n" +
"FROM customers\n" +
"WITH READ ONLY;",//
SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE));
OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();
stmt.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());
System.out.println("orderBy : " + visitor.getOrderByColumns());
assertEquals(1, visitor.getTables().size());
assertEquals(3, visitor.getColumns().size());
assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "last_name")));
}
}
@@ -0,0 +1,67 @@
/*
* 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.oracle.create;
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.parser.OracleStatementParser;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;
import com.alibaba.druid.stat.TableStat;
import com.alibaba.druid.util.JdbcConstants;
import org.junit.Assert;
import java.util.List;
public class OracleCreateViewTest7 extends OracleTest {
public void test_types() throws Exception {
String sql = //
" CREATE VIEW emp_view AS \n" +
" SELECT last_name, salary*12 annual_salary\n" +
" FROM employees \n" +
" WHERE department_id = 20;";
OracleStatementParser parser = new OracleStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
SQLStatement stmt = statementList.get(0);
print(statementList);
Assert.assertEquals(1, statementList.size());
Assert.assertEquals("CREATE VIEW emp_view\n" +
"AS\n" +
"SELECT last_name, salary * 12 AS annual_salary\n" +
"FROM employees\n" +
"WHERE department_id = 20;",//
SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE));
OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();
stmt.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());
System.out.println("orderBy : " + visitor.getOrderByColumns());
Assert.assertEquals(1, visitor.getTables().size());
Assert.assertEquals(3, visitor.getColumns().size());
Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "last_name")));
}
}
@@ -0,0 +1,71 @@
/*
* 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.oracle.create;
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.parser.OracleStatementParser;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;
import com.alibaba.druid.stat.TableStat;
import com.alibaba.druid.util.JdbcConstants;
import org.junit.Assert;
import java.util.List;
public class OracleCreateViewTest8 extends OracleTest {
public void test_types() throws Exception {
String sql = //
" CREATE VIEW emp_sal (emp_id, last_name, \n" +
" email UNIQUE RELY DISABLE NOVALIDATE,\n" +
" CONSTRAINT id_pk PRIMARY KEY (emp_id) RELY DISABLE NOVALIDATE)\n" +
" AS SELECT employee_id, last_name, email FROM employees;";
OracleStatementParser parser = new OracleStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
SQLStatement stmt = statementList.get(0);
print(statementList);
Assert.assertEquals(1, statementList.size());
Assert.assertEquals("CREATE VIEW emp_sal (\n" +
"\temp_id, \n" +
"\tlast_name, \n" +
"\temail UNIQUE, \n" +
"\tCONSTRAINT id_pk PRIMARY KEY (emp_id) RELY DIABLE NOVALIDATE\n" +
")\n" +
"AS\n" +
"SELECT employee_id, last_name, email\n" +
"FROM employees;",//
SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE));
OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();
stmt.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());
System.out.println("orderBy : " + visitor.getOrderByColumns());
Assert.assertEquals(1, visitor.getTables().size());
Assert.assertEquals(3, visitor.getColumns().size());
Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "last_name")));
}
}
@@ -0,0 +1,73 @@
/*
* 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.oracle.create;
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.parser.OracleStatementParser;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;
import com.alibaba.druid.stat.TableStat;
import com.alibaba.druid.util.JdbcConstants;
import org.junit.Assert;
import java.util.List;
public class OracleCreateViewTest9_check_option extends OracleTest {
public void test_types() throws Exception {
String sql = //
" CREATE VIEW clerk AS\n" +
" SELECT employee_id, last_name, department_id, job_id \n" +
" FROM employees\n" +
" WHERE job_id = 'PU_CLERK' \n" +
" or job_id = 'SH_CLERK' \n" +
" or job_id = 'ST_CLERK'\n" +
" WITH CHECK OPTION;";
OracleStatementParser parser = new OracleStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
SQLStatement stmt = statementList.get(0);
print(statementList);
assertEquals(1, statementList.size());
assertEquals("CREATE VIEW clerk\n" +
"AS\n" +
"SELECT employee_id, last_name, department_id, job_id\n" +
"FROM employees\n" +
"WHERE job_id = 'PU_CLERK'\n" +
"\tOR job_id = 'SH_CLERK'\n" +
"\tOR job_id = 'ST_CLERK'\n" +
"WITH CHECK OPTION;",//
SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE));
OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();
stmt.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());
System.out.println("orderBy : " + visitor.getOrderByColumns());
assertEquals(1, visitor.getTables().size());
assertEquals(4, visitor.getColumns().size());
assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "last_name")));
}
}