mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
enhance sql server parser
This commit is contained in:
+29
-3
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -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);
|
||||
}
|
||||
|
||||
+11
@@ -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) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+13
-1
@@ -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) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+11
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user