enhance sql server parser

This commit is contained in:
温少
2012-03-18 21:43:03 +08:00
parent 07860f72b6
commit 01a8023dcb
10 changed files with 137 additions and 6 deletions
@@ -1,9 +1,13 @@
package com.alibaba.druid.sql.dialect.sqlserver.ast.expr;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerObjectImpl;
import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor;
public class SQLServerObjectReferenceExpr extends SQLServerObjectImpl implements SQLServerExpr {
public class SQLServerObjectReferenceExpr extends SQLServerObjectImpl implements SQLServerExpr, SQLName {
private static final long serialVersionUID = 1L;
@@ -11,10 +15,32 @@ public class SQLServerObjectReferenceExpr extends SQLServerObjectImpl implements
private String database;
private String schema;
private String object;
public SQLServerObjectReferenceExpr() {
}
public SQLServerObjectReferenceExpr(SQLExpr owner, String name) {
if (owner instanceof SQLIdentifierExpr) {
this.database = ((SQLIdentifierExpr) owner).getName();
this.object = name;
} else if (owner instanceof SQLPropertyExpr) {
SQLPropertyExpr propExpr = (SQLPropertyExpr) owner;
this.server = ((SQLIdentifierExpr) propExpr.getOwner()).getName();
this.database = propExpr.getName();
this.object = name;
} else {
throw new IllegalArgumentException(owner.toString());
}
}
@Override
public void accept0(SQLServerASTVisitor visitor) {
if (visitor.visit(this)) {
}
visitor.endVisit(this);
}
public void output(StringBuffer buf) {
@@ -1,8 +1,12 @@
package com.alibaba.druid.sql.dialect.sqlserver.parser;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr;
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;
public class SQLServerExprParser extends SQLExprParser {
@@ -15,4 +19,23 @@ public class SQLServerExprParser extends SQLExprParser {
this.lexer.nextToken();
}
public SQLExpr primaryRest(SQLExpr expr) throws ParserException {
if (lexer.token() == Token.DOTDOT) {
expr = nameRest((SQLName) expr);
}
return super.primaryRest(expr);
}
public SQLName nameRest(SQLName name) throws ParserException {
if (lexer.token() == Token.DOTDOT) {
lexer.nextToken();
String text = lexer.stringVal();
lexer.nextToken();
name = new SQLServerObjectReferenceExpr(name, text);
}
return super.nameRest(name);
}
}
@@ -8,6 +8,7 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;
import com.alibaba.druid.sql.dialect.sqlserver.ast.Top;
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.SQLSelectParser;
import com.alibaba.druid.sql.parser.Token;
@@ -76,4 +77,8 @@ public class SQLServerSelectParser extends SQLSelectParser {
return queryRest(queryBlock);
}
protected SQLExprParser createExprParser() {
return new SQLServerExprParser(lexer);
}
}
@@ -2,6 +2,7 @@ package com.alibaba.druid.sql.dialect.sqlserver.visitor;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;
import com.alibaba.druid.sql.dialect.sqlserver.ast.Top;
import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public interface SQLServerASTVisitor extends SQLASTVisitor {
@@ -13,4 +14,8 @@ public interface SQLServerASTVisitor extends SQLASTVisitor {
boolean visit(Top x);
void endVisit(Top x);
boolean visit(SQLServerObjectReferenceExpr x);
void endVisit(SQLServerObjectReferenceExpr x);
}
@@ -2,6 +2,7 @@ package com.alibaba.druid.sql.dialect.sqlserver.visitor;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;
import com.alibaba.druid.sql.dialect.sqlserver.ast.Top;
import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr;
import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;
public class SQLServerASTVisitorAdapter extends SQLASTVisitorAdapter implements SQLServerASTVisitor {
@@ -25,5 +26,15 @@ public class SQLServerASTVisitorAdapter extends SQLASTVisitorAdapter implements
public void endVisit(Top x) {
}
@Override
public boolean visit(SQLServerObjectReferenceExpr x) {
return true;
}
@Override
public void endVisit(SQLServerObjectReferenceExpr x) {
}
}
@@ -3,6 +3,7 @@ package com.alibaba.druid.sql.dialect.sqlserver.visitor;
import com.alibaba.druid.sql.ast.SQLSetQuantifier;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;
import com.alibaba.druid.sql.dialect.sqlserver.ast.Top;
import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr;
import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;
public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLServerASTVisitor {
@@ -42,7 +43,7 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe
}
if (x.getGroupBy() != null) {
print(" ");
println();
x.getGroupBy().accept(this);
}
@@ -67,4 +68,15 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe
}
@Override
public boolean visit(SQLServerObjectReferenceExpr x) {
print(x.toString());
return false;
}
@Override
public void endVisit(SQLServerObjectReferenceExpr x) {
}
}
@@ -3,6 +3,7 @@ package com.alibaba.druid.sql.dialect.sqlserver.visitor;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;
import com.alibaba.druid.sql.dialect.sqlserver.ast.Top;
import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
@@ -28,5 +29,15 @@ public class SQLServerSchemaStatVisitor extends SchemaStatVisitor implements SQL
}
@Override
public boolean visit(SQLServerObjectReferenceExpr x) {
return false;
}
@Override
public void endVisit(SQLServerObjectReferenceExpr x) {
}
}
@@ -626,7 +626,13 @@ public class SQLExprParser extends SQLParser {
SQLName name = new SQLIdentifierExpr(identName);
while (lexer.token() == Token.DOT) {
name = nameRest(name);
return name;
}
public SQLName nameRest(SQLName name) throws ParserException {
if (lexer.token() == Token.DOT) {
lexer.nextToken();
if (lexer.token() == Token.KEY) {
@@ -646,6 +652,7 @@ public class SQLExprParser extends SQLParser {
name = new SQLPropertyExpr(name, lexer.stringVal());
}
lexer.nextToken();
name = nameRest(name);
}
return name;
@@ -494,7 +494,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter {
x.getQuery().accept(this);
if (x.getOrderBy() != null) {
print(" ");
println();
x.getOrderBy().accept(this);
}
@@ -0,0 +1,31 @@
package com.alibaba.druid.bvt.sql.sqlserver;
import junit.framework.Assert;
import junit.framework.TestCase;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser;
import com.alibaba.druid.sql.test.TestUtils;
public class SQLServerSelectTest2 extends TestCase {
public void test_isEmpty() throws Exception {
String sql = "SELECT TOP 1 name FROM (SELECT TOP 9 name FROM master..syslogins ORDER BY name ASC) sq ORDER BY name DESC ";
String expect = "SELECT TOP 1 name\n" + //
"FROM (SELECT TOP 9 name\n" + //
"\tFROM master..syslogins\n" + //
"\tORDER BY name ASC\n" + //
"\t) sq\n" + //
"ORDER BY name DESC";
SQLServerStatementParser parser = new SQLServerStatementParser(sql);
SQLStatement stmt = parser.parseStatementList().get(0);
String text = TestUtils.outputSqlServer(stmt);
Assert.assertEquals(expect, text);
System.out.println(text);
}
}