improved sql parser.

This commit is contained in:
wenshao
2017-07-23 16:44:43 +08:00
parent 82fe08109f
commit 6829a23bce
41 changed files with 1183 additions and 514 deletions
@@ -185,6 +185,12 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
}
public void configFromPropety(Properties properties) {
{
String property = properties.getProperty("druid.name");
if (property != null) {
this.setName(property);
}
}
{
String property = properties.getProperty("druid.url");
if (property != null) {
@@ -96,7 +96,7 @@ public class MySqlExceptionSorter implements ExceptionSorter {
Throwable cause = e.getCause();
for (int i = 0; i < 5 && cause != null; ++i) {
if (cause instanceof SocketTimeoutException || cause instanceof IOException) {
if (cause instanceof SocketTimeoutException) {
return true;
}
@@ -443,7 +443,7 @@ public class PagerUtils {
countSelectQuery.setFrom(fromSubquery);
SQLSelect countSelect = new SQLSelect(countSelectQuery);
SQLSelectStatement countStmt = new SQLSelectStatement(countSelect);
SQLSelectStatement countStmt = new SQLSelectStatement(countSelect, dbType);
return SQLUtils.toSQLString(countStmt, dbType);
}
@@ -301,7 +301,7 @@ public class SQLUtils {
if (j != 0) {
visitor.println();
}
visitor.print(comment);
visitor.printComment(comment);
}
}
@@ -317,7 +317,8 @@ public class SQLUtils {
List<String> comments = stmt.getBeforeCommentsDirect();
if (comments != null){
for(String comment : comments) {
visitor.println(comment);
visitor.printComment(comment);
visitor.println();
}
}
}
@@ -331,7 +332,7 @@ public class SQLUtils {
if (j != 0) {
visitor.println();
}
visitor.print(comment);
visitor.printComment(comment);
}
}
}
@@ -15,6 +15,8 @@
*/
package com.alibaba.druid.sql.ast;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
@@ -50,10 +52,18 @@ public class SQLLimit extends SQLObjectImpl {
this.rowCount = rowCount;
}
public void setRowCount(int rowCount) {
this.setRowCount(new SQLIntegerExpr(rowCount));
}
public SQLExpr getOffset() {
return offset;
}
public void setOffset(int offset) {
this.setOffset(new SQLIntegerExpr(offset));
}
public void setOffset(SQLExpr offset) {
if (offset != null) {
offset.setParent(this);
@@ -53,6 +53,19 @@ public class SQLBinaryOpExpr extends SQLExprImpl implements SQLReplaceable, Seri
setLeft(left);
setRight(right);
this.operator = operator;
if (dbType == null) {
if (left instanceof SQLBinaryOpExpr) {
dbType = ((SQLBinaryOpExpr) left).dbType;
}
}
if (dbType == null) {
if (right instanceof SQLBinaryOpExpr) {
dbType = ((SQLBinaryOpExpr) right).dbType;
}
}
this.dbType = dbType;
}
@@ -392,4 +405,16 @@ public class SQLBinaryOpExpr extends SQLExprImpl implements SQLReplaceable, Seri
return false;
}
public SQLExpr other(SQLExpr x) {
if (x == left) {
return right;
}
if (x == right) {
return left;
}
return null;
}
}
@@ -19,6 +19,7 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLExprImpl;
import com.alibaba.druid.sql.ast.SQLReplaceable;
@@ -185,4 +186,28 @@ public class SQLMethodInvokeExpr extends SQLExprImpl implements SQLReplaceable,
}
return false;
}
public boolean match(String owner, String function) {
if (function == null) {
return false;
}
if (!SQLUtils.nameEquals(function, methodName)) {
return false;
}
if (owner == null && this.owner == null) {
return true;
}
if (owner == null || this.owner == null) {
return false;
}
if (this.owner instanceof SQLIdentifierExpr) {
return SQLUtils.nameEquals(((SQLIdentifierExpr) this.owner).name, owner);
}
return false;
}
}
@@ -18,6 +18,7 @@ package com.alibaba.druid.sql.ast.statement;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLObjectImpl;
@@ -58,6 +59,20 @@ public class SQLCreateViewStatement extends SQLStatementImpl implements SQLDDLSt
super(dbType);
}
public String computeName() {
if (tableSource == null) {
return null;
}
SQLExpr expr = tableSource.getExpr();
if (expr instanceof SQLName) {
String name = ((SQLName) expr).getSimpleName();
return SQLUtils.normalize(name);
}
return null;
}
public boolean isOrReplace() {
return orReplace;
}
@@ -79,22 +79,22 @@ public class SQLJoinTableSource extends SQLTableSourceImpl implements SQLReplace
this.left = left;
}
public void setLeft(String tableName) {
public void setLeft(String tableName, String alias) {
SQLExprTableSource tableSource;
if (tableName == null || tableName.length() == 0) {
tableSource = null;
} else {
tableSource = new SQLExprTableSource(new SQLIdentifierExpr(tableName));
tableSource = new SQLExprTableSource(new SQLIdentifierExpr(tableName), alias);
}
this.setLeft(tableSource);
}
public void setRight(String tableName) {
public void setRight(String tableName, String alias) {
SQLExprTableSource tableSource;
if (tableName == null || tableName.length() == 0) {
tableSource = null;
} else {
tableSource = new SQLExprTableSource(new SQLIdentifierExpr(tableName));
tableSource = new SQLExprTableSource(new SQLIdentifierExpr(tableName), alias);
}
this.setRight(tableSource);
}
@@ -228,4 +228,41 @@ public class SQLJoinTableSource extends SQLTableSourceImpl implements SQLReplace
cloneTo(x);
return x;
}
public void reverse() {
SQLTableSource temp = left;
left = right;
right = temp;
if (left instanceof SQLJoinTableSource) {
((SQLJoinTableSource) left).reverse();
}
if (right instanceof SQLJoinTableSource) {
((SQLJoinTableSource) right).reverse();
}
}
/**
* a inner_join (b inner_join c) -> a inner_join b innre_join c
*/
public void rearrangement() {
if (right instanceof SQLJoinTableSource) {
SQLJoinTableSource rightJoin = (SQLJoinTableSource) right;
SQLTableSource a = left;
SQLTableSource b = rightJoin.getLeft();
SQLTableSource c = rightJoin.getRight();
SQLExpr on_ab = condition;
SQLExpr on_bc = rightJoin.condition;
setLeft(rightJoin);
rightJoin.setLeft(a);
rightJoin.setRight(b);
rightJoin.setCondition(on_ab);
setRight(c);
setCondition(on_bc);
}
}
}
@@ -162,12 +162,12 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery
this.from = from;
}
public void setFrom(String tableName) {
public void setFrom(String tableName, String alias) {
SQLExprTableSource from;
if (tableName == null || tableName.length() == 0) {
from = null;
} else {
from = new SQLExprTableSource(new SQLIdentifierExpr(tableName));
from = new SQLExprTableSource(new SQLIdentifierExpr(tableName), alias);
}
this.setFrom(from);
}
@@ -250,45 +250,51 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
printSelectList(x.getSelectList());
if (x.getInto() != null) {
SQLExprTableSource into = x.getInto();
if (into != null) {
println();
print0(ucase ? "INTO " : "into ");
x.getInto().accept(this);
into.accept(this);
}
if (x.getFrom() != null) {
SQLTableSource form = x.getFrom();
if (form != null) {
println();
print0(ucase ? "FROM " : "from ");
x.getFrom().accept(this);
form.accept(this);
}
if (x.getWhere() != null) {
SQLExpr where = x.getWhere();
if (where != null) {
println();
print0(ucase ? "WHERE " : "where ");
x.getWhere().setParent(x);
x.getWhere().accept(this);
where.accept(this);
}
printHierarchical(x);
if (x.getGroupBy() != null) {
SQLSelectGroupByClause groupBy = x.getGroupBy();
if (groupBy != null) {
println();
x.getGroupBy().accept(this);
groupBy.accept(this);
}
if (x.getOrderBy() != null) {
SQLOrderBy orderBy = x.getOrderBy();
if (orderBy != null) {
println();
x.getOrderBy().accept(this);
orderBy.accept(this);
}
if (x.getLimit() != null) {
SQLLimit limit = x.getLimit();
if (limit != null) {
println();
x.getLimit().accept(this);
limit.accept(this);
}
if (x.getProcedureName() != null) {
SQLName procedureName = x.getProcedureName();
if (procedureName != null) {
print0(ucase ? " PROCEDURE " : " procedure ");
x.getProcedureName().accept(this);
procedureName.accept(this);
if (!x.getProcedureArgumentList().isEmpty()) {
print('(');
printAndAccept(x.getProcedureArgumentList(), ", ");
@@ -16,17 +16,21 @@
package com.alibaba.druid.sql.dialect.mysql.visitor.transform;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectJoin;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectSubqueryTableSource;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableReference;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter;
import oracle.sql.SQLName;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* @author wenshao[szujobs@hotmail.com]
@@ -34,6 +38,9 @@ import java.util.List;
public class FromSubqueryResolver extends OracleASTVisitorAdapter {
private final List<SQLStatement> targetList;
private final String viewName;
private final Map<String, String> mappings = new LinkedHashMap<String, String>();
private int viewNameSeed = 1;
public FromSubqueryResolver(List<SQLStatement> targetList, String viewName) {
this.targetList = targetList;
@@ -50,13 +57,13 @@ public class FromSubqueryResolver extends OracleASTVisitorAdapter {
SQLObject parent = x.getParent();
if(parent instanceof SQLSelectQueryBlock) {
SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) parent;
queryBlock.setFrom(subViewName);
queryBlock.setFrom(subViewName, x.getAlias());
} else if(parent instanceof SQLJoinTableSource) {
SQLJoinTableSource join = (SQLJoinTableSource) parent;
if (join.getLeft() == x) {
join.setLeft(subViewName);
join.setLeft(subViewName, x.getAlias());
} else if (join.getRight() == x) {
join.setRight(subViewName);
join.setRight(subViewName, x.getAlias());
}
}
@@ -64,7 +71,6 @@ public class FromSubqueryResolver extends OracleASTVisitorAdapter {
stmt.setName(generateSubViewName());
SQLSelect select = x.getSelect();
stmt.setSubQuery(select);
@@ -75,6 +81,23 @@ public class FromSubqueryResolver extends OracleASTVisitorAdapter {
return false;
}
public boolean visit(SQLExprTableSource x) {
SQLExpr expr = x.getExpr();
if (expr instanceof SQLIdentifierExpr) {
SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr;
String ident = identifierExpr.getName();
String mappingIdent = mappings.get(ident);
if (mappingIdent != null) {
identifierExpr.setName(mappingIdent);
}
}
return false;
}
public boolean visit(OracleSelectTableReference x) {
return visit((SQLExprTableSource) x);
}
private String generateSubViewName() {
return this.viewName + "_" + targetList.size();
}
@@ -86,6 +109,28 @@ public class FromSubqueryResolver extends OracleASTVisitorAdapter {
String viewName = SQLUtils.normalize(stmt.getName().getSimpleName());
FromSubqueryResolver visitor = new FromSubqueryResolver(targetList, viewName);
SQLWithSubqueryClause withSubqueryClause = stmt.getSubQuery().getWithSubQuery();
if (withSubqueryClause != null) {
stmt.getSubQuery().setWithSubQuery(null);
for (SQLWithSubqueryClause.Entry entry : withSubqueryClause.getEntries()) {
String entryName = entry.getName().getName();
SQLCreateViewStatement entryStmt = new SQLCreateViewStatement();
entryStmt.setDbType(stmt.getDbType());
String entryViewName = visitor.generateSubViewName();
entryStmt.setName(entryViewName);
entryStmt.setSubQuery(entry.getSubQuery());
visitor.targetList.add(0, entryStmt);
visitor.mappings.put(entryName, entryViewName);
entryStmt.accept(visitor);
}
}
stmt.accept(visitor);
String dbType = stmt.getDbType();
@@ -95,7 +140,6 @@ public class FromSubqueryResolver extends OracleASTVisitorAdapter {
targetStmt.setAfterSemi(true);
}
return targetList;
}
}
@@ -456,22 +456,23 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis
printSelectList(x.getSelectList());
if (x.getFrom() != null) {
SQLTableSource from = x.getFrom();
if (from != null) {
println();
print0(ucase ? "FROM " : "from ");
x.getFrom().accept(this);
from.accept(this);
}
if (x.getWhere() != null) {
SQLExpr where = x.getWhere();
if (where != null) {
println();
print0(ucase ? "WHERE " : "where ");
if (x.getWhere().hasBeforeComment() && isPrettyFormat()) {
if (where.hasBeforeComment() && isPrettyFormat()) {
printlnComments(x.getWhere().getBeforeCommentsDirect());
}
x.getWhere().setParent(x);
x.getWhere().accept(this);
if (x.getWhere().hasAfterComment() && isPrettyFormat()) {
where.accept(this);
if (where.hasAfterComment() && isPrettyFormat()) {
print(' ');
printlnComment(x.getWhere().getAfterCommentsDirect());
}
@@ -20,6 +20,7 @@ import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
@@ -35,6 +36,9 @@ public class OracleSelectJoin extends SQLJoinTableSource implements OracleSelect
}
public OracleSelectJoin(SQLTableSource left, JoinType joinType, SQLTableSource right, SQLExpr condition){
super (left, joinType, right, condition);
}
public OracleSelectPivotBase getPivot() {
return pivot;
@@ -241,6 +241,8 @@ public class OracleExprParser extends SQLExprParser {
}
accept(Token.RPAREN);
// } else if (lexer.token() == Token.RPAREN) {
// return charType;
} else if (restrict) {
accept(Token.LPAREN);
}
@@ -1218,6 +1220,12 @@ public class OracleExprParser extends SQLExprParser {
continue;
}
if (lexer.token() == Token.CACHE) {
lexer.nextToken();
clause.setCache(true);
continue;
}
if (lexer.token() == Token.KEEP_DUPLICATES) {
lexer.nextToken();
clause.setKeepDuplicate(true);
@@ -142,7 +142,7 @@ public class OracleStatementParser extends SQLStatementParser {
}
if (lexer.token() == Token.WITH) {
SQLSelectStatement stmt = new SQLSelectStatement(this.createSQLSelectParser().select());
SQLSelectStatement stmt = new SQLSelectStatement(this.createSQLSelectParser().select(), dbType);
stmt.setParent(parent);
statementList.add(stmt);
continue;
@@ -118,42 +118,42 @@ public class SQLExprParser extends SQLParser {
if (token == Token.CARET) {
lexer.nextToken();
SQLExpr rightExp = primary();
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BitwiseXor, rightExp, getDbType());
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BitwiseXor, rightExp, dbType);
expr = bitXorRest(expr);
} else if (token == Token.SUBGT) {
lexer.nextToken();
SQLExpr rightExp = primary();
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.SubGt, rightExp, getDbType());
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.SubGt, rightExp, dbType);
expr = bitXorRest(expr);
} else if (token == Token.SUBGTGT) {
lexer.nextToken();
SQLExpr rightExp = primary();
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.SubGtGt, rightExp, getDbType());
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.SubGtGt, rightExp, dbType);
expr = bitXorRest(expr);
} else if (token == Token.POUNDGT) {
lexer.nextToken();
SQLExpr rightExp = primary();
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.PoundGt, rightExp, getDbType());
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.PoundGt, rightExp, dbType);
expr = bitXorRest(expr);
} else if (token == Token.POUNDGTGT) {
lexer.nextToken();
SQLExpr rightExp = primary();
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.PoundGtGt, rightExp, getDbType());
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.PoundGtGt, rightExp, dbType);
expr = bitXorRest(expr);
} else if (token == Token.QUESQUES) {
lexer.nextToken();
SQLExpr rightExp = primary();
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.QuesQues, rightExp, getDbType());
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.QuesQues, rightExp, dbType);
expr = bitXorRest(expr);
} else if (token == Token.QUESBAR) {
lexer.nextToken();
SQLExpr rightExp = primary();
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.QuesBar, rightExp, getDbType());
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.QuesBar, rightExp, dbType);
expr = bitXorRest(expr);
} else if (token == Token.QUESAMP) {
lexer.nextToken();
SQLExpr rightExp = primary();
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.QuesAmp, rightExp, getDbType());
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.QuesAmp, rightExp, dbType);
expr = bitXorRest(expr);
}
@@ -462,7 +462,7 @@ public class SQLExprParser extends SQLParser {
SQLCastExpr cast = new SQLCastExpr();
cast.setExpr(expr());
accept(Token.AS);
cast.setDataType(parseDataType());
cast.setDataType(parseDataType(false));
accept(Token.RPAREN);
sqlExpr = cast;
@@ -1798,8 +1798,8 @@ public class SQLExprParser extends SQLParser {
}
public SQLDataType parseDataType(boolean restrict) {
if (lexer.token() == Token.DEFAULT || lexer.token() == Token.NOT || lexer.token() == Token.NULL) {
Token token = lexer.token();
if (token == Token.DEFAULT || token == Token.NOT || token == Token.NULL) {
return null;
}
@@ -0,0 +1,372 @@
/*
* 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.sql.repository;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr;
import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTableStatement;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentSkipListMap;
/**
* Created by wenshao on 21/07/2017.
*/
public class Schema {
private String name;
protected final Map<String, SchemaObject> objects = new ConcurrentSkipListMap<String, SchemaObject>();
private final Map<String, SchemaObject> functions = new ConcurrentSkipListMap<String, SchemaObject>();
private final Schema.SchemaVisitor visitor = new Schema.SchemaVisitor();
private SchemaRepository repository;
public Schema(SchemaRepository repository) {
this.repository = repository;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public SchemaObject findTable(String tableName) {
String lowerName = tableName.toLowerCase();
SchemaObject object = objects.get(lowerName);
if (object != null && object.getType() == SchemaObjectType.Table) {
return object;
}
return null;
}
public SchemaObject findTableOrView(String tableName) {
String lowerName = tableName.toLowerCase();
SchemaObject object = objects.get(lowerName);
if (object == null) {
return null;
}
SchemaObjectType type = object.getType();
if (type == SchemaObjectType.Table || type == SchemaObjectType.View) {
return object;
}
return null;
}
public SchemaObject findFunction(String functionName) {
String lowerName = functionName.toLowerCase();
return functions.get(lowerName);
}
public void acceptDDL(String ddl, String dbType) {
List<SQLStatement> stmtList = SQLUtils.parseStatements(ddl, dbType);
for (SQLStatement stmt : stmtList) {
accept(stmt);
}
}
public void accept(SQLStatement stmt) {
stmt.accept(visitor);
}
public boolean isSequence(String name) {
SchemaObject object = objects.get(name);
return object != null
&& object.getType() == SchemaObjectType.Sequence;
}
public class SchemaVisitor extends OracleASTVisitorAdapter {
public boolean visit(SQLDropSequenceStatement x) {
String name = x.getName().getSimpleName();
objects.remove(name);
return false;
}
public boolean visit(SQLCreateSequenceStatement x) {
String name = x.getName().getSimpleName();
SchemaObject object = new SchemaObjectImpl(name, SchemaObjectType.Sequence);
objects.put(name.toLowerCase(), object);
return false;
}
public boolean visit(OracleCreateTableStatement x) {
visit((SQLCreateTableStatement) x);
return false;
}
public boolean visit(SQLCreateTableStatement x) {
String name = x.computeName();
SchemaObject object = new SchemaObjectImpl(name, SchemaObjectType.Table, x);
String name_lower = name.toLowerCase();
if (objects.containsKey(name_lower)) {
return false;
}
objects.put(name_lower, object);
return false;
}
public boolean visit(SQLCreateViewStatement x) {
String name = x.computeName();
SchemaObject object = new SchemaObjectImpl(name, SchemaObjectType.View, x);
String name_lower = name.toLowerCase();
if (objects.containsKey(name_lower)) {
return false;
}
objects.put(name_lower, object);
return false;
}
public boolean visit(SQLCreateIndexStatement x) {
String name = x.getName().getSimpleName();
SchemaObject object = new SchemaObjectImpl(name, SchemaObjectType.Index);
objects.put(name.toLowerCase(), object);
return false;
}
public boolean visit(SQLCreateFunctionStatement x) {
String name = x.getName().getSimpleName();
SchemaObject object = new SchemaObjectImpl(name, SchemaObjectType.Function, x);
functions.put(name.toLowerCase(), object);
return false;
}
}
public SchemaObject findTable(SQLTableSource tableSource, String alias) {
if (tableSource instanceof SQLExprTableSource) {
if (alias.equalsIgnoreCase(tableSource.computeAlias())) {
SQLExprTableSource exprTableSource = (SQLExprTableSource) tableSource;
SchemaObject tableObject = exprTableSource.getSchemaObject();
if (tableObject != null) {
return tableObject;
}
SQLExpr expr = exprTableSource.getExpr();
if (expr instanceof SQLIdentifierExpr) {
String tableName = ((SQLIdentifierExpr) expr).getName();
tableObject = findTable(tableName);
if (tableObject != null) {
exprTableSource.setSchemaObject(tableObject);
}
return tableObject;
}
if (expr instanceof SQLPropertyExpr) {
String tableName = ((SQLPropertyExpr) expr).getName();
tableObject = findTable(tableName);
if (tableObject != null) {
exprTableSource.setSchemaObject(tableObject);
}
return tableObject;
}
}
return null;
}
if (tableSource instanceof SQLJoinTableSource) {
SQLJoinTableSource join = (SQLJoinTableSource) tableSource;
SQLTableSource left = join.getLeft();
SchemaObject tableObject = findTable(left, alias);
if (tableObject != null) {
return tableObject;
}
SQLTableSource right = join.getRight();
tableObject = findTable(right, alias);
return tableObject;
}
return null;
}
public SQLColumnDefinition findColumn(SQLTableSource tableSource, SQLSelectItem selectItem) {
if (selectItem == null) {
return null;
}
return findColumn(tableSource, selectItem.getExpr());
}
public SQLColumnDefinition findColumn(SQLTableSource tableSource, SQLExpr expr) {
SchemaObject object = findTable(tableSource, expr);
if (object != null) {
if (expr instanceof SQLAggregateExpr) {
SQLAggregateExpr aggregateExpr = (SQLAggregateExpr) expr;
String function = aggregateExpr.getMethodName();
if ("min".equalsIgnoreCase(function)
|| "max".equalsIgnoreCase(function)) {
SQLExpr arg = aggregateExpr.getArguments().get(0);
expr = arg;
}
}
if (expr instanceof SQLName) {
return object.findColumn(((SQLName) expr).getSimpleName());
}
}
return null;
}
public SchemaObject findTable(SQLTableSource tableSource, SQLSelectItem selectItem) {
if (selectItem == null) {
return null;
}
return findTable(tableSource, selectItem.getExpr());
}
public SchemaObject findTable(SQLTableSource tableSource, SQLExpr expr) {
if (expr instanceof SQLAggregateExpr) {
SQLAggregateExpr aggregateExpr = (SQLAggregateExpr) expr;
String function = aggregateExpr.getMethodName();
if ("min".equalsIgnoreCase(function)
|| "max".equalsIgnoreCase(function)) {
SQLExpr arg = aggregateExpr.getArguments().get(0);
return findTable(tableSource, arg);
}
}
if (expr instanceof SQLPropertyExpr) {
String ownerName = ((SQLPropertyExpr) expr).getOwnernName();
return findTable(tableSource, ownerName);
}
if (expr instanceof SQLAllColumnExpr || expr instanceof SQLIdentifierExpr) {
if (tableSource instanceof SQLExprTableSource) {
return findTable(tableSource, tableSource.computeAlias());
}
if (tableSource instanceof SQLJoinTableSource) {
SQLJoinTableSource join = (SQLJoinTableSource) tableSource;
SchemaObject table = findTable(join.getLeft(), expr);
if (table == null) {
table = findTable(join.getRight(), expr);
}
return table;
}
return null;
}
return null;
}
public Map<String, SchemaObject> getTables(SQLTableSource x) {
Map<String, SchemaObject> tables = new LinkedHashMap<String, SchemaObject>();
computeTables(x, tables);
return tables;
}
protected void computeTables(SQLTableSource x, Map<String, SchemaObject> tables) {
if (x == null) {
return;
}
if (x instanceof SQLExprTableSource) {
SQLExprTableSource exprTableSource = (SQLExprTableSource) x;
SQLExpr expr = exprTableSource.getExpr();
if (expr instanceof SQLIdentifierExpr) {
String tableName = ((SQLIdentifierExpr) expr).getName();
SchemaObject table = exprTableSource.getSchemaObject();
if (table == null) {
table = findTable(tableName);
if (table != null) {
exprTableSource.setSchemaObject(table);
}
}
if (table != null) {
tables.put(tableName, table);
String alias = x.getAlias();
if (alias != null && !alias.equalsIgnoreCase(tableName)) {
tables.put(alias, table);
}
}
}
return;
}
if (x instanceof SQLJoinTableSource) {
SQLJoinTableSource join = (SQLJoinTableSource) x;
computeTables(join.getLeft(), tables);
computeTables(join.getRight(), tables);
}
}
public int getTableCount() {
int count = 0;
for (SchemaObject object : this.objects.values()) {
if (object.getType() == SchemaObjectType.Table) {
count++;
}
}
return count;
}
public Map<String, SchemaObject> getObjects() {
return this.objects;
}
public int getViewCount() {
int count = 0;
for (SchemaObject object : this.objects.values()) {
if (object.getType() == SchemaObjectType.View) {
count++;
}
}
return count;
}
}
@@ -27,6 +27,7 @@ import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTableStatement;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -36,300 +37,150 @@ import java.util.concurrent.ConcurrentSkipListMap;
* Created by wenshao on 03/06/2017.
*/
public class SchemaRepository {
private String name;
private Schema defaultSchema;
private final Map<String, SchemaObject> objects = new ConcurrentSkipListMap<String, SchemaObject>();
private Map<String, Schema> schemas = new LinkedHashMap<String, Schema>();
private final Map<String, SchemaObject> functions = new ConcurrentSkipListMap<String, SchemaObject>();
private final SchemaVisitor visitor = new SchemaVisitor();
public String getName() {
return name;
public String getDefaultSchemaName() {
return getDefaultSchema().getName();
}
public void setName(String name) {
this.name = name;
public void setDefaultSchema(String name) {
if (name == null) {
defaultSchema = null;
return;
}
String normalizedName = SQLUtils.normalize(name)
.toLowerCase();
Schema defaultSchema = schemas.get(normalizedName);
if (defaultSchema != null) {
this.defaultSchema = defaultSchema;
return;
}
if (defaultSchema == null) {
if (this.defaultSchema != null
&& this.defaultSchema.getName() == null) {
this.defaultSchema.setName(name);
schemas.put(normalizedName, this.defaultSchema);
return;
}
defaultSchema = new Schema(this);
defaultSchema.setName(name);
schemas.put(normalizedName, defaultSchema);
this.defaultSchema = defaultSchema;
}
}
public Schema findSchema(String schema) {
if (schema == null) {
return null;
}
return schemas.get(
SQLUtils.normalize(schema)
.toLowerCase());
}
public Schema getDefaultSchema() {
if (defaultSchema == null) {
defaultSchema = new Schema(this);
}
return defaultSchema;
}
public void setDefaultSchema(Schema schema) {
this.defaultSchema = schema;
}
public SchemaObject findTable(String tableName) {
String lowerName = tableName.toLowerCase();
SchemaObject object = objects.get(lowerName);
return getDefaultSchema().findTable(tableName);
}
if (object != null && object.getType() == SchemaObjectType.Table) {
public SchemaObject findTableOrView(String tableName) {
return findTableOrView(tableName, true);
}
public SchemaObject findTableOrView(String tableName, boolean onlyCurrent) {
Schema schema = getDefaultSchema();
SchemaObject object = schema.findTableOrView(tableName);
if (object != null) {
return object;
}
for (Schema s : this.schemas.values()) {
if (s == schema) {
continue;
}
object = schema.findTableOrView(tableName);
if (object != null) {
return object;
}
}
return null;
}
public Collection<Schema> getSchemas() {
return schemas.values();
}
public SchemaObject findFunction(String functionName) {
String lowerName = functionName.toLowerCase();
return functions.get(lowerName);
return getDefaultSchema().findFunction(functionName);
}
public void acceptDDL(String ddl, String dbType) {
List<SQLStatement> stmtList = SQLUtils.parseStatements(ddl, dbType);
for (SQLStatement stmt : stmtList) {
accept(stmt);
}
getDefaultSchema().acceptDDL(ddl, dbType);
}
public void accept(SQLStatement stmt) {
stmt.accept(visitor);
getDefaultSchema().accept(stmt);
}
public boolean isSequence(String name) {
SchemaObject object = objects.get(name);
return object != null
&& object.getType() == SchemaObjectType.Sequence;
}
public class SchemaVisitor extends OracleASTVisitorAdapter {
public boolean visit(SQLDropSequenceStatement x) {
String name = x.getName().getSimpleName();
objects.remove(name);
return false;
}
public boolean visit(SQLCreateSequenceStatement x) {
String name = x.getName().getSimpleName();
SchemaObject object = new SchemaObjectImpl(name, SchemaObjectType.Sequence);
objects.put(name.toLowerCase(), object);
return false;
}
public boolean visit(OracleCreateTableStatement x) {
visit((SQLCreateTableStatement) x);
return false;
}
public boolean visit(SQLCreateTableStatement x) {
String name = x.computeName();
SchemaObject object = new SchemaObjectImpl(name, SchemaObjectType.Table, x);
String name_lower = name.toLowerCase();
if (objects.containsKey(name_lower)) {
return false;
}
objects.put(name_lower, object);
return false;
}
public boolean visit(SQLCreateIndexStatement x) {
String name = x.getName().getSimpleName();
SchemaObject object = new SchemaObjectImpl(name, SchemaObjectType.Index);
objects.put(name.toLowerCase(), object);
return false;
}
public boolean visit(SQLCreateFunctionStatement x) {
String name = x.getName().getSimpleName();
SchemaObject object = new SchemaObjectImpl(name, SchemaObjectType.Function, x);
functions.put(name.toLowerCase(), object);
return false;
}
return getDefaultSchema().isSequence(name);
}
public SchemaObject findTable(SQLTableSource tableSource, String alias) {
if (tableSource instanceof SQLExprTableSource) {
if (alias.equalsIgnoreCase(tableSource.computeAlias())) {
SQLExprTableSource exprTableSource = (SQLExprTableSource) tableSource;
SchemaObject tableObject = exprTableSource.getSchemaObject();
if (tableObject != null) {
return tableObject;
}
SQLExpr expr = exprTableSource.getExpr();
if (expr instanceof SQLIdentifierExpr) {
String tableName = ((SQLIdentifierExpr) expr).getName();
tableObject = findTable(tableName);
if (tableObject != null) {
exprTableSource.setSchemaObject(tableObject);
}
return tableObject;
}
if (expr instanceof SQLPropertyExpr) {
String tableName = ((SQLPropertyExpr) expr).getName();
tableObject = findTable(tableName);
if (tableObject != null) {
exprTableSource.setSchemaObject(tableObject);
}
return tableObject;
}
}
return null;
}
if (tableSource instanceof SQLJoinTableSource) {
SQLJoinTableSource join = (SQLJoinTableSource) tableSource;
SQLTableSource left = join.getLeft();
SchemaObject tableObject = findTable(left, alias);
if (tableObject != null) {
return tableObject;
}
SQLTableSource right = join.getRight();
tableObject = findTable(right, alias);
return tableObject;
}
return null;
return getDefaultSchema().findTable(tableSource, alias);
}
public SQLColumnDefinition findColumn(SQLTableSource tableSource, SQLSelectItem selectItem) {
if (selectItem == null) {
return null;
}
return findColumn(tableSource, selectItem.getExpr());
return getDefaultSchema().findColumn(tableSource, selectItem);
}
public SQLColumnDefinition findColumn(SQLTableSource tableSource, SQLExpr expr) {
SchemaObject object = findTable(tableSource, expr);
if (object != null) {
if (expr instanceof SQLAggregateExpr) {
SQLAggregateExpr aggregateExpr = (SQLAggregateExpr) expr;
String function = aggregateExpr.getMethodName();
if ("min".equalsIgnoreCase(function)
|| "max".equalsIgnoreCase(function)) {
SQLExpr arg = aggregateExpr.getArguments().get(0);
expr = arg;
}
}
if (expr instanceof SQLName) {
return object.findColumn(((SQLName) expr).getSimpleName());
}
}
return null;
return getDefaultSchema().findColumn(tableSource, expr);
}
public SchemaObject findTable(SQLTableSource tableSource, SQLSelectItem selectItem) {
if (selectItem == null) {
return null;
}
return findTable(tableSource, selectItem.getExpr());
return getDefaultSchema().findTable(tableSource, selectItem);
}
public SchemaObject findTable(SQLTableSource tableSource, SQLExpr expr) {
if (expr instanceof SQLAggregateExpr) {
SQLAggregateExpr aggregateExpr = (SQLAggregateExpr) expr;
String function = aggregateExpr.getMethodName();
if ("min".equalsIgnoreCase(function)
|| "max".equalsIgnoreCase(function)) {
SQLExpr arg = aggregateExpr.getArguments().get(0);
return findTable(tableSource, arg);
}
}
if (expr instanceof SQLPropertyExpr) {
String ownerName = ((SQLPropertyExpr) expr).getOwnernName();
return findTable(tableSource, ownerName);
}
if (expr instanceof SQLAllColumnExpr || expr instanceof SQLIdentifierExpr) {
if (tableSource instanceof SQLExprTableSource) {
return findTable(tableSource, tableSource.computeAlias());
}
if (tableSource instanceof SQLJoinTableSource) {
SQLJoinTableSource join = (SQLJoinTableSource) tableSource;
SchemaObject table = findTable(join.getLeft(), expr);
if (table == null) {
table = findTable(join.getRight(), expr);
}
return table;
}
return null;
}
return null;
return getDefaultSchema().findTable(tableSource, expr);
}
public Map<String, SchemaObject> getTables(SQLTableSource x) {
Map<String, SchemaObject> tables = new LinkedHashMap<String, SchemaObject>();
computeTables(x, tables);
return tables;
}
private void computeTables(SQLTableSource x, Map<String, SchemaObject> tables) {
if (x == null) {
return;
}
if (x instanceof SQLExprTableSource) {
SQLExprTableSource exprTableSource = (SQLExprTableSource) x;
SQLExpr expr = exprTableSource.getExpr();
if (expr instanceof SQLIdentifierExpr) {
String tableName = ((SQLIdentifierExpr) expr).getName();
SchemaObject table = exprTableSource.getSchemaObject();
if (table == null) {
table = findTable(tableName);
if (table != null) {
exprTableSource.setSchemaObject(table);
}
}
if (table != null) {
tables.put(tableName, table);
String alias = x.getAlias();
if (alias != null && !alias.equalsIgnoreCase(tableName)) {
tables.put(alias, table);
}
}
}
return;
}
if (x instanceof SQLJoinTableSource) {
SQLJoinTableSource join = (SQLJoinTableSource) x;
computeTables(join.getLeft(), tables);
computeTables(join.getRight(), tables);
}
return getDefaultSchema().getTables(x);
}
public int getTableCount() {
int count = 0;
for (SchemaObject object : this.objects.values()) {
if (object.getType() == SchemaObjectType.Table) {
count++;
}
}
return count;
return getDefaultSchema().getTableCount();
}
public Map<String, SchemaObject> getObjects() {
return this.objects;
return getDefaultSchema().getObjects();
}
public int getViewCount() {
int count = 0;
for (SchemaObject object : this.objects.values()) {
if (object.getType() == SchemaObjectType.View) {
count++;
}
}
return count;
return getDefaultSchema().getViewCount();
}
}
@@ -134,7 +134,9 @@ public final class ExportParameterVisitorUtils {
}
public static void exportParameter(final List<Object> parameters, SQLBinaryOpExpr x) {
if (x.getLeft() instanceof SQLLiteralExpr && x.getRight() instanceof SQLLiteralExpr && x.getOperator().isRelational()) {
if (x.getLeft() instanceof SQLLiteralExpr
&& x.getRight() instanceof SQLLiteralExpr
&& x.getOperator().isRelational()) {
return;
}
@@ -697,15 +697,19 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
return false;
}
if (x.getText() == null) {
printChars(x.getText());
return false;
}
protected void printChars(String text) {
if (text == null) {
print0(ucase ? "NULL" : "null");
} else {
print('\'');
print0(x.getText().replaceAll("'", "''"));
print0(text.replaceAll("'", "''"));
print('\'');
}
return false;
}
public boolean visit(SQLDataType x) {
@@ -884,39 +888,49 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
if (this.parameterized) {
List<SQLExpr> targetList = x.getTargetList();
boolean changed = true;
if (targetList.size() == 1 && targetList.get(0) instanceof SQLVariantRefExpr) {
changed = false;
}
x.getExpr().accept(this);
if (x.isNot()) {
print(isUppCase() ? " NOT IN (?)" : " not in (?)");
} else {
print(isUppCase() ? " IN (?)" : " in (?)");
}
if (changed) {
incrementReplaceCunt();
if(this instanceof ExportParameterVisitor || this.parameters != null) {
if (parameterizedMergeInList) {
List<Object> subList = new ArrayList<Object>(x.getTargetList().size());
for (SQLExpr target : x.getTargetList()) {
ExportParameterVisitorUtils.exportParameter(subList, target);
}
if (subList != null) {
parameters.add(subList);
}
} else {
for (SQLExpr target : x.getTargetList()) {
ExportParameterVisitorUtils.exportParameter(this.parameters, target);
}
}
boolean allLiteral = true;
for (SQLExpr item : targetList) {
if (!(item instanceof SQLLiteralExpr || item instanceof SQLVariantRefExpr)) {
allLiteral = false;
break;
}
}
return false;
if (allLiteral) {
boolean changed = true;
if (targetList.size() == 1 && targetList.get(0) instanceof SQLVariantRefExpr) {
changed = false;
}
x.getExpr().accept(this);
if (x.isNot()) {
print(isUppCase() ? " NOT IN (?)" : " not in (?)");
} else {
print(isUppCase() ? " IN (?)" : " in (?)");
}
if (changed) {
incrementReplaceCunt();
if (this instanceof ExportParameterVisitor || this.parameters != null) {
if (parameterizedMergeInList) {
List<Object> subList = new ArrayList<Object>(x.getTargetList().size());
for (SQLExpr target : x.getTargetList()) {
ExportParameterVisitorUtils.exportParameter(subList, target);
}
if (subList != null) {
parameters.add(subList);
}
} else {
for (SQLExpr target : x.getTargetList()) {
ExportParameterVisitorUtils.exportParameter(this.parameters, target);
}
}
}
}
return false;
}
}
x.getExpr().accept(this);
@@ -962,19 +976,21 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
public boolean visit(SQLIntegerExpr x) {
int val = x.getNumber().intValue();
if (val == 1
&& JdbcConstants.ORACLE.equals(dbType)) {
SQLObject parent = x.getParent();
if (parent instanceof SQLBinaryOpExpr) {
SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) parent;
SQLExpr left = binaryOpExpr.getLeft();
SQLBinaryOperator op = binaryOpExpr.getOperator();
if (left instanceof SQLIdentifierExpr
&& op == SQLBinaryOperator.Equality) {
String name = ((SQLIdentifierExpr) left).getName();
if ("rownum".equals(name)) {
print(1);
return false;
SQLObject parent = x.getParent();
if (val == 1) {
if (JdbcConstants.ORACLE.equals(dbType)) {
if (parent instanceof SQLBinaryOpExpr) {
SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) parent;
SQLExpr left = binaryOpExpr.getLeft();
SQLBinaryOperator op = binaryOpExpr.getOperator();
if (left instanceof SQLIdentifierExpr
&& op == SQLBinaryOperator.Equality) {
String name = ((SQLIdentifierExpr) left).getName();
if ("rownum".equals(name)) {
print(1);
return false;
}
}
}
}
@@ -1015,14 +1031,21 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
SQLExpr param = x.getParameters().get(i);
if (parameterized) {
if (JdbcUtils.ORACLE.equalsIgnoreCase(dbType)) {
if (size == 2 && i == 1 && param instanceof SQLCharExpr) {
if (size == 2 && i == 1 && param instanceof SQLCharExpr) {
if (JdbcUtils.ORACLE.equals(dbType)) {
if ("TO_CHAR".equalsIgnoreCase(function)
|| "TO_DATE".equalsIgnoreCase(function)) {
param.putAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP, true);
printChars(((SQLCharExpr) param).getText());
continue;
}
} else if (JdbcConstants.MYSQL.equals(dbType)) {
if ("DATE_FORMAT".equalsIgnoreCase(function)) {
printChars(((SQLCharExpr) param).getText());
continue;
}
}
}
}
if (param instanceof SQLBinaryOpExpr) {
@@ -3427,16 +3450,26 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
if (i != 0 && comment.startsWith("--")) {
println();
}
print0(comment);
printComment(comment);
}
}
}
public void printComment(String comment) {
if (comment.startsWith("--") && comment.length() > 2 && comment.charAt(2) != ' ') {
print0("-- ");
print0(comment.substring(2));
} else {
print0(comment);
}
}
protected void printlnComments(List<String> comments) {
if (comments != null) {
for (int i = 0; i < comments.size(); ++i) {
String comment = comments.get(i);
print0(comment);
printComment(comment);
println();
}
}
@@ -34,14 +34,7 @@ import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.*;
/**
* @author wenshao [szujobs@hotmail.com]
@@ -629,6 +622,10 @@ public final class JdbcUtils implements JdbcConstants {
}
}
public static void execute(Connection conn, String sql) throws SQLException {
execute(conn, sql, Collections.emptyList());
}
public static void execute(Connection conn, String sql, List<Object> parameters) throws SQLException {
PreparedStatement stmt = null;