mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
oracle sql parser support keep
This commit is contained in:
@@ -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")));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user