support pgsql function tablesource

This commit is contained in:
wenshao
2012-07-10 11:14:20 +08:00
parent 74df8eb04c
commit 9559a638d9
11 changed files with 450 additions and 71 deletions
@@ -0,0 +1,39 @@
package com.alibaba.druid.sql.dialect.postgresql.ast.expr;
import com.alibaba.druid.sql.ast.SQLDataType;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.dialect.postgresql.ast.PGSQLObjectImpl;
import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;
public class PGParameter extends PGSQLObjectImpl {
private static final long serialVersionUID = 1L;
private SQLExpr name;
private SQLDataType dataType;
public SQLExpr getName() {
return name;
}
public void setName(SQLExpr name) {
this.name = name;
}
public SQLDataType getDataType() {
return dataType;
}
public void setDataType(SQLDataType dataType) {
this.dataType = dataType;
}
@Override
public void accept0(PGASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, name);
acceptChild(visitor, dataType);
}
visitor.endVisit(this);
}
}
@@ -0,0 +1,43 @@
package com.alibaba.druid.sql.dialect.postgresql.ast.stmt;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.dialect.postgresql.ast.PGSQLObject;
import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGParameter;
import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class PGFunctionTableSource extends SQLExprTableSource implements PGSQLObject {
private static final long serialVersionUID = 1L;
private final List<PGParameter> parameters = new ArrayList<PGParameter>();
public PGFunctionTableSource(){
}
public PGFunctionTableSource(SQLExpr expr){
this.expr = expr;
}
public List<PGParameter> getParameters() {
return parameters;
}
@Override
protected void accept0(SQLASTVisitor visitor) {
this.accept0((PGASTVisitor) visitor);
}
public void accept0(PGASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, this.expr);
acceptChild(visitor, this.parameters);
}
visitor.endVisit(this);
}
}
@@ -1,5 +1,7 @@
package com.alibaba.druid.sql.dialect.postgresql.parser;
import static com.alibaba.druid.sql.parser.Token.LITERAL_CHARS;
import java.util.HashMap;
import java.util.Map;
@@ -51,4 +53,90 @@ public class PGLexer extends Lexer {
super(input);
super.keywods = DEFAULT_PG_KEYWORDS;
}
protected void scanString() {
np = bp;
boolean hasSpecial = false;
for (;;) {
if (bp >= buflen) {
lexError(tokenPos, "unclosed.str.lit");
return;
}
ch = buf[++bp];
if (ch == '\\') {
scanChar();
if (!hasSpecial) {
System.arraycopy(buf, np + 1, sbuf, 0, sp);
hasSpecial = true;
}
switch (ch) {
case '\0':
putChar('\0');
break;
case '\'':
putChar('\'');
break;
case '"':
putChar('"');
break;
case 'b':
putChar('\b');
break;
case 'n':
putChar('\n');
break;
case 'r':
putChar('\r');
break;
case 't':
putChar('\t');
break;
case '\\':
putChar('\\');
break;
case 'Z':
putChar((char) 0x1A); // ctrl + Z
break;
default:
putChar(ch);
break;
}
scanChar();
}
if (ch == '\'') {
scanChar();
if (ch != '\'') {
token = LITERAL_CHARS;
break;
} else {
System.arraycopy(buf, np + 1, sbuf, 0, sp);
hasSpecial = true;
putChar('\'');
continue;
}
}
if (!hasSpecial) {
sp++;
continue;
}
if (sp == sbuf.length) {
putChar(ch);
} else {
sbuf[sp++] = ch;
}
}
if (!hasSpecial) {
stringVal = new String(buf, np + 1, sp);
} else {
stringVal = new String(sbuf, 0, sp);
}
}
}
@@ -1,10 +1,15 @@
package com.alibaba.druid.sql.dialect.postgresql.parser;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLSetQuantifier;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGParameter;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGFunctionTableSource;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.IntoOption;
import com.alibaba.druid.sql.parser.ParserException;
@@ -200,4 +205,44 @@ public class PGSelectParser extends SQLSelectParser {
return queryRest(queryBlock);
}
protected SQLTableSource parseTableSourceRest(SQLTableSource tableSource) throws ParserException {
if (lexer.token() == Token.AS && tableSource instanceof SQLExprTableSource) {
String alias = this.as();
if (lexer.token() == Token.LPAREN) {
SQLExprTableSource exprTableSource = (SQLExprTableSource) tableSource;
PGFunctionTableSource functionTableSource = new PGFunctionTableSource(exprTableSource.getExpr());
functionTableSource.setAlias(alias);
lexer.nextToken();
parserParameters(functionTableSource.getParameters());
accept(Token.RPAREN);
return super.parseTableSourceRest(functionTableSource);
}
}
return super.parseTableSourceRest(tableSource);
}
private void parserParameters(List<PGParameter> parameters) {
for (;;) {
PGParameter parameter = new PGParameter();
parameter.setName(this.exprParser.name());
parameter.setDataType(this.exprParser.parseDataType());
parameters.add(parameter);
if (lexer.token() == Token.COMMA || lexer.token() == Token.SEMI) {
lexer.nextToken();
}
if (lexer.token() != Token.BEGIN && lexer.token() != Token.RPAREN) {
continue;
}
break;
}
}
}
@@ -4,7 +4,9 @@ import com.alibaba.druid.sql.dialect.postgresql.ast.PGAggregateExpr;
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.PGAnalytic;
import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGParameter;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGDeleteStatement;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGFunctionTableSource;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGInsertStatement;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectStatement;
@@ -17,9 +19,9 @@ public interface PGASTVisitor extends SQLASTVisitor {
void endVisit(PGSelectQueryBlock x);
boolean visit(PGSelectQueryBlock x);
void endVisit(PGSelectQueryBlock.WindowClause x);
boolean visit(PGSelectQueryBlock.WindowClause x);
void endVisit(PGSelectQueryBlock.FetchClause x);
@@ -57,14 +59,21 @@ public interface PGASTVisitor extends SQLASTVisitor {
void endVisit(PGUpdateStatement x);
boolean visit(PGUpdateStatement x);
void endVisit(PGAggregateExpr x);
boolean visit(PGAggregateExpr x);
void endVisit(PGAnalytic x);
boolean visit(PGAnalytic x);
void endVisit(PGParameter x);
boolean visit(PGParameter x);
void endVisit(PGFunctionTableSource x);
boolean visit(PGFunctionTableSource x);
}
@@ -4,7 +4,9 @@ import com.alibaba.druid.sql.dialect.postgresql.ast.PGAggregateExpr;
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.PGAnalytic;
import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGParameter;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGDeleteStatement;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGFunctionTableSource;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGInsertStatement;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.FetchClause;
@@ -126,7 +128,7 @@ public class PGASTVisitorAdapter extends SQLASTVisitorAdapter implements PGASTVi
@Override
public void endVisit(PGSelectQueryBlock x) {
}
@Override
@@ -134,23 +136,43 @@ public class PGASTVisitorAdapter extends SQLASTVisitorAdapter implements PGASTVi
return true;
}
@Override
public void endVisit(PGAggregateExpr x) {
}
@Override
public void endVisit(PGAggregateExpr x) {
}
@Override
public boolean visit(PGAggregateExpr x) {
return false;
}
@Override
public boolean visit(PGAggregateExpr x) {
return true;
}
@Override
public void endVisit(PGAnalytic x) {
}
@Override
public void endVisit(PGAnalytic x) {
}
@Override
public boolean visit(PGAnalytic x) {
@Override
public boolean visit(PGAnalytic x) {
return false;
}
return true;
}
@Override
public void endVisit(PGParameter x) {
}
@Override
public boolean visit(PGParameter x) {
return true;
}
@Override
public void endVisit(PGFunctionTableSource x) {
}
@Override
public boolean visit(PGFunctionTableSource x) {
return true;
}
}
@@ -7,7 +7,9 @@ import com.alibaba.druid.sql.dialect.postgresql.ast.PGAggregateExpr;
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.PGAnalytic;
import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGParameter;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGDeleteStatement;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGFunctionTableSource;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGInsertStatement;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.FetchClause;
@@ -163,7 +165,7 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor
print(x.getIntoOption().name());
print(" ");
}
x.getInto().accept(this);
}
@@ -221,7 +223,6 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor
return false;
}
@Override
public void endVisit(PGTruncateStatement x) {
@@ -291,7 +292,7 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor
x.getWhere().setParent(x);
x.getWhere().accept(this);
}
if (x.isReturning()) {
println();
print("RETURNING *");
@@ -302,16 +303,16 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor
@Override
public void endVisit(PGInsertStatement x) {
}
@Override
public boolean visit(PGInsertStatement x) {
if (x.getWith() != null) {
x.getWith().accept(this);
println();
}
print("INSERT INTO ");
x.getTableName().accept(this);
@@ -343,7 +344,7 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor
x.getQuery().accept(this);
}
}
if (x.getReturning() != null) {
println();
print("RETURNING ");
@@ -352,36 +353,36 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor
return false;
}
@Override
public void endVisit(PGSelectStatement x) {
}
@Override
public boolean visit(PGSelectStatement x) {
if (x.getWith() != null) {
x.getWith().accept(this);
println();
}
return visit((SQLSelectStatement) x);
}
@Override
public void endVisit(PGUpdateStatement x) {
}
@Override
public boolean visit(PGUpdateStatement x) {
if (x.getWith() != null) {
x.getWith().accept(this);
println();
}
print("UPDATE ");
if (x.isOnly()) {
print("ONLY ");
}
@@ -396,7 +397,7 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor
}
x.getItems().get(i).accept(this);
}
if (x.getFrom() != null) {
println();
print("FROM ");
@@ -409,7 +410,7 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor
x.getWhere().setParent(x);
x.getWhere().accept(this);
}
if (x.getReturning().size() > 0) {
println();
print("RETURNING ");
@@ -421,48 +422,86 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor
@Override
public void endVisit(PGSelectQueryBlock x) {
}
@Override
public void endVisit(PGAggregateExpr x) {
}
@Override
public void endVisit(PGAggregateExpr x) {
@Override
public boolean visit(PGAggregateExpr x) {
}
@Override
public boolean visit(PGAggregateExpr x) {
print(x.getMethodName());
print("(");
printAndAccept(x.getArguments(), ", ");
print(")");
if(x.getOver() != null){
x.getOver().accept(this);
if (x.getOver() != null) {
x.getOver().accept(this);
}
return false;
}
}
@Override
public void endVisit(PGAnalytic x) {
@Override
public void endVisit(PGAnalytic x) {
}
}
@Override
public boolean visit(PGAnalytic x) {
print(" OVER (");
if (x.getPartitionBy().size() > 0) {
int mark = 0;
for (SQLExpr e : x.getPartitionBy()) {
if (mark++ != 0) {
print(", ");
}
e.accept(this);
}
}
if (x.getOrderBy() != null) {
x.getOrderBy().accept(this);
}
print(")");
return false;
}
@Override
public void endVisit(PGParameter x) {
}
@Override
public boolean visit(PGParameter x) {
x.getName().accept(this);
print(" ");
x.getDataType().accept(this);
return false;
}
@Override
public boolean visit(PGFunctionTableSource x) {
x.getExpr().accept(this);
if (x.getAlias() != null) {
print(" AS ");
print(x.getAlias());
}
if (x.getParameters().size() > 0) {
print('(');
printAndAccept(x.getParameters(), ", ");
print(')');
}
return false;
}
@Override
public void endVisit(PGFunctionTableSource x) {
}
@Override
public boolean visit(PGAnalytic x) {
print(" OVER (");
if(x.getPartitionBy().size() > 0){
int mark = 0;
for(SQLExpr e:x.getPartitionBy()){
if(mark++ != 0){
print(", ");
}
e.accept(this);
}
}
if(x.getOrderBy() != null){
x.getOrderBy().accept(this);
}
print(")");
return false;
}
}
@@ -11,7 +11,9 @@ import com.alibaba.druid.sql.dialect.postgresql.ast.PGAggregateExpr;
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.PGAnalytic;
import com.alibaba.druid.sql.dialect.postgresql.ast.expr.PGParameter;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGDeleteStatement;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGFunctionTableSource;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGInsertStatement;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock;
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.FetchClause;
@@ -262,4 +264,24 @@ public class PGSchemaStatVisitor extends SchemaStatVisitor implements PGASTVisit
public boolean visit(PGAnalytic x) {
return false;
}
@Override
public void endVisit(PGParameter x) {
}
@Override
public boolean visit(PGParameter x) {
return false;
}
@Override
public void endVisit(PGFunctionTableSource x) {
}
@Override
public boolean visit(PGFunctionTableSource x) {
return true;
}
}