mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
improved sql parser.
This commit is contained in:
@@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
+14
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
@@ -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";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user