improved sql parser for postgresql

This commit is contained in:
wenshao
2014-11-16 15:35:47 +08:00
parent 6983fa6d1f
commit 8e6dbe121b
29 changed files with 655 additions and 74 deletions
@@ -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;
}
}
@@ -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
}
@@ -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);
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -158,4 +158,9 @@ public class PGLexer extends Lexer {
stringVal = new String(buf, 0, bufPos);
}
}
public void scanSharp() {
token = Token.POUND;
scanChar();
}
}
@@ -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);
}
@@ -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;
}
}
@@ -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) {
}
}
@@ -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;
}
}