improved sql parser.

This commit is contained in:
wenshao
2017-07-11 15:48:32 +08:00
parent 15ac64e501
commit bb833e499e
20 changed files with 564 additions and 95 deletions
@@ -444,7 +444,9 @@ public class PagerUtils {
}
private static SQLSelectQueryBlock createQueryBlock(String dbType) {
if (JdbcConstants.MYSQL.equals(dbType)) {
if (JdbcConstants.MYSQL.equals(dbType)
|| JdbcConstants.MARIADB.equals(dbType)
|| JdbcConstants.ALIYUN_ADS.equals(dbType)) {
return new MySqlSelectQueryBlock();
}
@@ -48,6 +48,14 @@ public class SQLMethodInvokeExpr extends SQLExprImpl implements SQLReplaceable,
setOwner(owner);
}
public SQLMethodInvokeExpr(String methodName, SQLExpr owner, SQLExpr... params){
this.methodName = methodName;
setOwner(owner);
for (SQLExpr param : params) {
this.addParameter(param);
}
}
public String getMethodName() {
return this.methodName;
}
@@ -15,6 +15,7 @@
*/
package com.alibaba.druid.sql.ast.statement;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLCommentHint;
import com.alibaba.druid.sql.ast.SQLDataTypeImpl;
import com.alibaba.druid.sql.ast.SQLExpr;
@@ -99,4 +100,9 @@ public class SQLCharacterDataType extends SQLDataTypeImpl {
visitor.endVisit(this);
}
@Override
public String toString() {
return SQLUtils.toSQLString(this);
}
}
@@ -103,6 +103,9 @@ public class SQLColumnDefinition extends SQLObjectImpl implements SQLTableElemen
}
public void setDataType(SQLDataType dataType) {
if (dataType != null) {
dataType.setParent(this);
}
this.dataType = dataType;
}
@@ -227,4 +227,14 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS
}
}
}
public SQLPrimaryKey findPrimaryKey() {
for (SQLTableElement element : this.tableElementList) {
if (element instanceof SQLPrimaryKey) {
return (SQLPrimaryKey) element;
}
}
return null;
}
}
@@ -22,6 +22,7 @@ import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.*;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery, SQLReplaceable {
@@ -89,6 +90,18 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery
}
this.where = where;
}
public void addWhere(SQLExpr condition) {
if (condition == null) {
return;
}
if (where == null) {
where = condition;
} else {
where = SQLBinaryOpExpr.and(where, condition);
}
}
public SQLOrderBy getOrderBy() {
return orderBy;
@@ -448,4 +461,14 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery
this.setWhere(SQLBinaryOpExpr.and(where, expr));
}
public void limit(int rowCount, int offset) {
SQLLimit limit = new SQLLimit();
limit.setRowCount(new SQLIntegerExpr(rowCount));
if (offset > 0) {
limit.setOffset(new SQLIntegerExpr(offset));
}
setLimit(limit);
}
}
@@ -0,0 +1,78 @@
/*
* 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.builder;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
import com.alibaba.druid.util.JdbcConstants;
/**
* Created by wenshao on 09/07/2017.
*/
public class FunctionBuilder {
private final String dbType;
public FunctionBuilder(String dbType) {
this.dbType = dbType;
}
// for character function
public SQLMethodInvokeExpr length(SQLExpr expr) {
return new SQLMethodInvokeExpr("length", null, expr);
}
public SQLMethodInvokeExpr lower(SQLExpr expr) {
return new SQLMethodInvokeExpr("lower", null, expr);
}
public SQLMethodInvokeExpr upper(SQLExpr expr) {
return new SQLMethodInvokeExpr("upper", null, expr);
}
public SQLMethodInvokeExpr substr(SQLExpr expr) {
return new SQLMethodInvokeExpr("substr", null, expr);
}
public SQLMethodInvokeExpr ltrim(SQLExpr expr) {
return new SQLMethodInvokeExpr("ltrim", null, expr);
}
public SQLMethodInvokeExpr rtrim(SQLExpr expr) {
return new SQLMethodInvokeExpr("rtrim", null, expr);
}
public SQLMethodInvokeExpr trim(SQLExpr expr) {
return new SQLMethodInvokeExpr("trim", null, expr);
}
public SQLMethodInvokeExpr ifnull(SQLExpr expr1, SQLExpr expr2) {
if (JdbcConstants.ALIYUN_ADS.equals(dbType)
|| JdbcConstants.PRESTO.equals(dbType)
|| JdbcConstants.ODPS.equals(dbType)) {
return new SQLMethodInvokeExpr("coalesce", null, expr1, expr2);
}
if (JdbcConstants.ORACLE.equals(dbType)) {
return new SQLMethodInvokeExpr("nvl", null, expr1, expr2);
}
if (JdbcConstants.SQL_SERVER.equals(dbType)) {
return new SQLMethodInvokeExpr("isnull", null, expr1, expr2);
}
return new SQLMethodInvokeExpr("ifnull", null, expr1, expr2);
}
}
@@ -194,11 +194,7 @@ public class SQLSelectBuilderImpl implements SQLSelectBuilder {
@Override
public SQLSelectBuilderImpl whereAnd(String expr) {
SQLSelectQueryBlock queryBlock = getQueryBlock();
SQLExpr exprObj = SQLUtils.toSQLExpr(expr, dbType);
SQLExpr newCondition = SQLUtils.buildCondition(SQLBinaryOperator.BooleanAnd, exprObj, false,
queryBlock.getWhere());
queryBlock.setWhere(newCondition);
queryBlock.addWhere(SQLUtils.toSQLExpr(expr, dbType));
return this;
}
@@ -222,86 +218,9 @@ public class SQLSelectBuilderImpl implements SQLSelectBuilder {
@Override
public SQLSelectBuilderImpl limit(int rowCount, int offset) {
SQLSelectQueryBlock queryBlock = getQueryBlock();
if (queryBlock instanceof MySqlSelectQueryBlock) {
MySqlSelectQueryBlock mySqlQueryBlock = (MySqlSelectQueryBlock) queryBlock;
SQLLimit limit = new SQLLimit();
limit.setRowCount(new SQLIntegerExpr(rowCount));
if (offset > 0) {
limit.setOffset(new SQLIntegerExpr(offset));
}
mySqlQueryBlock.setLimit(limit);
return this;
}
if (queryBlock instanceof SQLServerSelectQueryBlock) {
SQLServerSelectQueryBlock sqlserverQueryBlock = (SQLServerSelectQueryBlock) queryBlock;
if (offset <= 0) {
SQLServerTop top = new SQLServerTop();
top.setExpr(new SQLIntegerExpr(rowCount));
sqlserverQueryBlock.setTop(top);
} else {
throw new UnsupportedOperationException("not support offset");
}
return this;
}
if (queryBlock instanceof PGSelectQueryBlock) {
PGSelectQueryBlock pgQueryBlock = (PGSelectQueryBlock) queryBlock;
SQLLimit limit = new SQLLimit();
if (offset > 0) {
limit.setOffset(new SQLIntegerExpr(offset));
}
limit.setRowCount(new SQLIntegerExpr(rowCount));
pgQueryBlock.setLimit(limit);
return this;
}
if (queryBlock instanceof DB2SelectQueryBlock) {
DB2SelectQueryBlock db2QueryBlock = (DB2SelectQueryBlock) queryBlock;
if (offset <= 0) {
SQLExpr rowCountExpr = new SQLIntegerExpr(rowCount);
db2QueryBlock.setFirst(rowCountExpr);
} else {
throw new UnsupportedOperationException("not support offset");
}
return this;
}
if (queryBlock instanceof OracleSelectQueryBlock) {
OracleSelectQueryBlock oracleQueryBlock = (OracleSelectQueryBlock) queryBlock;
if (offset <= 0) {
SQLExpr rowCountExpr = new SQLIntegerExpr(rowCount);
SQLExpr newCondition = SQLUtils.buildCondition(SQLBinaryOperator.BooleanAnd, rowCountExpr, false,
oracleQueryBlock.getWhere());
queryBlock.setWhere(newCondition);
} else {
throw new UnsupportedOperationException("not support offset");
}
return this;
}
if (queryBlock instanceof OdpsSelectQueryBlock) {
OdpsSelectQueryBlock odpsQueryBlock = (OdpsSelectQueryBlock) queryBlock;
if (offset > 0) {
throw new UnsupportedOperationException("not support offset");
}
odpsQueryBlock.setLimit(new SQLLimit(new SQLIntegerExpr(rowCount)));
return this;
}
throw new UnsupportedOperationException();
getQueryBlock()
.limit(rowCount, offset);
return this;
}
protected SQLSelectQueryBlock getQueryBlock() {
@@ -16,6 +16,7 @@
package com.alibaba.druid.sql.dialect.db2.ast.stmt;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.dialect.db2.ast.DB2Object;
import com.alibaba.druid.sql.dialect.db2.visitor.DB2ASTVisitor;
@@ -80,4 +81,12 @@ public class DB2SelectQueryBlock extends SQLSelectQueryBlock implements DB2Objec
public static enum Isolation {
RR, RS, CS, UR
}
public void limit(int rowCount, int offset) {
if (offset <= 0) {
setFirst(new SQLIntegerExpr(rowCount));
} else {
throw new UnsupportedOperationException("not support offset");
}
}
}
@@ -328,9 +328,10 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
dataType.accept(this);
}
if (x.getCharsetExpr() != null) {
final SQLExpr charsetExpr = x.getCharsetExpr();
if (charsetExpr != null) {
print0(ucase ? " CHARSET " : " charset ");
x.getCharsetExpr().accept(this);
charsetExpr.accept(this);
}
for (SQLColumnConstraint item : x.getConstraints()) {
@@ -338,20 +339,23 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
item.accept(this);
}
if (x.getDefaultExpr() != null) {
final SQLExpr defaultExpr = x.getDefaultExpr();
if (defaultExpr != null) {
print0(ucase ? " DEFAULT " : " default ");
x.getDefaultExpr().accept(this);
defaultExpr.accept(this);
}
if (x.getStorage() != null) {
final SQLExpr storage = x.getStorage();
if (storage != null) {
print0(ucase ? " STORAGE " : " storage ");
x.getStorage().accept(this);
storage.accept(this);
}
if (x.getOnUpdate() != null) {
SQLExpr onUpdate = x.getOnUpdate();
if (onUpdate != null) {
print0(ucase ? " ON UPDATE " : " on update ");
x.getOnUpdate().accept(this);
onUpdate.accept(this);
}
if (x.isAutoIncrement()) {
@@ -21,7 +21,9 @@ import java.util.List;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLHint;
import com.alibaba.druid.sql.ast.SQLLimit;
import com.alibaba.druid.sql.ast.SQLOrderBy;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;
@@ -122,4 +124,12 @@ public class OdpsSelectQueryBlock extends SQLSelectQueryBlock {
public String toString() {
return SQLUtils.toOdpsString(this);
}
public void limit(int rowCount, int offset) {
if (offset > 0) {
throw new UnsupportedOperationException("not support offset");
}
setLimit(new SQLLimit(new SQLIntegerExpr(rowCount)));
}
}
@@ -21,6 +21,9 @@ import java.util.List;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLCommentHint;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLLimit;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
@@ -147,4 +150,15 @@ public class OracleSelectQueryBlock extends SQLSelectQueryBlock {
public String toString() {
return SQLUtils.toOracleString(this);
}
public void limit(int rowCount, int offset) {
if (offset <= 0) {
SQLExpr rowCountExpr = new SQLIntegerExpr(rowCount);
SQLExpr newCondition = SQLUtils.buildCondition(SQLBinaryOperator.BooleanAnd, rowCountExpr, false,
where);
setWhere(newCondition);
} else {
throw new UnsupportedOperationException("not support offset");
}
}
}
@@ -15,6 +15,8 @@
*/
package com.alibaba.druid.sql.dialect.sqlserver.ast;
import com.alibaba.druid.sql.ast.SQLLimit;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
@@ -34,6 +36,10 @@ public class SQLServerSelectQueryBlock extends SQLSelectQueryBlock {
this.top = top;
}
public void setTop(int rowCount) {
setTop(new SQLServerTop(new SQLIntegerExpr(rowCount)));
}
@Override
protected void accept0(SQLASTVisitor visitor) {
accept0((SQLServerASTVisitor) visitor);
@@ -49,4 +55,12 @@ public class SQLServerSelectQueryBlock extends SQLSelectQueryBlock {
}
visitor.endVisit(this);
}
public void limit(int rowCount, int offset) {
if (offset <= 0) {
setTop(rowCount);
} else {
throw new UnsupportedOperationException("not support offset");
}
}
}
@@ -343,6 +343,16 @@ public class Lexer {
}
if (isFirstIdentifierChar(ch)) {
if (ch == '(') {
scanChar();
token = LPAREN;
return;
} else if (ch == ')') {
scanChar();
token = RPAREN;
return;
}
if (ch == 'N') {
if (charAt(pos + 1) == '\'') {
++pos;
@@ -110,7 +110,11 @@ public class SchemaRepository {
String name = x.computeName();
SchemaObject object = new SchemaObjectImpl(name, SchemaObjectType.Table, x);
objects.put(name.toLowerCase(), object);
String name_lower = name.toLowerCase();
if (objects.containsKey(name_lower)) {
return false;
}
objects.put(name_lower, object);
return false;
}
@@ -99,4 +99,9 @@ public interface JdbcConstants {
public static final String SQLITE = "sqlite";
public static final String SQLITE_DRIVER = "org.sqlite.JDBC";
public static final String ALIYUN_ADS = "aliyun_ads";
public static final String ALIYUN_DRDS = "aliyun_drds";
public static final String PRESTO = "presto";
}