improved sql parsre.

This commit is contained in:
wenshao
2017-10-11 19:59:45 +08:00
parent 2d88d76e80
commit c6cbb328ea
233 changed files with 3589 additions and 182 deletions
@@ -37,7 +37,7 @@ public class SQLAggregateExpr extends SQLExprImpl implements Serializable, SQLRe
protected SQLKeep keep;
protected SQLOver over;
protected SQLOrderBy withinGroup;
protected boolean ignoreNulls = false;
protected Boolean ignoreNulls = false;
public SQLAggregateExpr(String methodName){
this.methodName = methodName;
@@ -117,6 +117,10 @@ public class SQLAggregateExpr extends SQLExprImpl implements Serializable, SQLRe
}
public boolean isIgnoreNulls() {
return this.ignoreNulls != null && this.ignoreNulls;
}
public Boolean getIgnoreNulls() {
return this.ignoreNulls;
}
@@ -23,8 +23,9 @@ package com.alibaba.druid.sql.ast.expr;
public enum SQLBinaryOperator {
Union("UNION", 0),
COLLATE("COLLATE", 20),
BitwiseXor("^", 50),
BitwiseXor("^", 50),
BitwiseXorEQ("^=", 110),
Multiply("*", 60),
Divide("/", 60),
DIV("DIV", 60), // mysql integer division
@@ -70,7 +71,7 @@ public enum SQLBinaryOperator {
Array_Contains("@>", 110),
Array_ContainedBy("<@", 110),
SAME_AS("~=", 110),
RLike("RLIKE", 110),
NotRLike("NOT RLIKE", 110),
@@ -149,4 +150,19 @@ public enum SQLBinaryOperator {
public boolean isLogical() {
return this == BooleanAnd || this == BooleanOr || this == BooleanXor;
}
public boolean isArithmetic() {
switch (this) {
case Add:
case Subtract:
case Multiply:
case Divide:
case DIV:
case Modulus:
case Mod:
return true;
default:
return false;
}
}
}
@@ -1025,4 +1025,14 @@ public class OracleToMySqlOutputVisitor extends MySqlOutputVisitor implements Or
public void endVisit(OraclePipeRowStatement x) {
}
@Override
public boolean visit(OracleIsOfTypeExpr x) {
return false;
}
@Override
public void endVisit(OracleIsOfTypeExpr x) {
}
}
@@ -15,6 +15,7 @@
*/
package com.alibaba.druid.sql.dialect.oracle.ast;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLDataType;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLObjectImpl;
@@ -41,4 +42,8 @@ public abstract class OracleSQLObjectImpl extends SQLObjectImpl implements Oracl
public SQLDataType computeDataType() {
return null;
}
public String toString() {
return SQLUtils.toOracleString(this);
}
}
@@ -19,10 +19,14 @@ import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLExprImpl;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.SQLOrderBy;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleExpr;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class ModelClause extends OracleSQLObjectImpl {
@@ -391,7 +395,7 @@ public class ModelClause extends OracleSQLObjectImpl {
}
public static class CellAssignment extends OracleSQLObjectImpl {
public static class CellAssignment extends SQLExprImpl implements OracleExpr {
private SQLExpr measureColumn;
private final List<SQLExpr> conditions = new ArrayList<SQLExpr>();
@@ -404,8 +408,11 @@ public class ModelClause extends OracleSQLObjectImpl {
return measureColumn;
}
public void setMeasureColumn(SQLExpr measureColumn) {
this.measureColumn = measureColumn;
public void setMeasureColumn(SQLExpr e) {
if (e != null) {
e.setParent(this);
}
this.measureColumn = e;
}
@Override
@@ -417,6 +424,46 @@ public class ModelClause extends OracleSQLObjectImpl {
visitor.endVisit(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CellAssignment that = (CellAssignment) o;
if (measureColumn != null ? !measureColumn.equals(that.measureColumn) : that.measureColumn != null)
return false;
return conditions != null ? conditions.equals(that.conditions) : that.conditions == null;
}
@Override
public int hashCode() {
int result = measureColumn != null ? measureColumn.hashCode() : 0;
result = 31 * result + (conditions != null ? conditions.hashCode() : 0);
return result;
}
@Override
protected void accept0(SQLASTVisitor visitor) {
accept0((OracleASTVisitor) visitor);
}
@Override
public SQLExpr clone() {
CellAssignment x = new CellAssignment();
if (measureColumn != null) {
x.setMeasureColumn(measureColumn.clone());
}
return null;
}
@Override
public List<SQLObject> getChildren() {
List children = new ArrayList();
children.add(measureColumn);
children.addAll(conditions);
return children;
}
}
public ModelClause clone() {
@@ -18,6 +18,7 @@ package com.alibaba.druid.sql.dialect.oracle.ast.expr;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLExprImpl;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
@@ -29,10 +30,10 @@ public class OracleIntervalExpr extends SQLExprImpl implements SQLLiteralExpr, O
private SQLExpr value;
private OracleIntervalType type;
private Integer precision;
private SQLExpr precision;
private Integer factionalSecondsPrecision;
private OracleIntervalType toType;
private Integer toFactionalSecondsPrecision;
private SQLExpr toFactionalSecondsPrecision;
public OracleIntervalExpr(){
@@ -72,11 +73,18 @@ public class OracleIntervalExpr extends SQLExprImpl implements SQLLiteralExpr, O
this.type = type;
}
public Integer getPrecision() {
public SQLExpr getPrecision() {
return this.precision;
}
public void setPrecision(Integer precision) {
this.setPrecision(new SQLIntegerExpr(precision));
}
public void setPrecision(SQLExpr precision) {
if (precision != null) {
precision.setParent(this);
}
this.precision = precision;
}
@@ -96,12 +104,15 @@ public class OracleIntervalExpr extends SQLExprImpl implements SQLLiteralExpr, O
this.toType = toType;
}
public Integer getToFactionalSecondsPrecision() {
public SQLExpr getToFactionalSecondsPrecision() {
return this.toFactionalSecondsPrecision;
}
public void setToFactionalSecondsPrecision(Integer toFactionalSecondsPrecision) {
this.toFactionalSecondsPrecision = toFactionalSecondsPrecision;
public void setToFactionalSecondsPrecision(SQLExpr x) {
if (x != null) {
x.setParent(this);
}
this.toFactionalSecondsPrecision = x;
}
@Override
@@ -0,0 +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.oracle.ast.expr;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLExprImpl;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
import java.util.ArrayList;
import java.util.List;
public class OracleIsOfTypeExpr extends SQLExprImpl implements OracleExpr {
private SQLExpr expr;
private List<SQLExpr> types = new ArrayList<SQLExpr>();
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
OracleIsOfTypeExpr that = (OracleIsOfTypeExpr) o;
if (expr != null ? !expr.equals(that.expr) : that.expr != null) return false;
return types != null ? types.equals(that.types) : that.types == null;
}
@Override
public int hashCode() {
int result = expr != null ? expr.hashCode() : 0;
result = 31 * result + (types != null ? types.hashCode() : 0);
return result;
}
@Override
protected void accept0(SQLASTVisitor visitor) {
accept0((OracleASTVisitor) visitor);
}
@Override
public void accept0(OracleASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, expr);
acceptChild(visitor, types);
}
visitor.endVisit(this);
}
@Override
public SQLExpr clone() {
OracleIsOfTypeExpr x = new OracleIsOfTypeExpr();
if (expr != null) {
x.setExpr(expr);
}
return null;
}
@Override
public List<SQLObject> getChildren() {
List children = new ArrayList<SQLExpr>();
if (expr != null) {
children.add(expr);
}
children.addAll(types);
return children;
}
public SQLExpr getExpr() {
return expr;
}
public void setExpr(SQLExpr expr) {
if (expr != null) {
expr.setParent(this);
}
this.expr = expr;
}
public List<SQLExpr> getTypes() {
return types;
}
}
@@ -92,6 +92,9 @@ public class OracleSelectPivot extends OracleSelectPivotBase {
}
public void setExpr(SQLExpr expr) {
if (expr != null) {
expr.setParent(this);
}
this.expr = expr;
}
@@ -20,21 +20,7 @@ import java.util.Arrays;
import com.alibaba.druid.sql.ast.*;
import com.alibaba.druid.sql.ast.SQLKeep.DenseRank;
import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr;
import com.alibaba.druid.sql.ast.expr.SQLAggregateOption;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
import com.alibaba.druid.sql.ast.expr.SQLNumericLiteralExpr;
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
import com.alibaba.druid.sql.ast.expr.SQLSequenceExpr;
import com.alibaba.druid.sql.ast.expr.SQLTimestampExpr;
import com.alibaba.druid.sql.ast.expr.SQLUnaryExpr;
import com.alibaba.druid.sql.ast.expr.SQLUnaryOperator;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.ast.expr.*;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear;
@@ -592,6 +578,17 @@ public class OracleExprParser extends SQLExprParser {
expr = dblink;
}
if (lexer.token() == Token.LBRACKET) {
SQLArrayExpr arrayExpr = new SQLArrayExpr();
arrayExpr.setExpr(expr);
lexer.nextToken();
this.exprList(arrayExpr.getValues(), arrayExpr);
accept(Token.RBRACKET);
expr = arrayExpr;
expr = primaryRest(expr);
}
if (lexer.identifierEquals("DAY") || lexer.identifierEquals("YEAR")) {
Lexer.SavePoint savePoint = lexer.mark();
@@ -743,6 +740,10 @@ public class OracleExprParser extends SQLExprParser {
lexer.nextToken();
acceptIdentifier("NULLS");
aggregateExpr.setIgnoreNulls(true);
} else if (lexer.identifierEquals(FnvHash.Constants.RESPECT)) {
lexer.nextToken();
acceptIdentifier("NULLS");
aggregateExpr.setIgnoreNulls(false);
}
accept(Token.RPAREN);
@@ -873,10 +874,15 @@ public class OracleExprParser extends SQLExprParser {
accept(Token.INTERVAL);
OracleIntervalExpr interval = new OracleIntervalExpr();
if (lexer.token() != Token.LITERAL_CHARS) {
if (lexer.token() == Token.LITERAL_CHARS) {
interval.setValue(new SQLCharExpr(lexer.stringVal()));
} else if (lexer.token() == Token.VARIANT) {
interval.setValue(new SQLVariantRefExpr(lexer.stringVal()));
} else {
return new SQLIdentifierExpr("INTERVAL");
}
interval.setValue(new SQLCharExpr(lexer.stringVal()));
lexer.nextToken();
OracleIntervalType type;
@@ -906,12 +912,11 @@ public class OracleExprParser extends SQLExprParser {
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
if (lexer.token() != Token.LITERAL_INT) {
if (lexer.token() != Token.LITERAL_INT && lexer.token() != Token.VARIANT) {
throw new ParserException("syntax error. " + lexer.info());
}
interval.setPrecision(lexer.integerValue().intValue());
lexer.nextToken();
interval.setPrecision(this.primary());
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
if (lexer.token() != Token.LITERAL_INT) {
@@ -930,11 +935,10 @@ public class OracleExprParser extends SQLExprParser {
interval.setToType(OracleIntervalType.SECOND);
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
if (lexer.token() != Token.LITERAL_INT) {
if (lexer.token() != Token.LITERAL_INT && lexer.token() != Token.VARIANT) {
throw new ParserException("syntax error. " + lexer.info());
}
interval.setToFactionalSecondsPrecision(lexer.integerValue().intValue());
lexer.nextToken();
interval.setToFactionalSecondsPrecision(primary());
accept(Token.RPAREN);
}
} else {
@@ -958,6 +962,41 @@ public class OracleExprParser extends SQLExprParser {
lexer.nextToken();
accept(Token.SET);
expr = new OracleIsSetExpr(expr);
} else if (lexer.token() == Token.OF) {
lexer.nextToken();
if (lexer.identifierEquals(FnvHash.Constants.TYPE)) {
lexer.nextToken();
}
OracleIsOfTypeExpr isOf = new OracleIsOfTypeExpr();
isOf.setExpr(expr);
accept(Token.LPAREN);
for (;;) {
boolean only = lexer.identifierEquals(FnvHash.Constants.ONLY);
if (only) {
lexer.nextToken();
}
SQLExpr type = this.name();
if (only) {
type.putAttribute("ONLY", true);
}
type.setParent(isOf);
isOf.getTypes().add(type);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
accept(Token.RPAREN);
expr = isOf;
} else {
SQLExpr rightExpr = primary();
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Is, rightExpr, getDbType());
@@ -144,7 +144,8 @@ public class OracleLexer extends Lexer {
}
public void scanVariable() {
if (ch != ':' && ch != '#' && ch != '$') {
final char c0 = ch;
if (c0 != ':' && c0 != '#' && c0 != '$') {
throw new ParserException("illegal variable. " + info());
}
@@ -154,25 +155,46 @@ public class OracleLexer extends Lexer {
boolean quoteFlag = false;
boolean mybatisFlag = false;
if (charAt(pos + 1) == '"') {
char c1 = charAt(pos + 1);
if (c0 == ':' && c1 == ' ') {
pos++;
bufPos = 2;
c1 = charAt(pos + 1);
}
if (c1 == '"') {
pos++;
bufPos++;
quoteFlag = true;
} else if (charAt(pos + 1) == '{') {
} else if (c1 == '{') {
pos++;
bufPos++;
mybatisFlag = true;
}
for (;;) {
ch = charAt(++pos);
if (c0 == ':' && c1 >= '0' && c1 <= '9') {
for (; ; ) {
ch = charAt(++pos);
if (!isIdentifierChar(ch)) {
break;
if (ch < '0' || ch > '9') {
break;
}
bufPos++;
continue;
}
} else {
for (; ; ) {
ch = charAt(++pos);
bufPos++;
continue;
if (!isIdentifierChar(ch)) {
break;
}
bufPos++;
continue;
}
}
if (quoteFlag) {
@@ -48,6 +48,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableReference;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableSource;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectUnPivot;
import com.alibaba.druid.sql.parser.*;
import com.alibaba.druid.util.FnvHash;
public class OracleSelectParser extends SQLSelectParser {
@@ -204,8 +205,16 @@ public class OracleSelectParser extends SQLSelectParser {
throw new ParserException("syntax erorr : " + lexer.token());
}
searchClause.setType(SearchClause.Type.valueOf(lexer.stringVal()));
lexer.nextToken();
if (lexer.identifierEquals(FnvHash.Constants.DEPTH)) {
lexer.nextToken();
searchClause.setType(SearchClause.Type.DEPTH);
} else if (lexer.identifierEquals(FnvHash.Constants.BREADTH)) {
lexer.nextToken();
searchClause.setType(SearchClause.Type.BREADTH);
} else {
searchClause.setType(SearchClause.Type.valueOf(lexer.stringVal().toUpperCase()));
lexer.nextToken();
}
acceptIdentifier("FIRST");
accept(Token.BY);
@@ -522,9 +531,16 @@ public class OracleSelectParser extends SQLSelectParser {
item.setCellAssignment(parseCellAssignment());
item.setOrderBy(this.parseOrderBy());
accept(Token.EQ);
item.setExpr(expr());
SQLExpr expr = this.expr();
item.setExpr(expr);
modelRulesClause.getCellAssignmentItems().add(item);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
}
mainModel.setModelRulesClause(modelRulesClause);
@@ -533,7 +549,7 @@ public class OracleSelectParser extends SQLSelectParser {
private CellAssignment parseCellAssignment() {
CellAssignment cellAssignment = new CellAssignment();
cellAssignment.setMeasureColumn(expr());
cellAssignment.setMeasureColumn(this.exprParser.name());
accept(Token.LBRACKET);
this.exprParser.exprList(cellAssignment.getConditions(), cellAssignment);
accept(Token.RBRACKET);
@@ -609,6 +625,7 @@ public class OracleSelectParser extends SQLSelectParser {
} else if (lexer.token() == Token.IDENTIFIER) {
SQLTableSource identTable = parseTableSource();
accept(Token.RPAREN);
parsePivot((OracleSelectTableSource) identTable);
return identTable;
} else {
throw new ParserException("TODO :" + lexer.info());
@@ -688,6 +705,11 @@ public class OracleSelectParser extends SQLSelectParser {
lexer.nextToken();
partition.setPartition(exprParser.name());
accept(Token.RPAREN);
} else if (lexer.token() == Token.BY) {
lexer.nextToken();
accept(Token.LPAREN);
partition.setPartition(exprParser.name());
accept(Token.RPAREN);
} else {
accept(Token.FOR);
accept(Token.LPAREN);
@@ -861,6 +883,14 @@ public class OracleSelectParser extends SQLSelectParser {
if (lexer.token() == Token.ON) {
lexer.nextToken();
join.setCondition(this.exprParser.expr());
if (lexer.token() == Token.ON
&& tableSource instanceof SQLJoinTableSource
&& ((SQLJoinTableSource) tableSource).getCondition() == null) {
lexer.nextToken();
SQLExpr leftCondidition = this.exprParser.expr();
((SQLJoinTableSource) tableSource).setCondition(leftCondidition);
}
} else if (lexer.token() == Token.USING) {
lexer.nextToken();
accept(Token.LPAREN);
@@ -868,6 +898,8 @@ public class OracleSelectParser extends SQLSelectParser {
accept(Token.RPAREN);
}
parsePivot(join);
return parseTableSourceRest(join);
}
@@ -921,25 +953,28 @@ public class OracleSelectParser extends SQLSelectParser {
accept(Token.IN);
accept(Token.LPAREN);
if (lexer.token() == (Token.LPAREN)) {
throw new ParserException("TODO. " + lexer.info());
}
// if (lexer.token() == (Token.LPAREN)) {
// throw new ParserException("TODO. " + lexer.info());
// }
if (lexer.token() == (Token.SELECT)) {
throw new ParserException("TODO. " + lexer.info());
}
for (;;) {
SQLExpr expr = this.exprParser.expr();
item = new OracleSelectPivot.Item();
item.setExpr(this.exprParser.expr());
item.setAlias(as());
item.setExpr(expr);
pivot.getPivotIn().add(item);
} else {
for (; ; ) {
item = new OracleSelectPivot.Item();
item.setExpr(this.exprParser.expr());
item.setAlias(as());
pivot.getPivotIn().add(item);
if (lexer.token() != Token.COMMA) {
break;
if (lexer.token() != Token.COMMA) {
break;
}
lexer.nextToken();
}
lexer.nextToken();
}
accept(Token.RPAREN);
@@ -1381,7 +1381,10 @@ public class OracleStatementParser extends SQLStatementParser {
stmt.addItem(item);
accept(Token.RPAREN);
} else if (lexer.token() == Token.CONSTRAINT) {
} else if (lexer.token() == Token.CONSTRAINT
|| lexer.token() == Token.FOREIGN
|| lexer.token() == Token.PRIMARY
|| lexer.token() == Token.UNIQUE) {
OracleConstraint constraint = ((OracleExprParser) this.exprParser).parseConstaint();
SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint();
constraint.setParent(item);
@@ -437,4 +437,8 @@ public interface OracleASTVisitor extends SQLASTVisitor {
boolean visit(OraclePipeRowStatement x);
void endVisit(OraclePipeRowStatement x);
boolean visit(OracleIsOfTypeExpr x);
void endVisit(OracleIsOfTypeExpr x);
}
@@ -1083,4 +1083,14 @@ public class OracleASTVisitorAdapter extends SQLASTVisitorAdapter implements Ora
public void endVisit(OraclePipeRowStatement x) {
}
@Override
public boolean visit(OracleIsOfTypeExpr x) {
return true;
}
@Override
public void endVisit(OracleIsOfTypeExpr x) {
}
}
@@ -187,7 +187,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
if (x.getPrecision() != null) {
print('(');
print(x.getPrecision().intValue());
printExpr(x.getPrecision());
if (x.getFactionalSecondsPrecision() != null) {
print0(", ");
print(x.getFactionalSecondsPrecision().intValue());
@@ -200,7 +200,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
print0(x.getToType().name());
if (x.getToFactionalSecondsPrecision() != null) {
print('(');
print(x.getToFactionalSecondsPrecision().intValue());
printExpr(x.getToFactionalSecondsPrecision());
print(')');
}
}
@@ -297,6 +297,12 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
printFlashback(x.getFlashback());
}
OracleSelectPivotBase pivot = x.getPivot();
if (pivot != null) {
println();
pivot.accept(this);
}
return false;
}
@@ -471,9 +477,10 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
println();
print(')');
if (x.getPivot() != null) {
OracleSelectPivotBase pivot = x.getPivot();
if (pivot != null) {
println();
x.getPivot().accept(this);
pivot.accept(this);
}
printFlashback(x.getFlashback());
@@ -3341,4 +3348,30 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
public void endVisit(OraclePipeRowStatement x) {
}
@Override
public boolean visit(OracleIsOfTypeExpr x) {
printExpr(x.getExpr());
print0(ucase ? " IS OF TYPE (" : " is of type (");
List<SQLExpr> types = x.getTypes();
for (int i = 0, size = types.size(); i < size; ++i) {
if (i != 0) {
print0(", ");
}
SQLExpr type = types.get(i);
if (Boolean.TRUE == type.getAttribute("ONLY")) {
print0(ucase ? "ONLY " : "only ");
}
type.accept(this);
}
print(')');
return false;
}
@Override
public void endVisit(OracleIsOfTypeExpr x) {
}
}
@@ -1375,4 +1375,14 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle
public void endVisit(OraclePipeRowStatement x) {
}
@Override
public boolean visit(OracleIsOfTypeExpr x) {
return false;
}
@Override
public void endVisit(OracleIsOfTypeExpr x) {
}
}
@@ -33,7 +33,12 @@ public class PGTypeCastExpr extends SQLCastExpr implements PGExpr {
@Override
protected void accept0(SQLASTVisitor visitor) {
accept0((PGASTVisitor) visitor);
if (visitor instanceof PGASTVisitor) {
accept0((PGASTVisitor) visitor);
return;
}
super.accept0(visitor);
}
public String toString() {
@@ -38,7 +38,12 @@ public class PGUpdateStatement extends SQLUpdateStatement implements PGSQLStatem
}
protected void accept0(SQLASTVisitor visitor) {
accept0((PGASTVisitor) visitor);
if (visitor instanceof PGASTVisitor) {
accept0((PGASTVisitor) visitor);
return;
}
super.accept0(visitor);
}
@Override
@@ -31,6 +31,8 @@ import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import com.alibaba.druid.sql.parser.Token;
import com.alibaba.druid.util.FnvHash;
import com.alibaba.druid.util.JdbcConstants;
import java.util.ArrayList;
import java.util.List;
@@ -393,5 +395,77 @@ public class PGSQLStatementParser extends SQLStatementParser {
return stmt;
}
public SQLCreateSequenceStatement parseCreateSequence(boolean acceptCreate) {
if (acceptCreate) {
accept(Token.CREATE);
}
accept(Token.SEQUENCE);
SQLCreateSequenceStatement stmt = new SQLCreateSequenceStatement();
stmt.setDbType(dbType);
stmt.setName(this.exprParser.name());
for (;;) {
if (lexer.token() == Token.START) {
lexer.nextToken();
accept(Token.WITH);
stmt.setStartWith(this.exprParser.expr());
continue;
} else if (lexer.identifierEquals("INCREMENT")) {
lexer.nextToken();
accept(Token.BY);
stmt.setIncrementBy(this.exprParser.expr());
continue;
} else if (lexer.token() == Token.CACHE || lexer.identifierEquals(FnvHash.Constants.CACHE)) {
lexer.nextToken();
stmt.setCache(Boolean.TRUE);
if (lexer.token() == Token.LITERAL_INT) {
stmt.setCacheValue(this.exprParser.primary());
}
continue;
} else if (lexer.token() == Token.NOCACHE) {
lexer.nextToken();
stmt.setCache(Boolean.FALSE);
continue;
} else if (lexer.token() == Token.ORDER) {
lexer.nextToken();
stmt.setOrder(Boolean.TRUE);
continue;
} else if (lexer.identifierEquals("NOORDER")) {
lexer.nextToken();
stmt.setOrder(Boolean.FALSE);
continue;
} else if (lexer.identifierEquals("CYCLE")) {
lexer.nextToken();
stmt.setCycle(Boolean.TRUE);
continue;
} else if (lexer.identifierEquals("NOCYCLE")) {
lexer.nextToken();
stmt.setCycle(Boolean.FALSE);
continue;
} else if (lexer.identifierEquals("MINVALUE")) {
lexer.nextToken();
stmt.setMinValue(this.exprParser.expr());
continue;
} else if (lexer.identifierEquals("MAXVALUE")) {
lexer.nextToken();
stmt.setMaxValue(this.exprParser.expr());
continue;
} else if (lexer.identifierEquals("NOMAXVALUE")) {
lexer.nextToken();
stmt.setNoMaxValue(true);
continue;
} else if (lexer.identifierEquals("NOMINVALUE")) {
lexer.nextToken();
stmt.setNoMinValue(true);
continue;
}
break;
}
return stmt;
}
}
@@ -1082,7 +1082,7 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor
if (x.getPrecision() != null) {
print('(');
print(x.getPrecision().intValue());
printExpr(x.getPrecision());
if (x.getFactionalSecondsPrecision() != null) {
print0(", ");
print(x.getFactionalSecondsPrecision().intValue());
@@ -1095,7 +1095,7 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor
print0(x.getToType().name());
if (x.getToFactionalSecondsPrecision() != null) {
print('(');
print(x.getToFactionalSecondsPrecision().intValue());
printExpr(x.getToFactionalSecondsPrecision());
print(')');
}
}
@@ -2770,4 +2770,29 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor
x.getExpr().accept(this);
return false;
}
@Override
public boolean visit(OracleIsOfTypeExpr x) {
printExpr(x.getExpr());
print0(ucase ? " IS OF TYPE (" : " is of type (");
List<SQLExpr> types = x.getTypes();
for (int i = 0, size = types.size(); i < size; ++i) {
if (i != 0) {
print0(", ");
}
SQLExpr type = types.get(i);
if (Boolean.TRUE == type.getAttribute("ONLY")) {
print0(ucase ? "ONLY " : "only ");
}
type.accept(this);
}
print(')');
return false;
}
public void endVisit(OracleIsOfTypeExpr x) {
}
}
@@ -866,7 +866,40 @@ public class Lexer {
scanChar();
token = Token.LT_SUB_GT;
} else {
token = Token.LT;
if (ch == ' ') {
char c1 = charAt(pos + 1);
if (c1 == '=') {
scanChar();
scanChar();
if (ch == '>') {
token = Token.LTEQGT;
scanChar();
} else {
token = Token.LTEQ;
}
} else if (c1 == '>') {
scanChar();
scanChar();
token = Token.LTGT;
} else if (c1 == '<') {
scanChar();
scanChar();
token = Token.LTLT;
} else if (c1 == '@') {
scanChar();
scanChar();
token = Token.LT_MONKEYS_AT;
} else if (c1 == '-' && charAt(pos + 2) == '>') {
scanChar();
scanChar();
scanChar();
token = Token.LT_SUB_GT;
} else {
token = Token.LT;
}
} else {
token = Token.LT;
}
}
break;
case '!':
@@ -24,26 +24,7 @@ import java.util.List;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.*;
import com.alibaba.druid.sql.ast.expr.*;
import com.alibaba.druid.sql.ast.statement.SQLNotNullConstraint;
import com.alibaba.druid.sql.ast.statement.SQLNullConstraint;
import com.alibaba.druid.sql.ast.statement.SQLAssignItem;
import com.alibaba.druid.sql.ast.statement.SQLCharacterDataType;
import com.alibaba.druid.sql.ast.statement.SQLCheck;
import com.alibaba.druid.sql.ast.statement.SQLColumnCheck;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.ast.statement.SQLColumnPrimaryKey;
import com.alibaba.druid.sql.ast.statement.SQLColumnReference;
import com.alibaba.druid.sql.ast.statement.SQLColumnUniqueKey;
import com.alibaba.druid.sql.ast.statement.SQLConstraint;
import com.alibaba.druid.sql.ast.statement.SQLForeignKeyConstraint;
import com.alibaba.druid.sql.ast.statement.SQLForeignKeyImpl;
import com.alibaba.druid.sql.ast.statement.SQLPrimaryKey;
import com.alibaba.druid.sql.ast.statement.SQLPrimaryKeyImpl;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;
import com.alibaba.druid.sql.ast.statement.SQLUnique;
import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleArgumentExpr;
import com.alibaba.druid.util.FnvHash;
import com.alibaba.druid.util.JdbcConstants;
@@ -140,8 +121,15 @@ public class SQLExprParser extends SQLParser {
switch (token) {
case CARET: {
lexer.nextToken();
SQLBinaryOperator op;
if (lexer.token == Token.EQ) {
lexer.nextToken();
op = SQLBinaryOperator.BitwiseXorEQ;
} else {
op = SQLBinaryOperator.BitwiseXor;
}
SQLExpr rightExp = primary();
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BitwiseXor, rightExp, dbType);
expr = new SQLBinaryOpExpr(expr, op, rightExp, dbType);
expr = bitXorRest(expr);
break;
}
@@ -303,6 +291,13 @@ public class SQLExprParser extends SQLParser {
}
accept(Token.RPAREN);
if (lexer.token == Token.UNION && sqlExpr instanceof SQLQueryExpr) {
SQLQueryExpr queryExpr = (SQLQueryExpr) sqlExpr;
SQLSelectQuery query = this.createSelectParser().queryRest(queryExpr.getSubQuery().getQuery());
queryExpr.getSubQuery().setQuery(query);
}
break;
case INSERT:
lexer.nextToken();
@@ -707,6 +702,18 @@ public class SQLExprParser extends SQLParser {
sqlExpr = new SQLBinaryExpr(strVal);
break;
}
case SET: {
Lexer.SavePoint savePoint = lexer.mark();
lexer.nextToken();
if (lexer.token() == Token.LPAREN) {
sqlExpr = new SQLIdentifierExpr("SET");
} else {
lexer.reset(savePoint);
throw new ParserException("ERROR. " + lexer.info());
}
break;
}
default:
throw new ParserException("ERROR. " + lexer.info());
}
@@ -844,37 +851,37 @@ public class SQLExprParser extends SQLParser {
&& "GROUPING".equalsIgnoreCase(((SQLIdentifierExpr) expr).getName())) {
SQLGroupingSetExpr groupingSets = new SQLGroupingSetExpr();
lexer.nextToken();
accept(Token.LPAREN);
for (;;) {
for (; ; ) {
SQLExpr item;
if (lexer.token == Token.LPAREN) {
lexer.nextToken();
SQLListExpr listExpr = new SQLListExpr();
this.exprList(listExpr.getItems(), listExpr);
item = listExpr;
accept(Token.RPAREN);
} else {
item = this.expr();
}
item.setParent(groupingSets);
groupingSets.addParameter(item);
if (lexer.token == Token.RPAREN) {
break;
}
accept(Token.COMMA);
}
this.exprList(groupingSets.getParameters(), groupingSets);
accept(Token.RPAREN);
return groupingSets;
} else {
if (lexer.token == Token.LPAREN) {
@@ -992,7 +999,13 @@ public class SQLExprParser extends SQLParser {
if (lexer.token == Token.USING || lexer.identifierEquals(FnvHash.Constants.USING)) {
lexer.nextToken();
SQLExpr using = this.primary();
SQLExpr using;
if (lexer.token == Token.STAR) {
lexer.nextToken();
using = new SQLAllColumnExpr();
} else {
using = this.primary();
}
methodInvokeExpr.setUsing(using);
}
@@ -1542,8 +1555,13 @@ public class SQLExprParser extends SQLParser {
public final SQLExpr bitOrRest(SQLExpr expr) {
while (lexer.token == Token.BAR) {
lexer.nextToken();
SQLBinaryOperator op = SQLBinaryOperator.BitwiseOr;
if (lexer.token == Token.BAR) {
lexer.nextToken();
op = SQLBinaryOperator.Concat;
}
SQLExpr rightExp = bitAnd();
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BitwiseOr, rightExp, getDbType());
expr = new SQLBinaryOpExpr(expr, op, rightExp, getDbType());
expr = bitAndRest(expr);
}
return expr;
@@ -1897,6 +1897,11 @@ public class SQLStatementParser extends SQLParser {
return parseCreateType();
}
if (lexer.identifierEquals(FnvHash.Constants.PUBLIC)) {
lexer.reset(markBp, markChar, Token.CREATE);
return parseCreateSynonym();
}
// lexer.reset(mark_bp, mark_ch, Token.CREATE);
throw new ParserException("TODO " + lexer.info());
} else if (token == Token.DATABASE) {
@@ -2726,82 +2731,90 @@ public class SQLStatementParser extends SQLParser {
accept(Token.ON);
stmt.setOn(exprParser.expr());
boolean insertFlag = false;
if (lexer.token == Token.WHEN) {
lexer.nextToken();
if (lexer.token == Token.MATCHED) {
SQLMergeStatement.MergeUpdateClause updateClause = new SQLMergeStatement.MergeUpdateClause();
for (;;) {
boolean insertFlag = false;
if (lexer.token == Token.WHEN) {
lexer.nextToken();
accept(Token.THEN);
accept(Token.UPDATE);
accept(Token.SET);
if (lexer.token == Token.MATCHED) {
SQLMergeStatement.MergeUpdateClause updateClause = new SQLMergeStatement.MergeUpdateClause();
lexer.nextToken();
accept(Token.THEN);
accept(Token.UPDATE);
accept(Token.SET);
for (;;) {
SQLUpdateSetItem item = this.exprParser.parseUpdateSetItem();
for (; ; ) {
SQLUpdateSetItem item = this.exprParser.parseUpdateSetItem();
updateClause.addItem(item);
item.setParent(updateClause);
updateClause.addItem(item);
item.setParent(updateClause);
if (lexer.token == (Token.COMMA)) {
lexer.nextToken();
continue;
if (lexer.token == (Token.COMMA)) {
lexer.nextToken();
continue;
}
break;
}
break;
if (lexer.token == Token.WHERE) {
lexer.nextToken();
updateClause.setWhere(exprParser.expr());
}
if (lexer.token == Token.DELETE) {
lexer.nextToken();
accept(Token.WHERE);
updateClause.setWhere(exprParser.expr());
}
stmt.setUpdateClause(updateClause);
} else if (lexer.token == Token.NOT) {
lexer.nextToken();
insertFlag = true;
}
}
if (!insertFlag) {
if (lexer.token == Token.WHEN) {
lexer.nextToken();
}
if (lexer.token == Token.NOT) {
lexer.nextToken();
insertFlag = true;
}
}
if (insertFlag) {
SQLMergeStatement.MergeInsertClause insertClause = new SQLMergeStatement.MergeInsertClause();
accept(Token.MATCHED);
accept(Token.THEN);
accept(Token.INSERT);
if (lexer.token == Token.LPAREN) {
accept(Token.LPAREN);
exprParser.exprList(insertClause.getColumns(), insertClause);
accept(Token.RPAREN);
}
accept(Token.VALUES);
accept(Token.LPAREN);
exprParser.exprList(insertClause.getValues(), insertClause);
accept(Token.RPAREN);
if (lexer.token == Token.WHERE) {
lexer.nextToken();
updateClause.setWhere(exprParser.expr());
insertClause.setWhere(exprParser.expr());
}
if (lexer.token == Token.DELETE) {
lexer.nextToken();
accept(Token.WHERE);
updateClause.setWhere(exprParser.expr());
}
stmt.setUpdateClause(updateClause);
} else if (lexer.token == Token.NOT) {
lexer.nextToken();
insertFlag = true;
stmt.setInsertClause(insertClause);
}
}
if (!insertFlag) {
if (lexer.token == Token.WHEN) {
lexer.nextToken();
continue;
}
if (lexer.token == Token.NOT) {
lexer.nextToken();
insertFlag = true;
}
}
if (insertFlag) {
SQLMergeStatement.MergeInsertClause insertClause = new SQLMergeStatement.MergeInsertClause();
accept(Token.MATCHED);
accept(Token.THEN);
accept(Token.INSERT);
if (lexer.token == Token.LPAREN) {
accept(Token.LPAREN);
exprParser.exprList(insertClause.getColumns(), insertClause);
accept(Token.RPAREN);
}
accept(Token.VALUES);
accept(Token.LPAREN);
exprParser.exprList(insertClause.getValues(), insertClause);
accept(Token.RPAREN);
if (lexer.token == Token.WHERE) {
lexer.nextToken();
insertClause.setWhere(exprParser.expr());
}
stmt.setInsertClause(insertClause);
break;
}
SQLErrorLoggingClause errorClause = parseErrorLoggingClause();
@@ -41,6 +41,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleCursorExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDatetimeExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreatePackageStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleForStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectPivot;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleFunctionDataType;
import com.alibaba.druid.util.JdbcConstants;
import com.alibaba.druid.util.JdbcUtils;
@@ -1597,8 +1598,9 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
visit(subQuery);
print(')');
println();
} else if (parent instanceof SQLStatement
&& !(parent instanceof OracleForStatement)) {
} else if ((parent instanceof SQLStatement
&& !(parent instanceof OracleForStatement))
|| parent instanceof OracleSelectPivot.Item) {
this.indentCount++;
println();
@@ -4973,7 +4975,11 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
}
if (x.isNoMaxValue()) {
print0(ucase ? " NOMAXVALUE" : " nomaxvalue");
if (JdbcConstants.POSTGRESQL.equals(dbType)) {
print0(ucase ? " NO MAXVALUE" : " no maxvalue");
} else {
print0(ucase ? " NOMAXVALUE" : " nomaxvalue");
}
}
if (x.getMinValue() != null) {
@@ -4982,14 +4988,22 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
}
if (x.isNoMinValue()) {
print0(ucase ? " NOMINVALUE" : " nominvalue");
if (JdbcConstants.POSTGRESQL.equals(dbType)) {
print0(ucase ? " NO MINVALUE" : " no minvalue");
} else {
print0(ucase ? " NOMINVALUE" : " nominvalue");
}
}
if (x.getCycle() != null) {
if (x.getCycle().booleanValue()) {
print0(ucase ? " CYCLE" : " cycle");
} else {
print0(ucase ? " NOCYCLE" : " nocycle");
if (JdbcConstants.POSTGRESQL.equals(dbType)) {
print0(ucase ? " NO CYCLE" : " no cycle");
} else {
print0(ucase ? " NOCYCLE" : " nocycle");
}
}
}
@@ -306,6 +306,7 @@ public final class FnvHash {
long SQL_SMALL_RESULT = fnv1a_64_lower("SQL_SMALL_RESULT");
long SQL_BIG_RESULT = fnv1a_64_lower("SQL_BIG_RESULT");
long SQL_BUFFER_RESULT = fnv1a_64_lower("SQL_BUFFER_RESULT");
long CACHE = fnv1a_64_lower("CACHE");
long SQL_CACHE = fnv1a_64_lower("SQL_CACHE");
long SQL_NO_CACHE = fnv1a_64_lower("SQL_NO_CACHE");
long SQL_CALC_FOUND_ROWS = fnv1a_64_lower("SQL_CALC_FOUND_ROWS");
@@ -439,6 +440,7 @@ public final class FnvHash {
long FOLLOWING = fnv1a_64_lower("FOLLOWING");
long UNBOUNDED = fnv1a_64_lower("UNBOUNDED");
long SIBLINGS = fnv1a_64_lower("SIBLINGS");
long RESPECT = fnv1a_64_lower("RESPECT");
long NULLS = fnv1a_64_lower("NULLS");
long FIRST = fnv1a_64_lower("FIRST");
long LAST = fnv1a_64_lower("LAST");
@@ -511,6 +513,7 @@ public final class FnvHash {
long TRUNC = fnv1a_64_lower("TRUNC");
long SYSTIMESTAMP = fnv1a_64_lower("SYSTIMESTAMP");
long TYPE = fnv1a_64_lower("TYPE");
long ONLY = fnv1a_64_lower("ONLY");
long MEMBER = fnv1a_64_lower("MEMBER");
long STATIC = fnv1a_64_lower("STATIC");
long UNSUPPORTED = fnv1a_64_lower("UNSUPPORTED");
@@ -524,5 +527,8 @@ public final class FnvHash {
long COMPRESS = fnv1a_64_lower("COMPRESS");
long YES = fnv1a_64_lower("YES");
long WMSYS = fnv1a_64_lower("WMSYS");
long DEPTH = fnv1a_64_lower("DEPTH");
long BREADTH = fnv1a_64_lower("BREADTH");
}
}