diff --git a/src/main/java/com/alibaba/druid/sql/PagerUtils.java b/src/main/java/com/alibaba/druid/sql/PagerUtils.java index b8fe5524c6..158d46e595 100644 --- a/src/main/java/com/alibaba/druid/sql/PagerUtils.java +++ b/src/main/java/com/alibaba/druid/sql/PagerUtils.java @@ -142,11 +142,13 @@ public class PagerUtils { SQLBinaryOpExpr gt = new SQLBinaryOpExpr(new SQLIdentifierExpr("ROWNUM"), // SQLBinaryOperator.GreaterThan, // - new SQLNumberExpr(offset)); + new SQLNumberExpr(offset), // + JdbcConstants.DB2); SQLBinaryOpExpr lteq = new SQLBinaryOpExpr(new SQLIdentifierExpr("ROWNUM"), // SQLBinaryOperator.LessThanOrEqual, // - new SQLNumberExpr(count + offset)); - SQLBinaryOpExpr pageCondition = new SQLBinaryOpExpr(gt, SQLBinaryOperator.BooleanAnd, lteq); + new SQLNumberExpr(count + offset), // + JdbcConstants.DB2); + SQLBinaryOpExpr pageCondition = new SQLBinaryOpExpr(gt, SQLBinaryOperator.BooleanAnd, lteq, JdbcConstants.DB2); if (query instanceof SQLSelectQueryBlock) { DB2SelectQueryBlock queryBlock = (DB2SelectQueryBlock) query; @@ -199,11 +201,14 @@ public class PagerUtils { SQLBinaryOpExpr gt = new SQLBinaryOpExpr(new SQLIdentifierExpr("ROWNUM"), // SQLBinaryOperator.GreaterThan, // - new SQLNumberExpr(offset)); + new SQLNumberExpr(offset), // + JdbcConstants.SQL_SERVER + ); SQLBinaryOpExpr lteq = new SQLBinaryOpExpr(new SQLIdentifierExpr("ROWNUM"), // SQLBinaryOperator.LessThanOrEqual, // - new SQLNumberExpr(count + offset)); - SQLBinaryOpExpr pageCondition = new SQLBinaryOpExpr(gt, SQLBinaryOperator.BooleanAnd, lteq); + new SQLNumberExpr(count + offset), // + JdbcConstants.SQL_SERVER); + SQLBinaryOpExpr pageCondition = new SQLBinaryOpExpr(gt, SQLBinaryOperator.BooleanAnd, lteq, JdbcConstants.SQL_SERVER); if (query instanceof SQLSelectQueryBlock) { SQLServerSelectQueryBlock queryBlock = (SQLServerSelectQueryBlock) query; @@ -262,13 +267,17 @@ public class PagerUtils { if (queryBlock.getGroupBy() == null && select.getOrderBy() == null && offset <= 0) { SQLExpr condition = new SQLBinaryOpExpr(new SQLIdentifierExpr("ROWNUM"), // SQLBinaryOperator.LessThanOrEqual, // - new SQLNumberExpr(count)); + new SQLNumberExpr(count), // + JdbcConstants.ORACLE + ); if (queryBlock.getWhere() == null) { queryBlock.setWhere(condition); } else { queryBlock.setWhere(new SQLBinaryOpExpr(queryBlock.getWhere(), // SQLBinaryOperator.BooleanAnd, // - condition)); + condition, // + JdbcConstants.ORACLE + )); } return SQLUtils.toSQLString(select, dbType); @@ -282,7 +291,8 @@ public class PagerUtils { countQueryBlock.setFrom(new SQLSubqueryTableSource(select, "XX")); countQueryBlock.setWhere(new SQLBinaryOpExpr(new SQLIdentifierExpr("ROWNUM"), // SQLBinaryOperator.LessThanOrEqual, // - new SQLNumberExpr(count + offset))); + new SQLNumberExpr(count + offset), // + JdbcConstants.ORACLE)); if (offset <= 0) { return SQLUtils.toSQLString(countQueryBlock, dbType); } @@ -292,7 +302,8 @@ public class PagerUtils { offsetQueryBlock.setFrom(new SQLSubqueryTableSource(new SQLSelect(countQueryBlock), "XXX")); offsetQueryBlock.setWhere(new SQLBinaryOpExpr(new SQLIdentifierExpr("RN"), // SQLBinaryOperator.GreaterThan, // - new SQLNumberExpr(offset))); + new SQLNumberExpr(offset), // + JdbcConstants.ORACLE)); return SQLUtils.toSQLString(offsetQueryBlock, dbType); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOpExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOpExpr.java index 6d7dd5474a..87e33110ad 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOpExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOpExpr.java @@ -28,16 +28,25 @@ public class SQLBinaryOpExpr extends SQLExprImpl implements Serializable { private SQLExpr left; private SQLExpr right; private SQLBinaryOperator operator; + private String dbType; public SQLBinaryOpExpr(){ } - public SQLBinaryOpExpr(SQLExpr left, SQLBinaryOperator operator, SQLExpr right){ + public SQLBinaryOpExpr(String dbType){ + this.dbType = dbType; + } + public SQLBinaryOpExpr(SQLExpr left, SQLBinaryOperator operator, SQLExpr right){ + this(left, operator, right, null); + } + + public SQLBinaryOpExpr(SQLExpr left, SQLBinaryOperator operator, SQLExpr right, String dbType){ setLeft(left); setRight(right); this.operator = operator; + this.dbType = dbType; } public SQLBinaryOpExpr(SQLExpr left, SQLExpr right, SQLBinaryOperator operator){ @@ -47,6 +56,14 @@ public class SQLBinaryOpExpr extends SQLExprImpl implements Serializable { this.operator = operator; } + public String getDbType() { + return dbType; + } + + public void setDbType(String dbType) { + this.dbType = dbType; + } + public SQLExpr getLeft() { return this.left; } @@ -129,6 +146,6 @@ public class SQLBinaryOpExpr extends SQLExprImpl implements Serializable { } public String toString() { - return SQLUtils.toSQLString(this); + return SQLUtils.toSQLString(this, getDbType()); } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOperator.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOperator.java index 3f55890772..4d9dff9c07 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOperator.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOperator.java @@ -117,4 +117,8 @@ public enum SQLBinaryOperator { return false; } } + + public boolean isLogical() { + return this == BooleanAnd || this == BooleanOr || this == BooleanXor; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLUnaryOperator.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLUnaryOperator.java index 85decf9dd7..9912861601 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLUnaryOperator.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLUnaryOperator.java @@ -24,7 +24,9 @@ public enum SQLUnaryOperator { ConnectByRoot("CONNECT BY"), // BINARY("BINARY"), // RAW("RAW"), // - NOT("NOT"); + NOT("NOT"), + Pound("#") // Number of points in path or polygon + ; public final String name; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java index a5adf5e08d..72b4d5213b 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java @@ -57,6 +57,7 @@ import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLExprParser; import com.alibaba.druid.sql.parser.SQLSelectParser; import com.alibaba.druid.sql.parser.Token; +import com.alibaba.druid.util.JdbcConstants; public class MySqlExprParser extends SQLExprParser { @@ -79,7 +80,7 @@ public class MySqlExprParser extends SQLExprParser { rightExp = relationalRest(rightExp); - return new SQLBinaryOpExpr(expr, SQLBinaryOperator.RegExp, rightExp); + return new SQLBinaryOpExpr(expr, SQLBinaryOperator.RegExp, rightExp, JdbcConstants.MYSQL); } return super.relationalRest(expr); @@ -92,7 +93,7 @@ public class MySqlExprParser extends SQLExprParser { rightExp = relationalRest(rightExp); - return new SQLBinaryOpExpr(expr, SQLBinaryOperator.Modulus, rightExp); + return new SQLBinaryOpExpr(expr, SQLBinaryOperator.Modulus, rightExp, JdbcConstants.MYSQL); } return super.multiplicativeRest(expr); @@ -105,7 +106,7 @@ public class MySqlExprParser extends SQLExprParser { rightExp = relationalRest(rightExp); - return new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotRegExp, rightExp); + return new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotRegExp, rightExp, JdbcConstants.MYSQL); } return super.notRationalRest(expr); @@ -245,7 +246,7 @@ public class MySqlExprParser extends SQLExprParser { lexer.nextToken(); SQLBinaryOpExpr binaryExpr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.COLLATE, - new SQLIdentifierExpr(collate)); + new SQLIdentifierExpr(collate), JdbcConstants.MYSQL); expr = binaryExpr; @@ -470,7 +471,7 @@ public class MySqlExprParser extends SQLExprParser { lexer.nextToken(); return userName; } - + if (lexer.token() == Token.ERROR) { throw new ParserException("syntax error, token: " + lexer.token() + " " + lexer.stringVal() + ", pos : " + lexer.pos()); @@ -583,12 +584,12 @@ public class MySqlExprParser extends SQLExprParser { lexer.nextToken(); SQLExpr rightExp = and(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BooleanOr, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BooleanOr, rightExp, JdbcConstants.MYSQL); } else if (lexer.token() == Token.XOR) { lexer.nextToken(); SQLExpr rightExp = and(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BooleanXor, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BooleanXor, rightExp, JdbcConstants.MYSQL); } else { break; } @@ -596,19 +597,19 @@ public class MySqlExprParser extends SQLExprParser { return expr; } - + public SQLExpr additiveRest(SQLExpr expr) { if (lexer.token() == Token.PLUS) { lexer.nextToken(); SQLExpr rightExp = multiplicative(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Add, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Add, rightExp, JdbcConstants.MYSQL); expr = additiveRest(expr); } else if (lexer.token() == Token.SUB) { lexer.nextToken(); SQLExpr rightExp = multiplicative(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Subtract, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Subtract, rightExp, JdbcConstants.MYSQL); expr = additiveRest(expr); } @@ -845,7 +846,7 @@ public class MySqlExprParser extends SQLExprParser { } return aggregateExpr; } - + public MySqlSelectGroupByExpr parseSelectGroupByItem() { MySqlSelectGroupByExpr item = new MySqlSelectGroupByExpr(); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java index 601926b61d..0289cf0fa8 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java @@ -80,6 +80,7 @@ import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLExprParser; import com.alibaba.druid.sql.parser.Token; +import com.alibaba.druid.util.JdbcConstants; public class OracleExprParser extends SQLExprParser { @@ -139,11 +140,13 @@ public class OracleExprParser extends SQLExprParser { public OracleExprParser(Lexer lexer){ super(lexer); this.aggregateFunctions = AGGREGATE_FUNCTIONS; + this.dbType = JdbcConstants.ORACLE; } public OracleExprParser(String text){ this(new OracleLexer(text)); this.lexer.nextToken(); + this.dbType = JdbcConstants.ORACLE; } protected boolean isCharType(String dataTypeName) { @@ -966,14 +969,14 @@ public class OracleExprParser extends SQLExprParser { if (lexer.token() == Token.NOT) { lexer.nextToken(); SQLExpr rightExpr = primary(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.IsNot, rightExpr); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.IsNot, rightExpr, getDbType()); } else if (identifierEquals("A")) { lexer.nextToken(); accept(Token.SET); expr = new OracleIsSetExpr(expr); } else { SQLExpr rightExpr = primary(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Is, rightExpr); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Is, rightExpr, getDbType()); } return expr; @@ -1016,14 +1019,14 @@ public class OracleExprParser extends SQLExprParser { rightExp = equalityRest(rightExp); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Equality, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Equality, rightExp, getDbType()); } else if (lexer.token() == Token.BANGEQ) { lexer.nextToken(); rightExp = shift(); rightExp = equalityRest(rightExp); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotEqual, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotEqual, rightExp, getDbType()); } return expr; @@ -1113,7 +1116,7 @@ public class OracleExprParser extends SQLExprParser { if (lexer.token() == Token.COLONEQ) { lexer.nextToken(); SQLExpr right = expr(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Assignment, right); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Assignment, right, getDbType()); } return expr; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGBoxExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGBoxExpr.java new file mode 100644 index 0000000000..16cae9b5e2 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGBoxExpr.java @@ -0,0 +1,56 @@ +package com.alibaba.druid.sql.dialect.postgresql.ast.expr; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; + +public class PGBoxExpr extends PGExprImpl { + + private SQLExpr value; + + public SQLExpr getValue() { + return value; + } + + public void setValue(SQLExpr value) { + this.value = value; + } + + @Override + public void accept0(PGASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, value); + } + visitor.endVisit(this); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((value == null) ? 0 : value.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + PGBoxExpr other = (PGBoxExpr) obj; + if (value == null) { + if (other.value != null) { + return false; + } + } else if (!value.equals(other.value)) { + return false; + } + return true; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGDateField.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGDateField.java new file mode 100644 index 0000000000..a5ba033565 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGDateField.java @@ -0,0 +1,25 @@ +package com.alibaba.druid.sql.dialect.postgresql.ast.expr; + +public enum PGDateField { + CENTURY, + DAY, + DECADE, + DOW, + DOY, + EPOCH, + HOUR, + ISODOW, + ISOYEAR, + MICROSECONDS, + MILLENNIUM, + MILLISECONDS, + MINUTE, + MONTH, + QUARTER, + SECOND, + TIMEZONE, + TIMEZONE_HOUR, + TIMEZONE_MINUTE, + WEEK, + YEAR +} \ No newline at end of file diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGExprImpl.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGExprImpl.java index 74187cdeb4..619750008d 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGExprImpl.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGExprImpl.java @@ -15,6 +15,7 @@ */ package com.alibaba.druid.sql.dialect.postgresql.ast.expr; +import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLExprImpl; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -30,4 +31,7 @@ public abstract class PGExprImpl extends SQLExprImpl implements PGExpr { accept0((PGASTVisitor) visitor); } + public String toString() { + return SQLUtils.toPGString(this); + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGExtractExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGExtractExpr.java new file mode 100644 index 0000000000..bc5643320b --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGExtractExpr.java @@ -0,0 +1,69 @@ +package com.alibaba.druid.sql.dialect.postgresql.ast.expr; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; + +public class PGExtractExpr extends PGExprImpl { + + private PGDateField field; + private SQLExpr source; + + public PGDateField getField() { + return field; + } + + public void setField(PGDateField field) { + this.field = field; + } + + public SQLExpr getSource() { + return source; + } + + public void setSource(SQLExpr source) { + this.source = source; + } + + @Override + public void accept0(PGASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, source); + } + visitor.endVisit(this); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((field == null) ? 0 : field.hashCode()); + result = prime * result + ((source == null) ? 0 : source.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + PGExtractExpr other = (PGExtractExpr) obj; + if (field != other.field) { + return false; + } + if (source == null) { + if (other.source != null) { + return false; + } + } else if (!source.equals(other.source)) { + return false; + } + return true; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGPointExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGPointExpr.java new file mode 100644 index 0000000000..27dca014b3 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGPointExpr.java @@ -0,0 +1,56 @@ +package com.alibaba.druid.sql.dialect.postgresql.ast.expr; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; + +public class PGPointExpr extends PGExprImpl { + + private SQLExpr value; + + public SQLExpr getValue() { + return value; + } + + public void setValue(SQLExpr value) { + this.value = value; + } + + @Override + public void accept0(PGASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, value); + } + visitor.endVisit(this); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((value == null) ? 0 : value.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + PGPointExpr other = (PGPointExpr) obj; + if (value == null) { + if (other.value != null) { + return false; + } + } else if (!value.equals(other.value)) { + return false; + } + return true; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGTypeCastExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGTypeCastExpr.java index c12bb179ff..a3128ba371 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGTypeCastExpr.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/expr/PGTypeCastExpr.java @@ -15,6 +15,7 @@ */ package com.alibaba.druid.sql.dialect.postgresql.ast.expr; +import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.expr.SQLCastExpr; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -35,4 +36,7 @@ public class PGTypeCastExpr extends SQLCastExpr implements PGExpr { accept0((PGASTVisitor) visitor); } + public String toString() { + return SQLUtils.toPGString(this); + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java index 75f49259b5..93664d673e 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java @@ -19,12 +19,21 @@ import com.alibaba.druid.sql.ast.SQLDataType; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; 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.dialect.postgresql.ast.PGOrderBy; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGArrayExpr; +import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGBoxExpr; +import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGDateField; +import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGExtractExpr; +import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGPointExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGTypeCastExpr; import com.alibaba.druid.sql.parser.Lexer; +import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLExprParser; import com.alibaba.druid.sql.parser.Token; +import com.alibaba.druid.util.JdbcConstants; public class PGExprParser extends SQLExprParser { @@ -33,11 +42,13 @@ public class PGExprParser extends SQLExprParser { public PGExprParser(String sql){ this(new PGLexer(sql)); this.lexer.nextToken(); + this.dbType = JdbcConstants.POSTGRESQL; } public PGExprParser(Lexer lexer){ super(lexer); this.aggregateFunctions = AGGREGATE_FUNCTIONS; + this.dbType = JdbcConstants.POSTGRESQL; } @Override @@ -74,7 +85,22 @@ public class PGExprParser extends SQLExprParser { this.exprList(array.getValues(), array); accept(Token.RBRACKET); return primaryRest(array); + } else if (lexer.token() == Token.POUND) { + lexer.nextToken(); + if (lexer.token() == Token.LBRACE) { + lexer.nextToken(); + String varName = lexer.stringVal(); + lexer.nextToken(); + accept(Token.RBRACE); + SQLVariantRefExpr expr = new SQLVariantRefExpr("#{" + varName + "}"); + return primaryRest(expr); + } else { + SQLExpr value = this.primary(); + SQLUnaryExpr expr = new SQLUnaryExpr(SQLUnaryOperator.Pound, value); + return primaryRest(expr); + } } + return super.primary(); } @@ -126,6 +152,35 @@ public class PGExprParser extends SQLExprParser { return primaryRest(timestamp); + } else if ("EXTRACT".equalsIgnoreCase(ident)) { + accept(Token.LPAREN); + + PGExtractExpr extract = new PGExtractExpr(); + + String fieldName = lexer.stringVal(); + PGDateField field = PGDateField.valueOf(fieldName.toUpperCase()); + lexer.nextToken(); + + extract.setField(field); + + accept(Token.FROM); + SQLExpr source = this.expr(); + + extract.setSource(source); + + accept(Token.RPAREN); + + return primaryRest(extract); + } else if ("POINT".equalsIgnoreCase(ident)) { + SQLExpr value = this.primary(); + PGPointExpr point = new PGPointExpr(); + point.setValue(value); + return primaryRest(point); + } else if ("BOX".equalsIgnoreCase(ident)) { + SQLExpr value = this.primary(); + PGBoxExpr box = new PGBoxExpr(); + box.setValue(value); + return primaryRest(box); } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGLexer.java index 721c878209..313ecc2a11 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGLexer.java @@ -158,4 +158,9 @@ public class PGLexer extends Lexer { stringVal = new String(buf, 0, bufPos); } } + + public void scanSharp() { + token = Token.POUND; + scanChar(); + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitor.java index cd69889b78..53c052e81e 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitor.java @@ -18,7 +18,10 @@ package com.alibaba.druid.sql.dialect.postgresql.visitor; import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithQuery; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGArrayExpr; +import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGBoxExpr; +import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGExtractExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGParameter; +import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGPointExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGTypeCastExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGDeleteStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGFunctionTableSource; @@ -94,5 +97,17 @@ public interface PGASTVisitor extends SQLASTVisitor { void endVisit(PGArrayExpr x); boolean visit(PGArrayExpr x); + + void endVisit(PGExtractExpr x); + + boolean visit(PGExtractExpr x); + + void endVisit(PGBoxExpr x); + + boolean visit(PGBoxExpr x); + + void endVisit(PGPointExpr x); + + boolean visit(PGPointExpr x); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitorAdapter.java index ea99f0fcc6..247f9e6e73 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitorAdapter.java @@ -18,7 +18,10 @@ package com.alibaba.druid.sql.dialect.postgresql.visitor; import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithQuery; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGArrayExpr; +import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGBoxExpr; +import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGExtractExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGParameter; +import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGPointExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGTypeCastExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGDeleteStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGFunctionTableSource; @@ -199,5 +202,35 @@ public class PGASTVisitorAdapter extends SQLASTVisitorAdapter implements PGASTVi public boolean visit(PGArrayExpr x) { return true; } + + @Override + public void endVisit(PGExtractExpr x) { + + } + + @Override + public boolean visit(PGExtractExpr x) { + return true; + } + + @Override + public void endVisit(PGBoxExpr x) { + + } + + @Override + public boolean visit(PGBoxExpr x) { + return true; + } + + @Override + public void endVisit(PGPointExpr x) { + + } + + @Override + public boolean visit(PGPointExpr x) { + return true; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGOutputVisitor.java index 30629e7d6f..bf19c2b7c1 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGOutputVisitor.java @@ -21,7 +21,10 @@ import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithQuery; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGArrayExpr; +import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGBoxExpr; +import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGExtractExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGParameter; +import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGPointExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGTypeCastExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGDeleteStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGFunctionTableSource; @@ -525,5 +528,43 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor print("]"); return false; } + + @Override + public void endVisit(PGExtractExpr x) { + + } + + @Override + public boolean visit(PGExtractExpr x) { + print("EXTRACT ("); + print(x.getField().name()); + print(" FROM "); + x.getSource().accept(this); + print(")"); + return false; + } + + @Override + public boolean visit(PGBoxExpr x) { + print("BOX "); + x.getValue().accept(this); + return false; + } + @Override + public void endVisit(PGBoxExpr x) { + + } + + @Override + public boolean visit(PGPointExpr x) { + print("POINT "); + x.getValue().accept(this); + return false; + } + + @Override + public void endVisit(PGPointExpr x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java index 9526594320..87c7750684 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java @@ -24,7 +24,10 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithClause; import com.alibaba.druid.sql.dialect.postgresql.ast.PGWithQuery; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGArrayExpr; +import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGBoxExpr; +import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGExtractExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGParameter; +import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGPointExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGTypeCastExpr; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGDeleteStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGFunctionTableSource; @@ -309,4 +312,34 @@ public class PGSchemaStatVisitor extends SchemaStatVisitor implements PGASTVisit public boolean visit(PGArrayExpr x) { return true; } + + @Override + public void endVisit(PGExtractExpr x) { + + } + + @Override + public boolean visit(PGExtractExpr x) { + return true; + } + + @Override + public void endVisit(PGBoxExpr x) { + + } + + @Override + public boolean visit(PGBoxExpr x) { + return true; + } + + @Override + public void endVisit(PGPointExpr x) { + + } + + @Override + public boolean visit(PGPointExpr x) { + return true; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java index 08bd2b9ebd..69e2a97f7a 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java @@ -33,6 +33,7 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReference import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.SQLExprParser; import com.alibaba.druid.sql.parser.Token; +import com.alibaba.druid.util.JdbcConstants; public class SQLServerExprParser extends SQLExprParser { @@ -40,12 +41,14 @@ public class SQLServerExprParser extends SQLExprParser { public SQLServerExprParser(Lexer lexer){ super(lexer); + this.dbType = JdbcConstants.SQL_SERVER; this.aggregateFunctions = AGGREGATE_FUNCTIONS; } public SQLServerExprParser(String sql){ this(new SQLServerLexer(sql)); this.lexer.nextToken(); + this.dbType = JdbcConstants.SQL_SERVER; } public SQLExpr primary() { diff --git a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java index 503b1e85f3..00aa846896 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java @@ -498,7 +498,15 @@ public class Lexer { scanChar(); if (ch == '|') { scanChar(); - token = Token.BARBAR; + if (ch == '/') { + scanChar(); + token = Token.BARBARSLASH; + } else { + token = Token.BARBAR; + } + } else if (ch == '/') { + scanChar(); + token = Token.BARSLASH; } else { token = Token.BAR; } @@ -563,6 +571,9 @@ public class Lexer { } else if (ch == '<') { scanChar(); token = Token.BANGLT; + } else if (ch == '!') { + scanChar(); + token = Token.BANGBANG; // postsql } else { token = Token.BANG; } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java index 4caaf5c444..e5c3610454 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -149,7 +149,7 @@ public class SQLExprParser extends SQLParser { if (lexer.token() == Token.CARET) { lexer.nextToken(); SQLExpr rightExp = primary(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BitwiseXor, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BitwiseXor, rightExp, getDbType()); expr = bitXorRest(expr); } @@ -165,17 +165,17 @@ public class SQLExprParser extends SQLParser { if (lexer.token() == Token.STAR) { lexer.nextToken(); SQLExpr rightExp = bitXor(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Multiply, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Multiply, rightExp, getDbType()); expr = multiplicativeRest(expr); } else if (lexer.token() == Token.SLASH) { lexer.nextToken(); SQLExpr rightExp = bitXor(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Divide, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Divide, rightExp, getDbType()); expr = multiplicativeRest(expr); } else if (lexer.token() == Token.PERCENT) { lexer.nextToken(); SQLExpr rightExp = bitXor(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Modulus, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Modulus, rightExp, getDbType()); expr = multiplicativeRest(expr); } return expr; @@ -997,7 +997,7 @@ public class SQLExprParser extends SQLParser { while (lexer.token() == Token.AMP) { lexer.nextToken(); SQLExpr rightExp = shift(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BitwiseAnd, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BitwiseAnd, rightExp, getDbType()); } return expr; } @@ -1011,7 +1011,7 @@ public class SQLExprParser extends SQLParser { while (lexer.token() == Token.BAR) { lexer.nextToken(); SQLExpr rightExp = bitAnd(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BitwiseOr, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BitwiseOr, rightExp, getDbType()); expr = bitAndRest(expr); } return expr; @@ -1033,18 +1033,18 @@ public class SQLExprParser extends SQLParser { } rightExp = equalityRest(rightExp); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Equality, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Equality, rightExp, getDbType()); } else if (lexer.token() == Token.BANGEQ) { lexer.nextToken(); rightExp = bitOr(); rightExp = equalityRest(rightExp); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotEqual, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotEqual, rightExp, getDbType()); } else if (lexer.token() == Token.COLONEQ) { lexer.nextToken(); rightExp = expr(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Assignment, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Assignment, rightExp, getDbType()); } return expr; @@ -1092,18 +1092,18 @@ public class SQLExprParser extends SQLParser { lexer.nextToken(); SQLExpr rightExp = multiplicative(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Add, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Add, rightExp, getDbType()); expr = additiveRest(expr); } else if (lexer.token() == Token.BARBAR) { lexer.nextToken(); SQLExpr rightExp = multiplicative(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Concat, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Concat, rightExp, getDbType()); expr = additiveRest(expr); } else if (lexer.token() == Token.SUB) { lexer.nextToken(); SQLExpr rightExp = multiplicative(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Subtract, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Subtract, rightExp, getDbType()); expr = additiveRest(expr); } @@ -1120,13 +1120,13 @@ public class SQLExprParser extends SQLParser { lexer.nextToken(); SQLExpr rightExp = additive(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.LeftShift, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.LeftShift, rightExp, getDbType()); expr = shiftRest(expr); } else if (lexer.token() == Token.GTGT) { lexer.nextToken(); SQLExpr rightExp = additive(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.RightShift, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.RightShift, rightExp, getDbType()); expr = shiftRest(expr); } @@ -1144,7 +1144,7 @@ public class SQLExprParser extends SQLParser { lexer.nextToken(); SQLExpr rightExp = relational(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BooleanAnd, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BooleanAnd, rightExp, getDbType()); } else { break; } @@ -1165,12 +1165,12 @@ public class SQLExprParser extends SQLParser { lexer.nextToken(); SQLExpr rightExp = and(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BooleanOr, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BooleanOr, rightExp, getDbType()); } else if (lexer.token() == Token.XOR) { lexer.nextToken(); SQLExpr rightExp = and(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BooleanXor, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BooleanXor, rightExp, getDbType()); } else { break; } @@ -1198,7 +1198,7 @@ public class SQLExprParser extends SQLParser { } rightExp = bitOr(); - expr = new SQLBinaryOpExpr(expr, op, rightExp); + expr = new SQLBinaryOpExpr(expr, op, rightExp, getDbType()); // expr = relationalRest(expr); } else if (lexer.token() == Token.LTEQ) { lexer.nextToken(); @@ -1206,12 +1206,12 @@ public class SQLExprParser extends SQLParser { // rightExp = relationalRest(rightExp); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.LessThanOrEqual, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.LessThanOrEqual, rightExp, getDbType()); } else if (lexer.token() == Token.LTEQGT) { lexer.nextToken(); rightExp = bitOr(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.LessThanOrEqualOrGreaterThan, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.LessThanOrEqualOrGreaterThan, rightExp, getDbType()); } else if (lexer.token() == Token.GT) { SQLBinaryOperator op = SQLBinaryOperator.GreaterThan; @@ -1224,47 +1224,47 @@ public class SQLExprParser extends SQLParser { rightExp = bitOr(); - expr = new SQLBinaryOpExpr(expr, op, rightExp); + expr = new SQLBinaryOpExpr(expr, op, rightExp, getDbType()); } else if (lexer.token() == Token.GTEQ) { lexer.nextToken(); rightExp = bitOr(); // rightExp = relationalRest(rightExp); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.GreaterThanOrEqual, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.GreaterThanOrEqual, rightExp, getDbType()); } else if (lexer.token() == Token.BANGLT) { lexer.nextToken(); rightExp = bitOr(); // rightExp = relationalRest(rightExp); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotLessThan, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotLessThan, rightExp, getDbType()); } else if (lexer.token() == Token.BANGGT) { lexer.nextToken(); rightExp = bitOr(); rightExp = relationalRest(rightExp); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotGreaterThan, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotGreaterThan, rightExp, getDbType()); } else if (lexer.token() == Token.LTGT) { lexer.nextToken(); rightExp = bitOr(); // rightExp = relationalRest(rightExp); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.LessThanOrGreater, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.LessThanOrGreater, rightExp, getDbType()); } else if (lexer.token() == Token.LIKE) { lexer.nextToken(); rightExp = bitOr(); // rightExp = relationalRest(rightExp); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Like, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Like, rightExp, getDbType()); if (lexer.token() == Token.ESCAPE) { lexer.nextToken(); rightExp = primary(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Escape, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Escape, rightExp, getDbType()); } } else if (identifierEquals("RLIKE")) { lexer.nextToken(); @@ -1272,7 +1272,7 @@ public class SQLExprParser extends SQLParser { rightExp = relationalRest(rightExp); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.RLike, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.RLike, rightExp, getDbType()); } else if (lexer.token() == (Token.NOT)) { lexer.nextToken(); expr = notRationalRest(expr); @@ -1288,10 +1288,10 @@ public class SQLExprParser extends SQLParser { if (lexer.token() == (Token.NOT)) { lexer.nextToken(); SQLExpr rightExpr = primary(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.IsNot, rightExpr); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.IsNot, rightExpr, getDbType()); } else { SQLExpr rightExpr = primary(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Is, rightExpr); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Is, rightExpr, getDbType()); } } else if (lexer.token() == Token.IN) { expr = inRest(expr); @@ -1307,12 +1307,12 @@ public class SQLExprParser extends SQLParser { rightExp = relationalRest(rightExp); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotLike, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotLike, rightExp, getDbType()); if (lexer.token() == Token.ESCAPE) { lexer.nextToken(); rightExp = expr(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Escape, rightExp); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Escape, rightExp, getDbType()); } } else if (lexer.token() == Token.IN) { lexer.nextToken(); @@ -1352,7 +1352,7 @@ public class SQLExprParser extends SQLParser { rightExp = relationalRest(rightExp); - return new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotRLike, rightExp); + return new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotRLike, rightExp, getDbType()); } else { throw new ParserException("TODO " + lexer.token()); } diff --git a/src/main/java/com/alibaba/druid/sql/parser/Token.java b/src/main/java/com/alibaba/druid/sql/parser/Token.java index 3a42ad4f1c..a20e118eb4 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Token.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Token.java @@ -264,6 +264,7 @@ public enum Token { GT(">"), LT("<"), BANG("!"), + BANGBANG("!!"), TILDE("~"), QUES("?"), COLON(":"), @@ -279,6 +280,8 @@ public enum Token { BANGLT("!<"), AMPAMP("&&"), BARBAR("||"), + BARBARSLASH("||/"), + BARSLASH("|/"), PLUS("+"), SUB("-"), STAR("*"), @@ -289,7 +292,9 @@ public enum Token { PERCENT("%"), LTLT("<<"), GTGT(">>"), - MONKEYS_AT("@"); + MONKEYS_AT("@"), + POUND("#") + ; public final String name; diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java index c2deade239..0ca7eab854 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -583,15 +583,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab if (expr instanceof SQLBinaryOpExpr) { SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) expr; - switch (binaryOpExpr.getOperator()) { - case BooleanAnd: - case BooleanOr: - case BooleanXor: - needQuote = true; - break; - default: - break; - } + needQuote = binaryOpExpr.getOperator().isLogical(); } if (needQuote) { diff --git a/src/main/resources/META-INF/druid/wall/postgres/deny-function.txt b/src/main/resources/META-INF/druid/wall/postgres/deny-function.txt index e2adb8acaf..86c0b86ef5 100644 --- a/src/main/resources/META-INF/druid/wall/postgres/deny-function.txt +++ b/src/main/resources/META-INF/druid/wall/postgres/deny-function.txt @@ -18,4 +18,6 @@ pg_trigger_depth session_user user version -pg_sleep \ No newline at end of file +pg_sleep +pg_sleep_for +pg_sleep_until \ No newline at end of file diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGInsertTest6_multi.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGInsertTest6_multi.java new file mode 100644 index 0000000000..8b6313af3b --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGInsertTest6_multi.java @@ -0,0 +1,59 @@ +/* + * Copyright 1999-2011 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.bvt.sql.postgresql; + +import java.util.List; + +import org.junit.Assert; + +import com.alibaba.druid.sql.PGTest; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser; +import com.alibaba.druid.sql.dialect.postgresql.visitor.PGSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; + +public class PGInsertTest6_multi extends PGTest { + + public void test_0() throws Exception { + String sql = "INSERT INTO products (product_no, name, price) VALUES" + + "\n (1, 'Cheese', 9.99)," + + "\n (2, 'Bread', 1.99)," + + "\n (3, 'Milk', 2.99);"; + + PGSQLStatementParser parser = new PGSQLStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + PGSchemaStatVisitor visitor = new PGSchemaStatVisitor(); + statemen.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("products"))); + + Assert.assertEquals(3, visitor.getColumns().size()); + + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("products", "product_no"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("products", "name"))); + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("products", "price"))); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/datatypes/BitsTest.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/datatypes/BitsTest.java new file mode 100644 index 0000000000..4eddbccf4e --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/datatypes/BitsTest.java @@ -0,0 +1,16 @@ +package com.alibaba.druid.bvt.sql.postgresql.datatypes; + +import com.alibaba.druid.sql.PGTest; +import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGTypeCastExpr; +import com.alibaba.druid.sql.dialect.postgresql.parser.PGExprParser; + +public class BitsTest extends PGTest { + + public void test_timestamp() throws Exception { + String sql = "44::bit(10)"; + PGExprParser parser = new PGExprParser(sql); + PGTypeCastExpr expr = (PGTypeCastExpr) parser.expr(); + System.out.println(expr.toString()); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/expr/BoxTest.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/expr/BoxTest.java new file mode 100644 index 0000000000..8a3f025851 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/expr/BoxTest.java @@ -0,0 +1,23 @@ +package com.alibaba.druid.bvt.sql.postgresql.expr; + + +import org.junit.Assert; + +import com.alibaba.druid.sql.PGTest; +import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; +import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGBoxExpr; +import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGPointExpr; +import com.alibaba.druid.sql.dialect.postgresql.parser.PGExprParser; + + +public class BoxTest extends PGTest { + public void test_timestamp() throws Exception { + String sql = "box '((0,0),(1,1))' + point '(2.0,0)'"; + PGExprParser parser = new PGExprParser(sql); + SQLBinaryOpExpr binaryExpr = (SQLBinaryOpExpr) parser.expr(); + + PGBoxExpr box = (PGBoxExpr) binaryExpr.getLeft(); + PGPointExpr point = (PGPointExpr) binaryExpr.getRight(); + Assert.assertEquals("BOX '((0,0),(1,1))' + POINT '(2.0,0)'", binaryExpr.toString()); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/expr/ExtractTest_Year.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/expr/ExtractTest_Year.java new file mode 100644 index 0000000000..68930da5d0 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/expr/ExtractTest_Year.java @@ -0,0 +1,15 @@ +package com.alibaba.druid.bvt.sql.postgresql.expr; + +import com.alibaba.druid.sql.PGTest; +import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGExtractExpr; +import com.alibaba.druid.sql.dialect.postgresql.parser.PGExprParser; + + +public class ExtractTest_Year extends PGTest { + public void test_timestamp() throws Exception { + String sql = "EXTRACT(YEAR FROM TIMESTAMP '2001-02-16 20:38:40')"; + PGExprParser parser = new PGExprParser(sql); + PGExtractExpr expr = (PGExtractExpr) parser.expr(); + System.out.println(expr.toString()); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/expr/PolygonTest.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/expr/PolygonTest.java new file mode 100644 index 0000000000..f9b286b2ca --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/expr/PolygonTest.java @@ -0,0 +1,21 @@ +package com.alibaba.druid.bvt.sql.postgresql.expr; + + + +import org.junit.Assert; + +import com.alibaba.druid.sql.PGTest; +import com.alibaba.druid.sql.ast.expr.SQLUnaryExpr; +import com.alibaba.druid.sql.ast.expr.SQLUnaryOperator; +import com.alibaba.druid.sql.dialect.postgresql.parser.PGExprParser; + + +public class PolygonTest extends PGTest { + public void test_timestamp() throws Exception { + String sql = "# '((1,0),(0,1),(-1,0))'"; + PGExprParser parser = new PGExprParser(sql); + SQLUnaryExpr unaryExpr = (SQLUnaryExpr) parser.expr(); + Assert.assertEquals(SQLUnaryOperator.Pound, unaryExpr.getOperator()); + + } +}