mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
@@ -23,6 +23,7 @@ import com.alibaba.druid.sql.ast.expr.*;
|
||||
import com.alibaba.druid.sql.ast.statement.*;
|
||||
import com.alibaba.druid.sql.dialect.db2.visitor.DB2OutputVisitor;
|
||||
import com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;
|
||||
import com.alibaba.druid.sql.dialect.h2.visitor.H2OutputVisitor;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
|
||||
import com.alibaba.druid.sql.dialect.odps.visitor.OdpsOutputVisitor;
|
||||
@@ -43,6 +44,11 @@ import com.alibaba.druid.support.logging.LogFactory;
|
||||
import com.alibaba.druid.util.*;
|
||||
|
||||
public class SQLUtils {
|
||||
private final static SQLParserFeature[] FORMAT_DEFAULT_FEATURES = {
|
||||
SQLParserFeature.KeepComments,
|
||||
SQLParserFeature.EnableSQLBinaryOpExprGroup
|
||||
};
|
||||
|
||||
public static FormatOption DEFAULT_FORMAT_OPTION = new FormatOption(true, true);
|
||||
public static FormatOption DEFAULT_LCASE_FORMAT_OPTION
|
||||
= new FormatOption(false, true);
|
||||
@@ -234,13 +240,8 @@ public class SQLUtils {
|
||||
|
||||
public static String format(String sql, String dbType, List<Object> parameters, FormatOption option) {
|
||||
try {
|
||||
SQLParserFeature[] features = {SQLParserFeature.KeepComments, SQLParserFeature.EnableSQLBinaryOpExprGroup};
|
||||
|
||||
SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, features);
|
||||
parser.setKeepComments(true);
|
||||
|
||||
SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType, FORMAT_DEFAULT_FEATURES);
|
||||
List<SQLStatement> statementList = parser.parseStatementList();
|
||||
|
||||
return toSQLString(statementList, dbType, parameters, option);
|
||||
} catch (ParserException ex) {
|
||||
LOG.warn("format error", ex);
|
||||
@@ -363,8 +364,7 @@ public class SQLUtils {
|
||||
}
|
||||
|
||||
if (JdbcConstants.MYSQL.equals(dbType) //
|
||||
|| JdbcConstants.MARIADB.equals(dbType) //
|
||||
|| JdbcConstants.H2.equals(dbType)) {
|
||||
|| JdbcConstants.MARIADB.equals(dbType)) {
|
||||
return new MySqlOutputVisitor(out);
|
||||
}
|
||||
|
||||
@@ -384,6 +384,10 @@ public class SQLUtils {
|
||||
return new OdpsOutputVisitor(out);
|
||||
}
|
||||
|
||||
if (JdbcConstants.H2.equals(dbType)) {
|
||||
return new H2OutputVisitor(out);
|
||||
}
|
||||
|
||||
return new SQLASTOutputVisitor(out, dbType);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ package com.alibaba.druid.sql.ast;
|
||||
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
|
||||
public class SQLKeep extends SQLObjectImpl {
|
||||
public final class SQLKeep extends SQLObjectImpl {
|
||||
|
||||
protected DenseRank denseRank;
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
/**
|
||||
* Created by wenshao on 16/9/25.
|
||||
*/
|
||||
public class SQLLimit extends SQLObjectImpl {
|
||||
public final class SQLLimit extends SQLObjectImpl {
|
||||
|
||||
public SQLLimit() {
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SQLOrderBy extends SQLObjectImpl {
|
||||
public final class SQLOrderBy extends SQLObjectImpl {
|
||||
|
||||
protected final List<SQLSelectOrderByItem> items = new ArrayList<SQLSelectOrderByItem>();
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SQLParameter extends SQLObjectImpl implements SQLObjectWithDataType {
|
||||
public final class SQLParameter extends SQLObjectImpl implements SQLObjectWithDataType {
|
||||
|
||||
private SQLName name;
|
||||
private SQLDataType dataType;
|
||||
|
||||
@@ -19,7 +19,7 @@ import com.alibaba.druid.sql.ast.SQLExprImpl;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
|
||||
public class SQLAllColumnExpr extends SQLExprImpl {
|
||||
public final class SQLAllColumnExpr extends SQLExprImpl {
|
||||
private transient SQLTableSource resolvedTableSource;
|
||||
|
||||
public SQLAllColumnExpr(){
|
||||
|
||||
@@ -19,7 +19,7 @@ import com.alibaba.druid.sql.ast.SQLExprImpl;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelect;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
|
||||
public class SQLAllExpr extends SQLExprImpl {
|
||||
public final class SQLAllExpr extends SQLExprImpl {
|
||||
|
||||
public SQLSelect subQuery;
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import com.alibaba.druid.sql.ast.SQLExprImpl;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLCharacterDataType;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
|
||||
public class SQLBooleanExpr extends SQLExprImpl implements SQLExpr, SQLLiteralExpr, SQLValuableExpr {
|
||||
public final class SQLBooleanExpr extends SQLExprImpl implements SQLExpr, SQLLiteralExpr, SQLValuableExpr {
|
||||
public static final SQLDataType DEFAULT_DATA_TYPE = new SQLCharacterDataType("boolean");
|
||||
|
||||
private boolean value;
|
||||
|
||||
@@ -21,7 +21,7 @@ import com.alibaba.druid.sql.ast.SQLExprImpl;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelect;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
|
||||
public class SQLExistsExpr extends SQLExprImpl implements Serializable {
|
||||
public final class SQLExistsExpr extends SQLExprImpl implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
public boolean not = false;
|
||||
|
||||
@@ -21,7 +21,7 @@ import com.alibaba.druid.sql.ast.statement.*;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
import com.alibaba.druid.util.FnvHash;
|
||||
|
||||
public class SQLIdentifierExpr extends SQLExprImpl implements SQLName {
|
||||
public final class SQLIdentifierExpr extends SQLExprImpl implements SQLName {
|
||||
protected String name;
|
||||
private long hashCode64;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLExprImpl;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
|
||||
public class SQLInListExpr extends SQLExprImpl implements Serializable {
|
||||
public final class SQLInListExpr extends SQLExprImpl implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private boolean not = false;
|
||||
|
||||
@@ -22,7 +22,7 @@ import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLExprImpl;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
|
||||
public class SQLNotExpr extends SQLExprImpl implements Serializable {
|
||||
public final class SQLNotExpr extends SQLExprImpl implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
public SQLExpr expr;
|
||||
|
||||
@@ -20,7 +20,7 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
|
||||
import static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE_NULL;
|
||||
|
||||
public class SQLNullExpr extends SQLExprImpl implements SQLLiteralExpr, SQLValuableExpr {
|
||||
public final class SQLNullExpr extends SQLExprImpl implements SQLLiteralExpr, SQLValuableExpr {
|
||||
|
||||
public SQLNullExpr(){
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import com.alibaba.druid.sql.ast.statement.*;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
import com.alibaba.druid.util.FnvHash;
|
||||
|
||||
public class SQLPropertyExpr extends SQLExprImpl implements SQLName {
|
||||
public final class SQLPropertyExpr extends SQLExprImpl implements SQLName {
|
||||
private SQLExpr owner;
|
||||
private String name;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SQLSomeExpr extends SQLExprImpl {
|
||||
public final class SQLSomeExpr extends SQLExprImpl {
|
||||
|
||||
public SQLSelect subQuery;
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ public class SQLCreateTriggerStatement extends SQLStatementImpl implements SQLCr
|
||||
private boolean delete;
|
||||
private boolean insert;
|
||||
|
||||
private SQLName on;
|
||||
private SQLExprTableSource on;
|
||||
|
||||
private boolean forEachRow = false;
|
||||
|
||||
@@ -64,11 +64,18 @@ public class SQLCreateTriggerStatement extends SQLStatementImpl implements SQLCr
|
||||
visitor.endVisit(this);
|
||||
}
|
||||
|
||||
public SQLName getOn() {
|
||||
public SQLExprTableSource getOn() {
|
||||
return on;
|
||||
}
|
||||
|
||||
public void setOn(SQLName on) {
|
||||
this.setOn(new SQLExprTableSource(on));
|
||||
}
|
||||
|
||||
public void setOn(SQLExprTableSource on) {
|
||||
if (on != null) {
|
||||
on.setParent(this);
|
||||
}
|
||||
this.on = on;
|
||||
}
|
||||
|
||||
|
||||
+97
-112
@@ -1,112 +1,97 @@
|
||||
/*
|
||||
* 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.dialect.mysql.ast.statement;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
|
||||
|
||||
public class MySqlReplaceStatement extends MySqlStatementImpl {
|
||||
|
||||
private boolean lowPriority = false;
|
||||
private boolean delayed = false;
|
||||
|
||||
private SQLExprTableSource tableSource;
|
||||
private final List<SQLExpr> columns = new ArrayList<SQLExpr>();
|
||||
private List<ValuesClause> valuesList = new ArrayList<ValuesClause>();
|
||||
private SQLQueryExpr query;
|
||||
|
||||
public SQLName getTableName() {
|
||||
if (tableSource == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (SQLName) tableSource.getExpr();
|
||||
}
|
||||
|
||||
public void setTableName(SQLName tableName) {
|
||||
this.setTableSource(new SQLExprTableSource(tableName));
|
||||
}
|
||||
|
||||
public SQLExprTableSource getTableSource() {
|
||||
return tableSource;
|
||||
}
|
||||
|
||||
public void setTableSource(SQLExprTableSource tableSource) {
|
||||
if (tableSource != null) {
|
||||
tableSource.setParent(this);
|
||||
}
|
||||
this.tableSource = tableSource;
|
||||
}
|
||||
|
||||
public List<SQLExpr> getColumns() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
public void addColumn(SQLExpr column) {
|
||||
if (column != null) {
|
||||
column.setParent(this);
|
||||
}
|
||||
this.columns.add(column);
|
||||
}
|
||||
|
||||
public boolean isLowPriority() {
|
||||
return lowPriority;
|
||||
}
|
||||
|
||||
public void setLowPriority(boolean lowPriority) {
|
||||
this.lowPriority = lowPriority;
|
||||
}
|
||||
|
||||
public boolean isDelayed() {
|
||||
return delayed;
|
||||
}
|
||||
|
||||
public void setDelayed(boolean delayed) {
|
||||
this.delayed = delayed;
|
||||
}
|
||||
|
||||
public SQLQueryExpr getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public void setQuery(SQLQueryExpr query) {
|
||||
if (query != null) {
|
||||
query.setParent(this);
|
||||
}
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
public List<ValuesClause> getValuesList() {
|
||||
return valuesList;
|
||||
}
|
||||
|
||||
public void accept0(MySqlASTVisitor visitor) {
|
||||
if (visitor.visit(this)) {
|
||||
acceptChild(visitor, tableSource);
|
||||
acceptChild(visitor, columns);
|
||||
acceptChild(visitor, valuesList);
|
||||
acceptChild(visitor, query);
|
||||
}
|
||||
visitor.endVisit(this);
|
||||
}
|
||||
}
|
||||
package com.alibaba.druid.sql.ast.statement;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.ast.SQLStatementImpl;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SQLReplaceStatement extends SQLStatementImpl {
|
||||
protected boolean lowPriority = false;
|
||||
protected boolean delayed = false;
|
||||
|
||||
protected SQLExprTableSource tableSource;
|
||||
protected final List<SQLExpr> columns = new ArrayList<SQLExpr>();
|
||||
protected List<SQLInsertStatement.ValuesClause> valuesList = new ArrayList<SQLInsertStatement.ValuesClause>();
|
||||
protected SQLQueryExpr query;
|
||||
|
||||
|
||||
public SQLName getTableName() {
|
||||
if (tableSource == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (SQLName) tableSource.getExpr();
|
||||
}
|
||||
|
||||
public void setTableName(SQLName tableName) {
|
||||
this.setTableSource(new SQLExprTableSource(tableName));
|
||||
}
|
||||
|
||||
public SQLExprTableSource getTableSource() {
|
||||
return tableSource;
|
||||
}
|
||||
|
||||
public void setTableSource(SQLExprTableSource tableSource) {
|
||||
if (tableSource != null) {
|
||||
tableSource.setParent(this);
|
||||
}
|
||||
this.tableSource = tableSource;
|
||||
}
|
||||
|
||||
public List<SQLExpr> getColumns() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
public void addColumn(SQLExpr column) {
|
||||
if (column != null) {
|
||||
column.setParent(this);
|
||||
}
|
||||
this.columns.add(column);
|
||||
}
|
||||
|
||||
public boolean isLowPriority() {
|
||||
return lowPriority;
|
||||
}
|
||||
|
||||
public void setLowPriority(boolean lowPriority) {
|
||||
this.lowPriority = lowPriority;
|
||||
}
|
||||
|
||||
public boolean isDelayed() {
|
||||
return delayed;
|
||||
}
|
||||
|
||||
public void setDelayed(boolean delayed) {
|
||||
this.delayed = delayed;
|
||||
}
|
||||
|
||||
public SQLQueryExpr getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public void setQuery(SQLQueryExpr query) {
|
||||
if (query != null) {
|
||||
query.setParent(this);
|
||||
}
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
public List<SQLInsertStatement.ValuesClause> getValuesList() {
|
||||
return valuesList;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void accept0(SQLASTVisitor visitor) {
|
||||
if (visitor.visit(this)) {
|
||||
acceptChild(visitor, tableSource);
|
||||
acceptChild(visitor, columns);
|
||||
acceptChild(visitor, valuesList);
|
||||
acceptChild(visitor, query);
|
||||
}
|
||||
visitor.endVisit(this);
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ import com.alibaba.druid.sql.ast.SQLOrderingSpecification;
|
||||
import com.alibaba.druid.sql.ast.SQLReplaceable;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
|
||||
public class SQLSelectOrderByItem extends SQLObjectImpl implements SQLReplaceable {
|
||||
public final class SQLSelectOrderByItem extends SQLObjectImpl implements SQLReplaceable {
|
||||
|
||||
protected SQLExpr expr;
|
||||
protected String collate;
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.alibaba.druid.sql.dialect.h2.ast;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.ast.SQLStatementImpl;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class H2MergeStatement extends SQLStatementImpl {
|
||||
private SQLExprTableSource table;
|
||||
|
||||
private final List<SQLName> keyColumns = new ArrayList<SQLName>();
|
||||
|
||||
public SQLExprTableSource getTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
public void setTable(SQLName table) {
|
||||
this.setTable(new SQLExprTableSource(table));
|
||||
}
|
||||
|
||||
public void setTable(SQLExprTableSource table) {
|
||||
if (table != null) {
|
||||
table.setParent(this);
|
||||
}
|
||||
this.table = table;
|
||||
}
|
||||
|
||||
public List<SQLName> getKeyColumns() {
|
||||
return keyColumns;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.alibaba.druid.sql.dialect.h2.parser;
|
||||
|
||||
import com.alibaba.druid.sql.parser.Lexer;
|
||||
import com.alibaba.druid.sql.parser.SQLExprParser;
|
||||
import com.alibaba.druid.sql.parser.SQLParserFeature;
|
||||
import com.alibaba.druid.util.FnvHash;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class H2ExprParser extends SQLExprParser {
|
||||
private final static String[] AGGREGATE_FUNCTIONS;
|
||||
private final static long[] AGGREGATE_FUNCTIONS_CODES;
|
||||
|
||||
static {
|
||||
String[] strings = { "AVG", "COUNT", "MAX", "MIN", "STDDEV", "SUM", "ROW_NUMBER",
|
||||
"ROWNUMBER" };
|
||||
AGGREGATE_FUNCTIONS_CODES = FnvHash.fnv1a_64_lower(strings, true);
|
||||
AGGREGATE_FUNCTIONS = new String[AGGREGATE_FUNCTIONS_CODES.length];
|
||||
for (String str : strings) {
|
||||
long hash = FnvHash.fnv1a_64_lower(str);
|
||||
int index = Arrays.binarySearch(AGGREGATE_FUNCTIONS_CODES, hash);
|
||||
AGGREGATE_FUNCTIONS[index] = str;
|
||||
}
|
||||
}
|
||||
|
||||
public H2ExprParser(String sql){
|
||||
this(new H2Lexer(sql));
|
||||
this.lexer.nextToken();
|
||||
}
|
||||
|
||||
public H2ExprParser(String sql, SQLParserFeature... features){
|
||||
this(new H2Lexer(sql, features));
|
||||
this.lexer.nextToken();
|
||||
}
|
||||
|
||||
public H2ExprParser(Lexer lexer){
|
||||
super(lexer);
|
||||
this.aggregateFunctions = AGGREGATE_FUNCTIONS;
|
||||
this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.alibaba.druid.sql.dialect.h2.parser;
|
||||
|
||||
import com.alibaba.druid.sql.parser.Keywords;
|
||||
import com.alibaba.druid.sql.parser.Lexer;
|
||||
import com.alibaba.druid.sql.parser.SQLParserFeature;
|
||||
import com.alibaba.druid.sql.parser.Token;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class H2Lexer extends Lexer {
|
||||
public final static Keywords DEFAULT_H2_KEYWORDS;
|
||||
|
||||
static {
|
||||
Map<String, Token> map = new HashMap<String, Token>();
|
||||
|
||||
map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());
|
||||
|
||||
map.put("OF", Token.OF);
|
||||
map.put("CONCAT", Token.CONCAT);
|
||||
map.put("CONTINUE", Token.CONTINUE);
|
||||
map.put("MERGE", Token.MERGE);
|
||||
map.put("USING", Token.USING);
|
||||
|
||||
map.put("ROW", Token.ROW);
|
||||
|
||||
DEFAULT_H2_KEYWORDS = new Keywords(map);
|
||||
}
|
||||
|
||||
public H2Lexer(String input){
|
||||
super(input);
|
||||
super.keywods = DEFAULT_H2_KEYWORDS;
|
||||
}
|
||||
|
||||
public H2Lexer(String input, SQLParserFeature... features){
|
||||
super(input);
|
||||
super.keywods = DEFAULT_H2_KEYWORDS;
|
||||
for (SQLParserFeature feature : features) {
|
||||
config(feature, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.alibaba.druid.sql.dialect.h2.parser;
|
||||
|
||||
import com.alibaba.druid.sql.parser.SQLExprParser;
|
||||
import com.alibaba.druid.sql.parser.SQLSelectParser;
|
||||
|
||||
public class H2SelectParser extends SQLSelectParser {
|
||||
|
||||
public H2SelectParser(SQLExprParser exprParser){
|
||||
super(exprParser);
|
||||
}
|
||||
|
||||
public H2SelectParser(String sql){
|
||||
this(new H2ExprParser(sql));
|
||||
}
|
||||
|
||||
protected SQLExprParser createExprParser() {
|
||||
return new H2ExprParser(lexer);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.alibaba.druid.sql.dialect.h2.parser;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLReplaceStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelect;
|
||||
import com.alibaba.druid.sql.dialect.h2.ast.H2MergeStatement;
|
||||
import com.alibaba.druid.sql.parser.*;
|
||||
import com.alibaba.druid.util.FnvHash;
|
||||
|
||||
public class H2StatementParser extends SQLStatementParser {
|
||||
public H2StatementParser(String sql) {
|
||||
super (new H2ExprParser(sql));
|
||||
}
|
||||
|
||||
public H2StatementParser(String sql, SQLParserFeature... features) {
|
||||
super (new H2ExprParser(sql, features));
|
||||
}
|
||||
|
||||
public H2StatementParser(Lexer lexer){
|
||||
super(new H2ExprParser(lexer));
|
||||
}
|
||||
|
||||
public H2SelectParser createSQLSelectParser() {
|
||||
return new H2SelectParser(this.exprParser);
|
||||
}
|
||||
|
||||
public SQLStatement parseMerge() {
|
||||
accept(Token.MERGE);
|
||||
accept(Token.INTO);
|
||||
|
||||
SQLReplaceStatement stmt = new SQLReplaceStatement();
|
||||
|
||||
SQLName tableName = exprParser.name();
|
||||
stmt.setTableName(tableName);
|
||||
|
||||
if (lexer.token() == Token.KEY) {
|
||||
lexer.nextToken();
|
||||
accept(Token.LPAREN);
|
||||
this.exprParser.exprList(stmt.getColumns(), stmt);
|
||||
accept(Token.RPAREN);
|
||||
}
|
||||
|
||||
if (lexer.token() == Token.VALUES || lexer.identifierEquals("VALUE")) {
|
||||
lexer.nextToken();
|
||||
|
||||
parseValueClause(stmt.getValuesList(), 0, stmt);
|
||||
} else if (lexer.token() == Token.SELECT) {
|
||||
SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr();
|
||||
stmt.setQuery(queryExpr);
|
||||
} else if (lexer.token() == Token.LPAREN) {
|
||||
SQLSelect select = this.createSQLSelectParser().select();
|
||||
SQLQueryExpr queryExpr = new SQLQueryExpr(select);
|
||||
stmt.setQuery(queryExpr);
|
||||
}
|
||||
|
||||
return stmt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.alibaba.druid.sql.dialect.h2.visitor;
|
||||
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
|
||||
public interface H2ASTVisitor extends SQLASTVisitor {
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.alibaba.druid.sql.dialect.h2.visitor;
|
||||
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;
|
||||
|
||||
public class H2ASTVisitorAdapter extends SQLASTVisitorAdapter implements H2ASTVisitor {
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package com.alibaba.druid.sql.dialect.h2.visitor;
|
||||
|
||||
import com.alibaba.druid.sql.ast.expr.*;
|
||||
import com.alibaba.druid.sql.visitor.SQLEvalVisitor;
|
||||
import com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;
|
||||
import com.alibaba.druid.sql.visitor.functions.Function;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class H2EvalVisitor extends H2ASTVisitorAdapter implements SQLEvalVisitor {
|
||||
private Map<String, Function> functions = new HashMap<String, Function>();
|
||||
private List<Object> parameters = new ArrayList<Object>();
|
||||
|
||||
private int variantIndex = -1;
|
||||
|
||||
private boolean markVariantIndex = true;
|
||||
|
||||
public H2EvalVisitor(){
|
||||
this(new ArrayList<Object>(1));
|
||||
}
|
||||
|
||||
public H2EvalVisitor(List<Object> parameters){
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public List<Object> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public void setParameters(List<Object> parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public boolean visit(SQLCharExpr x) {
|
||||
return SQLEvalVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
public int incrementAndGetVariantIndex() {
|
||||
return ++variantIndex;
|
||||
}
|
||||
|
||||
public int getVariantIndex() {
|
||||
return variantIndex;
|
||||
}
|
||||
|
||||
public boolean visit(SQLVariantRefExpr x) {
|
||||
return SQLEvalVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
public boolean visit(SQLBinaryOpExpr x) {
|
||||
return SQLEvalVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
public boolean visit(SQLUnaryExpr x) {
|
||||
return SQLEvalVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
public boolean visit(SQLIntegerExpr x) {
|
||||
return SQLEvalVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
public boolean visit(SQLNumberExpr x) {
|
||||
return SQLEvalVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLCaseExpr x) {
|
||||
return SQLEvalVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLInListExpr x) {
|
||||
return SQLEvalVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLNullExpr x) {
|
||||
return SQLEvalVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLMethodInvokeExpr x) {
|
||||
return SQLEvalVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLQueryExpr x) {
|
||||
return SQLEvalVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
public boolean isMarkVariantIndex() {
|
||||
return markVariantIndex;
|
||||
}
|
||||
|
||||
public void setMarkVariantIndex(boolean markVariantIndex) {
|
||||
this.markVariantIndex = markVariantIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function getFunction(String funcName) {
|
||||
return functions.get(funcName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerFunction(String funcName, Function function) {
|
||||
functions.put(funcName, function);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterFunction(String funcName) {
|
||||
functions.remove(funcName);
|
||||
}
|
||||
|
||||
public boolean visit(SQLIdentifierExpr x) {
|
||||
return SQLEvalVisitorUtils.visit(this, x);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.alibaba.druid.sql.dialect.h2.visitor;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLReplaceStatement;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class H2OutputVisitor extends SQLASTOutputVisitor implements H2ASTVisitor {
|
||||
public H2OutputVisitor(Appendable appender) {
|
||||
super(appender);
|
||||
}
|
||||
|
||||
public H2OutputVisitor(Appendable appender, String dbType) {
|
||||
super(appender, dbType);
|
||||
}
|
||||
|
||||
public H2OutputVisitor(Appendable appender, boolean parameterized) {
|
||||
super(appender, parameterized);
|
||||
}
|
||||
|
||||
public boolean visit(SQLReplaceStatement x) {
|
||||
print0(ucase ? "MERGE INTO " : "merge into ");
|
||||
|
||||
printTableSourceExpr(x.getTableName());
|
||||
|
||||
List<SQLExpr> columns = x.getColumns();
|
||||
if (columns.size() > 0) {
|
||||
print0(ucase ? " KEY (" : " key (");
|
||||
for (int i = 0, size = columns.size(); i < size; ++i) {
|
||||
if (i != 0) {
|
||||
print0(", ");
|
||||
}
|
||||
|
||||
SQLExpr columnn = columns.get(i);
|
||||
printExpr(columnn);
|
||||
}
|
||||
print(')');
|
||||
}
|
||||
|
||||
List<SQLInsertStatement.ValuesClause> valuesClauseList = x.getValuesList();
|
||||
if (valuesClauseList.size() != 0) {
|
||||
println();
|
||||
print0(ucase ? "VALUES " : "values ");
|
||||
int size = valuesClauseList.size();
|
||||
if (size == 0) {
|
||||
print0("()");
|
||||
} else {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
if (i != 0) {
|
||||
print0(", ");
|
||||
}
|
||||
visit(valuesClauseList.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SQLQueryExpr query = x.getQuery();
|
||||
if (query != null) {
|
||||
visit(query);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.alibaba.druid.sql.dialect.h2.visitor;
|
||||
|
||||
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
|
||||
|
||||
public class H2SchemaStatVisitor extends SchemaStatVisitor implements H2ASTVisitor {
|
||||
}
|
||||
@@ -504,7 +504,7 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
}
|
||||
|
||||
if (lexer.token() == Token.REPLACE) {
|
||||
MySqlReplaceStatement stmt = parseReplicate();
|
||||
SQLReplaceStatement stmt = parseReplace();
|
||||
statementList.add(stmt);
|
||||
return true;
|
||||
}
|
||||
@@ -1773,8 +1773,8 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
return stmt;
|
||||
}
|
||||
|
||||
public MySqlReplaceStatement parseReplicate() {
|
||||
MySqlReplaceStatement stmt = new MySqlReplaceStatement();
|
||||
public SQLReplaceStatement parseReplace() {
|
||||
SQLReplaceStatement stmt = new SQLReplaceStatement();
|
||||
|
||||
accept(Token.REPLACE);
|
||||
|
||||
@@ -2262,95 +2262,6 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
return insertStatement;
|
||||
}
|
||||
|
||||
private void parseValueClause(List<ValuesClause> valueClauseList, int columnSize, SQLObject parent) {
|
||||
for (int i = 0; ; ++i) {
|
||||
int startPos = lexer.pos() - 1;
|
||||
|
||||
if (lexer.token() != Token.LPAREN) {
|
||||
throw new ParserException("syntax error, expect ')', " + lexer.info());
|
||||
}
|
||||
lexer.nextTokenValue();
|
||||
|
||||
if (lexer.token() != Token.RPAREN) {
|
||||
List<SQLExpr> valueExprList;
|
||||
if (columnSize > 0) {
|
||||
valueExprList = new ArrayList<SQLExpr>(columnSize);
|
||||
} else {
|
||||
valueExprList = new ArrayList<SQLExpr>();
|
||||
}
|
||||
|
||||
for (; ; ) {
|
||||
SQLExpr expr;
|
||||
if (lexer.token() == Token.LITERAL_INT) {
|
||||
expr = new SQLIntegerExpr(lexer.integerValue());
|
||||
lexer.nextTokenComma();
|
||||
} else if (lexer.token() == Token.LITERAL_CHARS) {
|
||||
expr = new SQLCharExpr(lexer.stringVal());
|
||||
lexer.nextTokenComma();
|
||||
} else if (lexer.token() == Token.LITERAL_NCHARS) {
|
||||
expr = new SQLNCharExpr(lexer.stringVal());
|
||||
lexer.nextTokenComma();
|
||||
} else {
|
||||
expr = exprParser.expr();
|
||||
}
|
||||
|
||||
if (lexer.token() == Token.COMMA) {
|
||||
valueExprList.add(expr);
|
||||
lexer.nextTokenValue();
|
||||
continue;
|
||||
} else if (lexer.token() == Token.RPAREN) {
|
||||
valueExprList.add(expr);
|
||||
break;
|
||||
} else {
|
||||
expr = this.exprParser.primaryRest(expr);
|
||||
if (lexer.token() != Token.COMMA && lexer.token() != Token.RPAREN) {
|
||||
expr = this.exprParser.exprRest(expr);
|
||||
}
|
||||
|
||||
valueExprList.add(expr);
|
||||
if (lexer.token() == Token.COMMA) {
|
||||
lexer.nextToken();
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause(valueExprList);
|
||||
values.setParent(parent);
|
||||
|
||||
if (lexer.isEnabled(SQLParserFeature.KeepInsertValueClauseOriginalString)) {
|
||||
int endPos = lexer.pos();
|
||||
String orginalString = lexer.subString(startPos, endPos - startPos);
|
||||
values.setOriginalString(orginalString);
|
||||
}
|
||||
|
||||
valueClauseList.add(values);
|
||||
} else {
|
||||
SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause(new ArrayList<SQLExpr>(0));
|
||||
valueClauseList.add(values);
|
||||
}
|
||||
|
||||
if (lexer.token() != Token.RPAREN) {
|
||||
throw new ParserException("syntax error. " + lexer.info());
|
||||
}
|
||||
|
||||
if (!parseCompleteValues && valueClauseList.size() >= parseValuesSize) {
|
||||
lexer.skipToEOF();
|
||||
break;
|
||||
}
|
||||
|
||||
lexer.nextTokenComma();
|
||||
if (lexer.token() == Token.COMMA) {
|
||||
lexer.nextTokenLParen();
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SQLSelectParser createSQLSelectParser() {
|
||||
return new MySqlSelectParser(this.exprParser);
|
||||
}
|
||||
|
||||
@@ -103,10 +103,6 @@ public interface MySqlASTVisitor extends SQLASTVisitor {
|
||||
|
||||
boolean visit(MySqlLoadXmlStatement x);
|
||||
|
||||
void endVisit(MySqlReplaceStatement x);
|
||||
|
||||
boolean visit(MySqlReplaceStatement x);
|
||||
|
||||
void endVisit(MySqlShowColumnsStatement x);
|
||||
|
||||
boolean visit(MySqlShowColumnsStatement x);
|
||||
|
||||
@@ -186,17 +186,6 @@ public class MySqlASTVisitorAdapter extends SQLASTVisitorAdapter implements MySq
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(MySqlReplaceStatement x) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(MySqlReplaceStatement x) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(MySqlShowColumnsStatement x) {
|
||||
|
||||
|
||||
@@ -803,20 +803,22 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
|
||||
print0(ucase ? "IGNORE " : "ignore ");
|
||||
}
|
||||
|
||||
if (x.getFrom() == null) {
|
||||
SQLTableSource from = x.getFrom();
|
||||
if (from == null) {
|
||||
print0(ucase ? "FROM " : "from ");
|
||||
x.getTableSource().accept(this);
|
||||
} else {
|
||||
x.getTableSource().accept(this);
|
||||
println();
|
||||
print0(ucase ? "FROM " : "from ");
|
||||
x.getFrom().accept(this);
|
||||
from.accept(this);
|
||||
}
|
||||
|
||||
if (x.getUsing() != null) {
|
||||
SQLTableSource using = x.getUsing();
|
||||
if (using != null) {
|
||||
println();
|
||||
print0(ucase ? "USING " : "using ");
|
||||
x.getUsing().accept(this);
|
||||
using.accept(this);
|
||||
}
|
||||
|
||||
SQLExpr where = x.getWhere();
|
||||
@@ -894,7 +896,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
|
||||
|
||||
SQLExpr column = columns.get(i);
|
||||
if (column instanceof SQLIdentifierExpr) {
|
||||
visit((SQLIdentifierExpr) column);
|
||||
print0(((SQLIdentifierExpr) column).getName());
|
||||
} else {
|
||||
printExpr(column);
|
||||
}
|
||||
@@ -1053,13 +1055,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(MySqlReplaceStatement x) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(MySqlReplaceStatement x) {
|
||||
public boolean visit(SQLReplaceStatement x) {
|
||||
print0(ucase ? "REPLACE " : "replace ");
|
||||
|
||||
if (x.isLowPriority()) {
|
||||
@@ -1574,9 +1570,10 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
|
||||
|
||||
@Override
|
||||
public boolean visit(MySqlUpdateStatement x) {
|
||||
if (x.getReturning() != null && x.getReturning().size() > 0) {
|
||||
List<SQLExpr> returning = x.getReturning();
|
||||
if (returning != null && returning.size() > 0) {
|
||||
print0(ucase ? "SELECT " : "select ");
|
||||
printAndAccept(x.getReturning(), ", ");
|
||||
printAndAccept(returning, ", ");
|
||||
println();
|
||||
print0(ucase ? "FROM " : "from ");
|
||||
}
|
||||
@@ -1614,11 +1611,12 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
|
||||
|
||||
println();
|
||||
print0(ucase ? "SET " : "set ");
|
||||
for (int i = 0, size = x.getItems().size(); i < size; ++i) {
|
||||
List<SQLUpdateSetItem> items = x.getItems();
|
||||
for (int i = 0, size = items.size(); i < size; ++i) {
|
||||
if (i != 0) {
|
||||
print0(", ");
|
||||
}
|
||||
SQLUpdateSetItem item = x.getItems().get(i);
|
||||
SQLUpdateSetItem item = items.get(i);
|
||||
visit(item);
|
||||
}
|
||||
|
||||
@@ -3007,26 +3005,31 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLBlockStatement x) {
|
||||
if (x.getLabelName() != null && !x.getLabelName().equals("")) {
|
||||
print0(x.getLabelName());
|
||||
SQLObject parent = x.getParent();
|
||||
String labelName = x.getLabelName();
|
||||
|
||||
if (labelName != null && !labelName.equals("")) {
|
||||
print0(labelName);
|
||||
print0(": ");
|
||||
}
|
||||
if (x.getParameters().size() != 0) {
|
||||
|
||||
List<SQLParameter> parameters = x.getParameters();
|
||||
if (parameters.size() != 0) {
|
||||
this.indentCount++;
|
||||
if (x.getParent() instanceof SQLCreateProcedureStatement) {
|
||||
if (parent instanceof SQLCreateProcedureStatement) {
|
||||
printIndent();
|
||||
}
|
||||
if (!(x.getParent() instanceof SQLCreateProcedureStatement)) {
|
||||
if (!(parent instanceof SQLCreateProcedureStatement)) {
|
||||
print0(ucase ? "DECLARE" : "declare");
|
||||
println();
|
||||
}
|
||||
|
||||
for (int i = 0, size = x.getParameters().size(); i < size; ++i) {
|
||||
for (int i = 0, size = parameters.size(); i < size; ++i) {
|
||||
if (i != 0) {
|
||||
println();
|
||||
}
|
||||
SQLParameter param = x.getParameters().get(i);
|
||||
param.accept(this);
|
||||
SQLParameter param = parameters.get(i);
|
||||
visit(param);
|
||||
print(';');
|
||||
}
|
||||
|
||||
@@ -3036,19 +3039,20 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
|
||||
print0(ucase ? "BEGIN" : "begin");
|
||||
this.indentCount++;
|
||||
println();
|
||||
for (int i = 0, size = x.getStatementList().size(); i < size; ++i) {
|
||||
List<SQLStatement> statementList = x.getStatementList();
|
||||
for (int i = 0, size = statementList.size(); i < size; ++i) {
|
||||
if (i != 0) {
|
||||
println();
|
||||
}
|
||||
SQLStatement stmt = x.getStatementList().get(i);
|
||||
SQLStatement stmt = statementList.get(i);
|
||||
stmt.accept(this);
|
||||
}
|
||||
this.indentCount--;
|
||||
println();
|
||||
print0(ucase ? "END" : "end");
|
||||
if (x.getLabelName() != null && !x.getLabelName().equals("")) {
|
||||
if (labelName != null && !labelName.equals("")) {
|
||||
print(' ');
|
||||
print0(x.getLabelName());
|
||||
print0(labelName);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -3060,8 +3064,9 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
|
||||
print0(ucase ? " THEN" : " then");
|
||||
this.indentCount++;
|
||||
println();
|
||||
for (int i = 0, size = x.getStatements().size(); i < size; ++i) {
|
||||
SQLStatement item = x.getStatements().get(i);
|
||||
List<SQLStatement> statements = x.getStatements();
|
||||
for (int i = 0, size = statements.size(); i < size; ++i) {
|
||||
SQLStatement item = statements.get(i);
|
||||
item.accept(this);
|
||||
if (i != size - 1) {
|
||||
println();
|
||||
@@ -3073,7 +3078,9 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
|
||||
iterable_element.accept(this);
|
||||
}
|
||||
|
||||
if (x.getElseItem() != null) x.getElseItem().accept(this);
|
||||
if (x.getElseItem() != null) {
|
||||
x.getElseItem().accept(this);
|
||||
}
|
||||
|
||||
print0(ucase ? "END IF" : "end if");
|
||||
return false;
|
||||
|
||||
@@ -259,35 +259,6 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(MySqlReplaceStatement x) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(MySqlReplaceStatement x) {
|
||||
if (repository != null
|
||||
&& x.getParent() == null) {
|
||||
repository.resolve(x);
|
||||
}
|
||||
|
||||
setMode(x, Mode.Replace);
|
||||
|
||||
SQLName tableName = x.getTableName();
|
||||
|
||||
TableStat stat = getTableStat(tableName);
|
||||
|
||||
if (stat != null) {
|
||||
stat.incrementInsertCount();
|
||||
}
|
||||
|
||||
accept(x.getColumns());
|
||||
accept(x.getValuesList());
|
||||
accept(x.getQuery());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(SQLStartTransactionStatement x) {
|
||||
|
||||
|
||||
@@ -97,19 +97,21 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
|
||||
space = true;
|
||||
}
|
||||
|
||||
if (x.getOrderBy() != null) {
|
||||
SQLOrderBy orderBy = x.getOrderBy();
|
||||
if (orderBy != null) {
|
||||
if (space) {
|
||||
print(' ');
|
||||
}
|
||||
x.getOrderBy().accept(this);
|
||||
visit(orderBy);
|
||||
space = true;
|
||||
}
|
||||
|
||||
if (x.getWindowing() != null) {
|
||||
OracleAnalyticWindowing windowing = x.getWindowing();
|
||||
if (windowing != null) {
|
||||
if (space) {
|
||||
print(' ');
|
||||
}
|
||||
x.getWindowing().accept(this);
|
||||
visit(windowing);
|
||||
}
|
||||
|
||||
print(')');
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.alibaba.druid.sql.parser;
|
||||
import com.alibaba.druid.sql.dialect.db2.parser.DB2ExprParser;
|
||||
import com.alibaba.druid.sql.dialect.db2.parser.DB2Lexer;
|
||||
import com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;
|
||||
import com.alibaba.druid.sql.dialect.h2.parser.H2StatementParser;
|
||||
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlExprParser;
|
||||
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlLexer;
|
||||
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
|
||||
@@ -85,7 +86,7 @@ public class SQLParserUtils {
|
||||
}
|
||||
|
||||
if (JdbcUtils.H2.equals(dbType)) {
|
||||
return new MySqlStatementParser(sql);
|
||||
return new H2StatementParser(sql);
|
||||
}
|
||||
|
||||
if (JdbcUtils.DB2.equals(dbType)) {
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.alibaba.druid.sql.ast.*;
|
||||
import com.alibaba.druid.sql.ast.expr.*;
|
||||
import com.alibaba.druid.sql.ast.statement.*;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement.TriggerType;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;
|
||||
import com.alibaba.druid.util.FnvHash;
|
||||
import com.alibaba.druid.util.JdbcConstants;
|
||||
@@ -2600,7 +2599,7 @@ public class SQLStatementParser extends SQLParser {
|
||||
this.parseValuesSize = parseValuesSize;
|
||||
}
|
||||
|
||||
public SQLMergeStatement parseMerge() {
|
||||
public SQLStatement parseMerge() {
|
||||
accept(Token.MERGE);
|
||||
|
||||
SQLMergeStatement stmt = new SQLMergeStatement();
|
||||
@@ -2870,4 +2869,93 @@ public class SQLStatementParser extends SQLParser {
|
||||
|
||||
throw new ParserException("TODO. " + lexer.info());
|
||||
}
|
||||
|
||||
protected void parseValueClause(List<SQLInsertStatement.ValuesClause> valueClauseList, int columnSize, SQLObject parent) {
|
||||
for (int i = 0; ; ++i) {
|
||||
int startPos = lexer.pos() - 1;
|
||||
|
||||
if (lexer.token() != Token.LPAREN) {
|
||||
throw new ParserException("syntax error, expect ')', " + lexer.info());
|
||||
}
|
||||
lexer.nextTokenValue();
|
||||
|
||||
if (lexer.token() != Token.RPAREN) {
|
||||
List<SQLExpr> valueExprList;
|
||||
if (columnSize > 0) {
|
||||
valueExprList = new ArrayList<SQLExpr>(columnSize);
|
||||
} else {
|
||||
valueExprList = new ArrayList<SQLExpr>();
|
||||
}
|
||||
|
||||
for (; ; ) {
|
||||
SQLExpr expr;
|
||||
if (lexer.token() == Token.LITERAL_INT) {
|
||||
expr = new SQLIntegerExpr(lexer.integerValue());
|
||||
lexer.nextTokenComma();
|
||||
} else if (lexer.token() == Token.LITERAL_CHARS) {
|
||||
expr = new SQLCharExpr(lexer.stringVal());
|
||||
lexer.nextTokenComma();
|
||||
} else if (lexer.token() == Token.LITERAL_NCHARS) {
|
||||
expr = new SQLNCharExpr(lexer.stringVal());
|
||||
lexer.nextTokenComma();
|
||||
} else {
|
||||
expr = exprParser.expr();
|
||||
}
|
||||
|
||||
if (lexer.token() == Token.COMMA) {
|
||||
valueExprList.add(expr);
|
||||
lexer.nextTokenValue();
|
||||
continue;
|
||||
} else if (lexer.token() == Token.RPAREN) {
|
||||
valueExprList.add(expr);
|
||||
break;
|
||||
} else {
|
||||
expr = this.exprParser.primaryRest(expr);
|
||||
if (lexer.token() != Token.COMMA && lexer.token() != Token.RPAREN) {
|
||||
expr = this.exprParser.exprRest(expr);
|
||||
}
|
||||
|
||||
valueExprList.add(expr);
|
||||
if (lexer.token() == Token.COMMA) {
|
||||
lexer.nextToken();
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause(valueExprList);
|
||||
values.setParent(parent);
|
||||
|
||||
if (lexer.isEnabled(SQLParserFeature.KeepInsertValueClauseOriginalString)) {
|
||||
int endPos = lexer.pos();
|
||||
String orginalString = lexer.subString(startPos, endPos - startPos);
|
||||
values.setOriginalString(orginalString);
|
||||
}
|
||||
|
||||
valueClauseList.add(values);
|
||||
} else {
|
||||
SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause(new ArrayList<SQLExpr>(0));
|
||||
valueClauseList.add(values);
|
||||
}
|
||||
|
||||
if (lexer.token() != Token.RPAREN) {
|
||||
throw new ParserException("syntax error. " + lexer.info());
|
||||
}
|
||||
|
||||
if (!parseCompleteValues && valueClauseList.size() >= parseValuesSize) {
|
||||
lexer.skipToEOF();
|
||||
break;
|
||||
}
|
||||
|
||||
lexer.nextTokenComma();
|
||||
if (lexer.token() == Token.COMMA) {
|
||||
lexer.nextTokenLParen();
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,23 +169,8 @@ class SchemaResolveVisitorFactory {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean visit(MySqlReplaceStatement x) {
|
||||
Context ctx = createContext(x);
|
||||
|
||||
SQLExprTableSource tableSource = x.getTableSource();
|
||||
ctx.setTableSource(tableSource);
|
||||
visit(tableSource);
|
||||
|
||||
for (SQLExpr column : x.getColumns()) {
|
||||
column.accept(this);
|
||||
}
|
||||
|
||||
SQLQueryExpr queryExpr = x.getQuery();
|
||||
if (queryExpr != null) {
|
||||
visit(queryExpr.getSubQuery());
|
||||
}
|
||||
|
||||
popContext();
|
||||
public boolean visit(SQLReplaceStatement x) {
|
||||
resolve(this, x);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1339,6 +1324,11 @@ class SchemaResolveVisitorFactory {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean visit(SQLReplaceStatement x) {
|
||||
resolve(this, x);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(Option option) {
|
||||
return (options & option.mask) != 0;
|
||||
@@ -2444,6 +2434,25 @@ class SchemaResolveVisitorFactory {
|
||||
return false;
|
||||
}
|
||||
|
||||
static void resolve(SchemaResolveVisitor visitor, SQLReplaceStatement x) {
|
||||
SchemaResolveVisitor.Context ctx = visitor.createContext(x);
|
||||
|
||||
SQLExprTableSource tableSource = x.getTableSource();
|
||||
ctx.setTableSource(tableSource);
|
||||
visitor.visit(tableSource);
|
||||
|
||||
for (SQLExpr column : x.getColumns()) {
|
||||
column.accept(visitor);
|
||||
}
|
||||
|
||||
SQLQueryExpr queryExpr = x.getQuery();
|
||||
if (queryExpr != null) {
|
||||
visitor.visit(queryExpr.getSubQuery());
|
||||
}
|
||||
|
||||
visitor.popContext();
|
||||
}
|
||||
|
||||
static void resolve(SchemaResolveVisitor visitor, SQLForeignKeyConstraint x) {
|
||||
SchemaRepository repository = visitor.getRepository();
|
||||
SQLObject parent = x.getParent();
|
||||
|
||||
@@ -426,7 +426,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
|
||||
// ////////////////////
|
||||
|
||||
public boolean visit(SQLBetweenExpr x) {
|
||||
x.getTestExpr().accept(this);
|
||||
printExpr(x.getTestExpr());
|
||||
|
||||
if (x.isNot()) {
|
||||
print0(ucase ? " NOT BETWEEN " : " not between ");
|
||||
@@ -1154,9 +1154,9 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
|
||||
printExpr(x.getExpr());
|
||||
|
||||
if (x.isNot()) {
|
||||
print(isUppCase() ? " NOT IN (?)" : " not in (?)");
|
||||
print(ucase ? " NOT IN (?)" : " not in (?)");
|
||||
} else {
|
||||
print(isUppCase() ? " IN (?)" : " in (?)");
|
||||
print(ucase ? " IN (?)" : " in (?)");
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
@@ -1296,7 +1296,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
|
||||
if (i != 0) {
|
||||
print0(", ");
|
||||
}
|
||||
SQLExpr param = x.getParameters().get(i);
|
||||
SQLExpr param = parameters.get(i);
|
||||
|
||||
if (this.parameterized) {
|
||||
if (size == 2 && i == 1 && param instanceof SQLCharExpr) {
|
||||
@@ -1365,11 +1365,13 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
|
||||
boolean parameterized = this.parameterized;
|
||||
this.parameterized = false;
|
||||
|
||||
print0(ucase ? x.getMethodName() : x.getMethodName().toLowerCase());
|
||||
String methodName = x.getMethodName();
|
||||
print0(ucase ? methodName : methodName.toLowerCase());
|
||||
print('(');
|
||||
|
||||
if (x.getOption() != null) {
|
||||
print0(x.getOption().toString());
|
||||
SQLAggregateOption option = x.getOption();
|
||||
if (option != null) {
|
||||
print0(option.toString());
|
||||
print(' ');
|
||||
}
|
||||
|
||||
@@ -1388,19 +1390,20 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
|
||||
SQLOrderBy withGroup = x.getWithinGroup();
|
||||
if (withGroup != null) {
|
||||
print0(ucase ? " WITHIN GROUP (" : " within group (");
|
||||
withGroup.accept(this);
|
||||
visit(withGroup);
|
||||
print(')');
|
||||
}
|
||||
|
||||
SQLKeep keep = x.getKeep();
|
||||
if (keep != null) {
|
||||
print(' ');
|
||||
keep.accept(this);
|
||||
visit(keep);
|
||||
}
|
||||
|
||||
if (x.getOver() != null) {
|
||||
SQLOver over = x.getOver();
|
||||
if (over != null) {
|
||||
print(' ');
|
||||
x.getOver().accept(this);
|
||||
over.accept(this);
|
||||
}
|
||||
|
||||
this.parameterized = parameterized;
|
||||
@@ -2449,9 +2452,10 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
|
||||
|
||||
printTableElements(x.getTableElementList());
|
||||
|
||||
if (x.getInherits() != null) {
|
||||
SQLExprTableSource inherits = x.getInherits();
|
||||
if (inherits != null) {
|
||||
print0(ucase ? " INHERITS (" : " inherits (");
|
||||
x.getInherits().accept(this);
|
||||
inherits.accept(this);
|
||||
print(')');
|
||||
}
|
||||
|
||||
@@ -2473,26 +2477,27 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
|
||||
}
|
||||
|
||||
print0(ucase ? "UNIQUE (" : "unique (");
|
||||
for (int i = 0, size = x.getColumns().size(); i < size; ++i) {
|
||||
List<SQLSelectOrderByItem> columns = x.getColumns();
|
||||
for (int i = 0, size = columns.size(); i < size; ++i) {
|
||||
if (i != 0) {
|
||||
print0(", ");
|
||||
}
|
||||
x.getColumns().get(i).accept(this);
|
||||
visit(columns.get(i));
|
||||
}
|
||||
print(')');
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean visit(SQLNotNullConstraint x) {
|
||||
if (x.getName() != null) {
|
||||
SQLName name = x.getName();
|
||||
if (name != null) {
|
||||
print0(ucase ? "CONSTRAINT " : "constraint ");
|
||||
x.getName().accept(this);
|
||||
name.accept(this);
|
||||
print(' ');
|
||||
}
|
||||
print0(ucase ? "NOT NULL" : "not null");
|
||||
|
||||
List<SQLCommentHint> hints = x.hints;
|
||||
|
||||
if (hints != null) {
|
||||
print(' ');
|
||||
for (SQLCommentHint hint : hints) {
|
||||
@@ -2504,9 +2509,10 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
|
||||
}
|
||||
|
||||
public boolean visit(SQLNullConstraint x) {
|
||||
if (x.getName() != null) {
|
||||
SQLName name = x.getName();
|
||||
if (name != null) {
|
||||
print0(ucase ? "CONSTRAINT " : "constraint ");
|
||||
x.getName().accept(this);
|
||||
name.accept(this);
|
||||
print(' ');
|
||||
}
|
||||
print0(ucase ? "NULL" : "null");
|
||||
|
||||
@@ -739,7 +739,11 @@ public interface SQLASTVisitor {
|
||||
|
||||
void endVisit(SQLBinaryOpExprGroup x);
|
||||
|
||||
boolean visit(SQLScriptCommitStatement astNode);
|
||||
boolean visit(SQLScriptCommitStatement x);
|
||||
|
||||
void endVisit(SQLScriptCommitStatement astNode);
|
||||
void endVisit(SQLScriptCommitStatement x);
|
||||
|
||||
boolean visit(SQLReplaceStatement x);
|
||||
|
||||
void endVisit(SQLReplaceStatement x);
|
||||
}
|
||||
|
||||
@@ -1695,7 +1695,17 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(SQLScriptCommitStatement astNode) {
|
||||
public void endVisit(SQLScriptCommitStatement x) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLReplaceStatement x) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(SQLReplaceStatement x) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1983,6 +1983,8 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter {
|
||||
}
|
||||
|
||||
public boolean visit(SQLCreateTriggerStatement x) {
|
||||
SQLExprTableSource on = x.getOn();
|
||||
on.accept(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2306,6 +2308,29 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(SQLReplaceStatement x) {
|
||||
if (repository != null
|
||||
&& x.getParent() == null) {
|
||||
repository.resolve(x);
|
||||
}
|
||||
|
||||
setMode(x, Mode.Replace);
|
||||
|
||||
SQLName tableName = x.getTableName();
|
||||
|
||||
TableStat stat = getTableStat(tableName);
|
||||
|
||||
if (stat != null) {
|
||||
stat.incrementInsertCount();
|
||||
}
|
||||
|
||||
accept(x.getColumns());
|
||||
accept(x.getValuesList());
|
||||
accept(x.getQuery());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected final void statExpr(SQLExpr x) {
|
||||
Class<?> clazz = x.getClass();
|
||||
if (clazz == SQLIdentifierExpr.class) {
|
||||
|
||||
@@ -34,7 +34,6 @@ import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlReplaceStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.ast.SQLLimit;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowCreateTableStatement;
|
||||
@@ -402,11 +401,6 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(MySqlReplaceStatement x) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLCallStatement x) {
|
||||
return false;
|
||||
|
||||
@@ -2181,7 +2181,7 @@ public class WallVisitorUtils {
|
||||
tableStat.incrementDeleteCount();
|
||||
} else if (parent instanceof SQLUpdateStatement) {
|
||||
tableStat.incrementUpdateCount();
|
||||
} else if (parent instanceof MySqlReplaceStatement) {
|
||||
} else if (parent instanceof SQLReplaceStatement) {
|
||||
tableStat.incrementReplaceCount();
|
||||
}
|
||||
}
|
||||
@@ -2512,7 +2512,7 @@ public class WallVisitorUtils {
|
||||
allow = config.isSetAllow();
|
||||
denyMessage = "set not allow";
|
||||
errorCode = ErrorCode.SET_NOT_ALLOW;
|
||||
} else if (x instanceof MySqlReplaceStatement) {
|
||||
} else if (x instanceof SQLReplaceStatement) {
|
||||
allow = config.isReplaceAllow();
|
||||
denyMessage = "replace not allow";
|
||||
errorCode = ErrorCode.REPLACE_NOT_ALLOW;
|
||||
|
||||
Reference in New Issue
Block a user