Merge branch 'master' of github.com:AlibabaTech/druid

This commit is contained in:
xiusiyan
2012-03-18 22:17:13 +08:00
26 changed files with 315 additions and 55 deletions
@@ -16,5 +16,5 @@
package com.alibaba.druid.sql.ast;
public interface SQLName extends SQLExpr {
String getSimleName();
}
@@ -33,6 +33,10 @@ public class SQLIdentifierExpr extends SQLExprImpl implements SQLName {
this.name = name;
}
public String getSimleName() {
return name;
}
public String getName() {
return this.name;
@@ -36,6 +36,10 @@ public class SQLPropertyExpr extends SQLExprImpl implements SQLName {
public SQLPropertyExpr(){
}
public String getSimleName() {
return name;
}
public SQLExpr getOwner() {
return this.owner;
@@ -57,7 +57,6 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowWarningsStatem
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStartTransactionStatement;
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.SQLStatementParser;
import com.alibaba.druid.sql.parser.Token;
@@ -67,16 +66,12 @@ public class MySqlStatementParser extends SQLStatementParser {
public MySqlStatementParser(String sql) throws ParserException{
this(new MySqlLexer(sql));
this.lexer.nextToken();
this.exprParser = this.createExprParser();
this.exprParser = new MySqlExprParser(lexer);
}
public MySqlStatementParser(Lexer lexer){
super(lexer);
this.exprParser = this.createExprParser();
}
protected SQLExprParser createExprParser() {
return new MySqlExprParser(lexer);
this.exprParser = new MySqlExprParser(lexer);
}
public SQLCreateTableStatement parseCreateTable() throws ParserException {
@@ -179,11 +174,11 @@ public class MySqlStatementParser extends SQLStatementParser {
for (;;) {
MySqlCreateUserStatement.UserSpecification userSpec = new MySqlCreateUserStatement.UserSpecification();
SQLCharExpr expr = (SQLCharExpr) this.createExprParser().expr();
SQLCharExpr expr = (SQLCharExpr) exprParser.expr();
String user = expr.toString();
if (lexer.token() == Token.VARIANT) {
lexer.nextToken();
SQLCharExpr expr2 = (SQLCharExpr) this.createExprParser().expr();
SQLCharExpr expr2 = (SQLCharExpr) exprParser.expr();
user += '@';
user += expr2.toString();
}
@@ -198,12 +193,12 @@ public class MySqlStatementParser extends SQLStatementParser {
lexer.nextToken();
}
SQLCharExpr password = (SQLCharExpr) this.createExprParser().expr();
SQLCharExpr password = (SQLCharExpr) this.exprParser.expr();
userSpec.setPassword(password);
} else if (lexer.token() == Token.WITH) {
lexer.nextToken();
SQLCharExpr text = (SQLCharExpr) this.createExprParser().expr();
SQLCharExpr text = (SQLCharExpr) this.exprParser.expr();
userSpec.setAuthPlugin(text);
}
}
@@ -346,7 +341,7 @@ public class MySqlStatementParser extends SQLStatementParser {
statementList.add(stmt);
return true;
}
if (identifierEquals("DESCRIBE")) {
SQLStatement stmt = parseDescribe();
statementList.add(stmt);
@@ -355,13 +350,13 @@ public class MySqlStatementParser extends SQLStatementParser {
return false;
}
public SQLStatement parseDescribe() throws ParserException {
acceptIdentifier("DESCRIBE");
MySqlDescribeStatement stmt = new MySqlDescribeStatement();
stmt.setObject(this.exprParser.name());
return stmt;
}
@@ -487,15 +482,15 @@ public class MySqlStatementParser extends SQLStatementParser {
MySqlSelectQueryBlock.Limit limit = new MySqlSelectQueryBlock.Limit();
SQLExpr temp = this.createExprParser().expr();
SQLExpr temp = this.exprParser.expr();
if (lexer.token() == (Token.COMMA)) {
limit.setOffset(temp);
lexer.nextToken();
limit.setRowCount(createExprParser().expr());
limit.setRowCount(exprParser.expr());
} else if (identifierEquals("OFFSET")) {
limit.setRowCount(temp);
lexer.nextToken();
limit.setOffset(createExprParser().expr());
limit.setOffset(exprParser.expr());
} else {
limit.setRowCount(temp);
}
@@ -991,11 +986,11 @@ public class MySqlStatementParser extends SQLStatementParser {
MySqlDropUser stmt = new MySqlDropUser();
for (;;) {
SQLCharExpr expr = (SQLCharExpr) this.createExprParser().expr();
SQLCharExpr expr = (SQLCharExpr) this.exprParser.expr();
String user = expr.toString();
if (lexer.token() == Token.VARIANT) {
lexer.nextToken();
SQLCharExpr expr2 = (SQLCharExpr) this.createExprParser().expr();
SQLCharExpr expr2 = (SQLCharExpr) this.exprParser.expr();
user += '@';
user += expr2.toString();
}
@@ -1035,7 +1030,7 @@ public class MySqlStatementParser extends SQLStatementParser {
}
return stmt;
}
public SQLSelectParser createSQLSelectParser() {
return new MySqlSelectParser(this.lexer);
}
@@ -30,6 +30,10 @@ public class OracleDbLinkExpr extends SQLExprImpl implements SQLName, OracleExpr
public OracleDbLinkExpr(){
}
public String getSimleName() {
return dbLink;
}
public SQLExpr getExpr() {
return this.expr;
@@ -102,16 +102,21 @@ public class OracleStatementParser extends SQLStatementParser {
public OracleStatementParser(String sql){
super(new OracleLexer(sql));
this.lexer.nextToken();
this.exprParser = createExprParser();
this.exprParser = new OracleExprParser(lexer);
}
public OracleStatementParser(Lexer lexer){
super(lexer);
this.exprParser = createExprParser();
this.exprParser = new OracleExprParser(lexer);
}
protected OracleExprParser createExprParser() {
return new OracleExprParser(lexer);
@Override
public OracleExprParser getExprParser() {
return (OracleExprParser) exprParser;
}
public void parseHints(List<OracleHint> hints) {
this.getExprParser().parseHints(hints);
}
public OracleCreateTableParser getSQLCreateTableParser() {
@@ -121,10 +126,10 @@ public class OracleStatementParser extends SQLStatementParser {
protected void parseInsert0_hinits(SQLInsertInto insertStatement) {
if (insertStatement instanceof OracleInsertStatement) {
OracleInsertStatement stmt = (OracleInsertStatement) insertStatement;
this.createExprParser().parseHints(stmt.getHints());
this.getExprParser().parseHints(stmt.getHints());
} else {
List<OracleHint> hints = new ArrayList<OracleHint>();
this.createExprParser().parseHints(hints);
this.getExprParser().parseHints(hints);
}
}
@@ -1124,8 +1129,7 @@ public class OracleStatementParser extends SQLStatementParser {
OracleMergeStatement stmt = new OracleMergeStatement();
OracleExprParser exprParser = this.createExprParser();
exprParser.parseHints(stmt.getHints());
parseHints(stmt.getHints());
accept(Token.INTO);
stmt.setInto(exprParser.name());
@@ -1241,7 +1245,7 @@ public class OracleStatementParser extends SQLStatementParser {
List<OracleHint> hints = new ArrayList<OracleHint>();
this.createExprParser().parseHints(hints);
parseHints(hints);
if (lexer.token() == Token.INTO) {
OracleInsertStatement stmt = new OracleInsertStatement();
@@ -1290,7 +1294,7 @@ public class OracleStatementParser extends SQLStatementParser {
OracleMultiInsertStatement.ConditionalInsertClauseItem item = new OracleMultiInsertStatement.ConditionalInsertClauseItem();
item.setWhen(this.createExprParser().expr());
item.setWhen(this.exprParser.expr());
accept(Token.THEN);
OracleMultiInsertStatement.InsertIntoClause insertInto = new OracleMultiInsertStatement.InsertIntoClause();
parseInsert0(insertInto);
@@ -1430,7 +1434,7 @@ public class OracleStatementParser extends SQLStatementParser {
if (lexer.token() == Token.DELETE) {
lexer.nextToken();
this.createExprParser().parseHints(deleteStatement.getHints());
parseHints(deleteStatement.getHints());
if (lexer.token() == (Token.FROM)) {
lexer.nextToken();
@@ -22,18 +22,20 @@ import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateStatement;
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.SQLStatementParser;
import com.alibaba.druid.sql.parser.Token;
public class OracleUpdateParser extends SQLStatementParser {
public OracleUpdateParser(String sql) throws ParserException{
super(sql);
super(new OracleLexer(sql));
this.lexer.nextToken();
this.exprParser = new OracleExprParser(lexer);
}
public OracleUpdateParser(Lexer lexer){
super(lexer);
this.exprParser = new OracleExprParser(lexer);
}
public OracleUpdateStatement parseUpdateStatement() throws ParserException {
@@ -142,8 +144,4 @@ public class OracleUpdateParser extends SQLStatementParser {
lexer.nextToken();
}
}
protected SQLExprParser createExprParser() {
return new OracleExprParser(lexer);
}
}
@@ -124,7 +124,7 @@ public class PGSQLStatementParser extends SQLStatementParser {
break;
}
} else if (lexer.token() == (Token.SELECT)) {
SQLQueryExpr queryExpr = (SQLQueryExpr) this.createExprParser().expr();
SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr();
stmt.setQuery(queryExpr.getSubQuery());
}
@@ -155,7 +155,7 @@ public class PGSQLStatementParser extends SQLStatementParser {
if (lexer.token() == Token.USING) {
lexer.nextToken();
for (;;) {
SQLName name = this.createExprParser().name();
SQLName name = this.exprParser.name();
deleteStatement.getUsing().add(name);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
@@ -271,13 +271,13 @@ public class PGSQLStatementParser extends SQLStatementParser {
private PGWithQuery withQuery() {
PGWithQuery withQuery = new PGWithQuery();
withQuery.setName(this.createExprParser().expr());
withQuery.setName(this.exprParser.expr());
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
for (;;) {
SQLExpr expr = this.createExprParser().expr();
SQLExpr expr = this.exprParser.expr();
withQuery.getColumns().add(expr);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
@@ -0,0 +1,8 @@
package com.alibaba.druid.sql.dialect.sqlserver.ast.expr;
import com.alibaba.druid.sql.ast.SQLExpr;
public interface SQLServerExpr extends SQLExpr {
}
@@ -0,0 +1,103 @@
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, SQLName {
private static final long serialVersionUID = 1L;
private String server;
private String database;
private String schema;
public SQLServerObjectReferenceExpr(){
}
public SQLServerObjectReferenceExpr(SQLExpr owner){
if (owner instanceof SQLIdentifierExpr) {
this.database = ((SQLIdentifierExpr) owner).getName();
} else if (owner instanceof SQLPropertyExpr) {
SQLPropertyExpr propExpr = (SQLPropertyExpr) owner;
this.server = ((SQLIdentifierExpr) propExpr.getOwner()).getName();
this.database = propExpr.getName();
} else {
throw new IllegalArgumentException(owner.toString());
}
}
public String getSimleName() {
if (schema != null) {
return schema;
}
if (database != null) {
return database;
}
return server;
}
@Override
public void accept0(SQLServerASTVisitor visitor) {
if (visitor.visit(this)) {
}
visitor.endVisit(this);
}
public void output(StringBuffer buf) {
boolean flag = false;
if (server != null) {
buf.append(server);
flag = true;
}
if (flag) {
buf.append('.');
}
if (database != null) {
buf.append(database);
flag = true;
}
if (flag) {
buf.append('.');
}
if (schema != null) {
buf.append(schema);
flag = true;
}
}
public String getServer() {
return server;
}
public void setServer(String server) {
this.server = server;
}
public String getDatabase() {
return database;
}
public void setDatabase(String database) {
this.database = database;
}
public String getSchema() {
return schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
}
@@ -0,0 +1,43 @@
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.ast.expr.SQLPropertyExpr;
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 {
public SQLServerExprParser(Lexer lexer){
super(lexer);
}
public SQLServerExprParser(String sql) throws ParserException{
super(new SQLServerLexer(sql));
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 expr) throws ParserException {
if (lexer.token() == Token.DOTDOT) {
lexer.nextToken();
String text = lexer.stringVal();
lexer.nextToken();
SQLServerObjectReferenceExpr owner = new SQLServerObjectReferenceExpr(expr);
expr = new SQLPropertyExpr(owner, text);
}
return super.nameRest(expr);
}
}
@@ -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);
}
}
@@ -24,6 +24,7 @@ public class SQLServerStatementParser extends SQLStatementParser {
public SQLServerStatementParser(String sql){
super(new SQLServerLexer(sql));
this.lexer.nextToken();
this.exprParser = new SQLServerExprParser(lexer);
}
public SQLSelectParser createSQLSelectParser() {
@@ -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) {
}
}
@@ -288,7 +288,12 @@ public class Lexer {
return;
} else if (ch == '.') {
scanChar();
token = Token.DOTDOT;
if (ch == '.') {
scanChar();
token = Token.DOTDOTDOT;
} else {
token = Token.DOTDOT;
}
} else {
token = Token.DOT;
}
@@ -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;
@@ -47,16 +47,16 @@ public class SQLStatementParser extends SQLParser {
public SQLStatementParser(String sql){
super(sql);
this.exprParser = createExprParser();
this.exprParser = new SQLExprParser(lexer);
}
public SQLStatementParser(Lexer lexer){
super(lexer);
this.exprParser = createExprParser();
this.exprParser = new SQLExprParser(lexer);
}
protected SQLExprParser createExprParser() {
return new SQLExprParser(lexer);
public SQLExprParser getExprParser() {
return exprParser;
}
public List<SQLStatement> parseStatementList() throws ParserException {
@@ -255,7 +255,7 @@ public class SQLStatementParser extends SQLParser {
insertStatement.setValues(values);
accept(Token.RPAREN);
} else if (acceptSubQuery && (lexer.token() == Token.SELECT || lexer.token() == Token.LPAREN)) {
SQLQueryExpr queryExpr = (SQLQueryExpr) this.createExprParser().expr();
SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr();
insertStatement.setQuery(queryExpr.getSubQuery());
}
}
@@ -213,6 +213,7 @@ public enum Token {
COMMA(","),
DOT("."),
DOTDOT(".."),
DOTDOTDOT("..,"),
EQ("="),
GT(">"),
LT("<"),
@@ -494,7 +494,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter {
x.getQuery().accept(this);
if (x.getOrderBy() != null) {
print(" ");
println();
x.getOrderBy().accept(this);
}
@@ -20,6 +20,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement;
import com.alibaba.druid.sql.ast.statement.SQLUnionQuery;
import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;
import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr;
import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor;
import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitorAdapter;
import com.alibaba.druid.wall.IllegalSQLObjectViolation;
@@ -178,4 +179,12 @@ public class SQLServerWallVisitor extends SQLServerASTVisitorAdapter implements
return true;
}
@Override
public boolean visit(SQLServerObjectReferenceExpr x) {
if (config.isPermitSchema(x.getSchema()) || config.isPermitSchema(x.getDatabase())) {
this.getViolations().add(new IllegalSQLObjectViolation(this.toSQL(x)));
}
return true;
}
}
@@ -464,8 +464,8 @@ public class WallVisitorUtils {
if (expr instanceof SQLPropertyExpr) {
SQLPropertyExpr propExpr = (SQLPropertyExpr) expr;
if (propExpr.getOwner() instanceof SQLIdentifierExpr) {
String ownerName = ((SQLIdentifierExpr) propExpr.getOwner()).getName();
if (propExpr.getOwner() instanceof SQLName) {
String ownerName = ((SQLName) propExpr.getOwner()).getSimleName();
ownerName = form(ownerName);
@@ -9,7 +9,6 @@ import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
import com.alibaba.druid.stat.TableStat;
import com.alibaba.druid.stat.TableStat.Column;
public class MySqlDescribteTest extends MysqlTest {
@@ -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);
}
}