oracle sql parser support keep

This commit is contained in:
高铁
2016-03-11 22:08:13 +08:00
parent b66c366f93
commit 9dc9c808f6
9 changed files with 217 additions and 11 deletions
@@ -0,0 +1,42 @@
package com.alibaba.druid.sql.ast;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class SQLKeep extends SQLObjectImpl {
protected DenseRank denseRank;
protected SQLOrderBy orderBy;
@Override
protected void accept0(SQLASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, this.orderBy);
}
visitor.endVisit(this);
}
public DenseRank getDenseRank() {
return denseRank;
}
public void setDenseRank(DenseRank denseRank) {
this.denseRank = denseRank;
}
public SQLOrderBy getOrderBy() {
return orderBy;
}
public void setOrderBy(SQLOrderBy orderBy) {
if (orderBy != null) {
orderBy.setParent(this);
}
this.orderBy = orderBy;
}
public static enum DenseRank {
FIRST, //
LAST
}
}
@@ -21,6 +21,7 @@ import java.util.List;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLExprImpl;
import com.alibaba.druid.sql.ast.SQLKeep;
import com.alibaba.druid.sql.ast.SQLOrderBy;
import com.alibaba.druid.sql.ast.SQLOver;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
@@ -31,6 +32,7 @@ public class SQLAggregateExpr extends SQLExprImpl implements Serializable {
protected String methodName;
protected SQLAggregateOption option;
protected final List<SQLExpr> arguments = new ArrayList<SQLExpr>();
protected SQLKeep keep;
protected SQLOver over;
protected SQLOrderBy withinGroup;
protected boolean ignoreNulls = false;
@@ -88,9 +90,23 @@ public class SQLAggregateExpr extends SQLExprImpl implements Serializable {
}
public void setOver(SQLOver over) {
if (over != null) {
over.setParent(this);
}
this.over = over;
}
public SQLKeep getKeep() {
return keep;
}
public void setKeep(SQLKeep keep) {
if (keep != null) {
keep.setParent(this);
}
this.keep = keep;
}
public boolean isIgnoreNulls() {
return this.ignoreNulls;
}
@@ -20,6 +20,8 @@ import java.math.BigInteger;
import com.alibaba.druid.sql.ast.SQLDataType;
import com.alibaba.druid.sql.ast.SQLDataTypeImpl;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLKeep;
import com.alibaba.druid.sql.ast.SQLKeep.DenseRank;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLOrderBy;
import com.alibaba.druid.sql.ast.SQLOrderingSpecification;
@@ -753,6 +755,28 @@ public class OracleExprParser extends SQLExprParser {
aggregateExpr.setWithinGroup(withinGroup);
accept(Token.RPAREN);
}
if (lexer.token() == Token.KEEP) {
lexer.nextToken();
SQLKeep keep = new SQLKeep();
accept(Token.LPAREN);
acceptIdentifier("DENSE_RANK");
if (identifierEquals("FIRST")) {
lexer.nextToken();
keep.setDenseRank(DenseRank.FIRST);
} else {
acceptIdentifier("LAST");
keep.setDenseRank(DenseRank.LAST);
}
SQLOrderBy orderBy = this.parseOrderBy();
keep.setOrderBy(orderBy);
aggregateExpr.setKeep(keep);
accept(Token.RPAREN);
}
if (lexer.token() == Token.OVER) {
OracleAnalytic over = new OracleAnalytic();
@@ -30,6 +30,7 @@ import com.alibaba.druid.sql.ast.SQLCommentHint;
import com.alibaba.druid.sql.ast.SQLDataType;
import com.alibaba.druid.sql.ast.SQLDeclareItem;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLKeep;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.SQLOrderBy;
@@ -566,9 +567,14 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab
x.getWithinGroup().accept(this);
print(')');
}
if (x.getKeep() != null) {
print(' ');
x.getKeep().accept(this);
}
if (x.getOver() != null) {
print0(" ");
print(' ');
x.getOver().accept(this);
}
return false;
@@ -1630,6 +1636,20 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab
print(')');
return false;
}
@Override
public boolean visit(SQLKeep x) {
if (x.getDenseRank() == SQLKeep.DenseRank.FIRST) {
print0(ucase ? "KEEP (DENSE_RANK FIRST " : "keep (dense_rank first ");
} else {
print0(ucase ? "KEEP (DENSE_RANK LAST " : "keep (dense_rank last ");
}
x.getOrderBy().accept(this);
print(')');
return false;
}
@Override
public boolean visit(SQLColumnPrimaryKey x) {
@@ -18,6 +18,7 @@ package com.alibaba.druid.sql.visitor;
import com.alibaba.druid.sql.ast.SQLCommentHint;
import com.alibaba.druid.sql.ast.SQLDataType;
import com.alibaba.druid.sql.ast.SQLDeclareItem;
import com.alibaba.druid.sql.ast.SQLKeep;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.SQLOrderBy;
import com.alibaba.druid.sql.ast.SQLOver;
@@ -354,6 +355,10 @@ public interface SQLASTVisitor {
void endVisit(SQLOver x);
boolean visit(SQLOver x);
void endVisit(SQLKeep x);
boolean visit(SQLKeep x);
void endVisit(SQLColumnPrimaryKey x);
@@ -19,6 +19,7 @@ import com.alibaba.druid.sql.ast.SQLCommentHint;
import com.alibaba.druid.sql.ast.SQLDataType;
import com.alibaba.druid.sql.ast.SQLDeclareItem;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLKeep;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.SQLOrderBy;
import com.alibaba.druid.sql.ast.SQLOver;
@@ -652,6 +653,15 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor {
public boolean visit(SQLOver x) {
return true;
}
@Override
public void endVisit(SQLKeep x) {
}
@Override
public boolean visit(SQLKeep x) {
return true;
}
@Override
public void endVisit(SQLColumnPrimaryKey x) {
@@ -20,6 +20,7 @@ import java.util.List;
import org.junit.Assert;
import com.alibaba.druid.sql.OracleTest;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;
@@ -29,7 +30,7 @@ public class OracleSelectTest51 extends OracleTest {
public void test_0() throws Exception {
String sql = //
"select TRIM(TRAILING 'M' FROM RTRIM(' testM')) from dual;"; //
"select TRIM(TRAILING 'M' FROM RTRIM(' testM')) from dual;"; //
OracleStatementParser parser = new OracleStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
@@ -51,11 +52,19 @@ public class OracleSelectTest51 extends OracleTest {
Assert.assertEquals(0, visitor.getColumns().size());
String text = TestUtils.outputOracle(stmt);
{
String text = SQLUtils.toOracleString(stmt);
Assert.assertEquals("SELECT TRIM(TRAILING 'M' FROM RTRIM(' testM'))" //
+ "\nFROM dual;"//
+ "\n", text);
Assert.assertEquals("SELECT TRIM(TRAILING 'M' FROM RTRIM(' testM'))" //
+ "\nFROM dual", text);
}
{
String text = SQLUtils.toOracleString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);
Assert.assertEquals("select TRIM(TRAILING 'M' from RTRIM(' testM'))" //
+ "\nfrom dual", text);
}
// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("acduser.vw_acd_info", "xzqh")));
@@ -20,6 +20,7 @@ import java.util.List;
import org.junit.Assert;
import com.alibaba.druid.sql.OracleTest;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;
@@ -29,7 +30,7 @@ public class OracleSelectTest52 extends OracleTest {
public void test_0() throws Exception {
String sql = //
"select 1 interval from dual"; //
"select 1 interval from dual"; //
OracleStatementParser parser = new OracleStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
@@ -51,11 +52,19 @@ public class OracleSelectTest52 extends OracleTest {
Assert.assertEquals(0, visitor.getColumns().size());
String text = TestUtils.outputOracle(stmt);
{
String text = SQLUtils.toOracleString(stmt);
Assert.assertEquals("SELECT 1 AS INTERVAL" //
+ "\nFROM dual;"//
+ "\n", text);
Assert.assertEquals("SELECT 1 AS INTERVAL" //
+ "\nFROM dual", text);
}
{
String text = SQLUtils.toOracleString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);
Assert.assertEquals("select 1 as INTERVAL" //
+ "\nfrom dual", text);
}
// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("acduser.vw_acd_info", "xzqh")));
@@ -0,0 +1,71 @@
/*
* Copyright 1999-2101 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.druid.bvt.sql.oracle;
import java.util.List;
import org.junit.Assert;
import com.alibaba.druid.sql.OracleTest;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;
public class OracleSelectTest53 extends OracleTest {
public void test_0() throws Exception {
String sql = //
"SELECT MIN(t.deptno) KEEP(DENSE_RANK FIRST ORDER BY t.sal) a FROM emp t"; //
OracleStatementParser parser = new OracleStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
SQLStatement stmt = statementList.get(0);
print(statementList);
Assert.assertEquals(1, statementList.size());
OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();
stmt.accept(visitor);
System.out.println("Tables : " + visitor.getTables());
System.out.println("fields : " + visitor.getColumns());
System.out.println("coditions : " + visitor.getConditions());
System.out.println("relationships : " + visitor.getRelationships());
System.out.println("orderBy : " + visitor.getOrderByColumns());
Assert.assertEquals(1, visitor.getTables().size());
Assert.assertEquals(1, visitor.getColumns().size());
{
String text = SQLUtils.toOracleString(stmt);
Assert.assertEquals("SELECT MIN(t.deptno) KEEP (DENSE_RANK FIRST ORDER BY t.sal) AS a" //
+ "\nFROM emp t", text);
}
{
String text = SQLUtils.toOracleString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);
Assert.assertEquals("select min(t.deptno) keep (dense_rank first order by t.sal) as a" //
+ "\nfrom emp t", text);
}
// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("acduser.vw_acd_info", "xzqh")));
// Assert.assertTrue(visitor.getOrderByColumns().contains(new TableStat.Column("employees", "last_name")));
}
}