improved sql parser.

This commit is contained in:
wenshao
2017-06-28 15:34:43 +08:00
parent c64c40e81d
commit 2f6e406e33
19 changed files with 971 additions and 14 deletions
@@ -35,6 +35,8 @@ public class SQLBinaryOpExpr extends SQLExprImpl implements SQLReplaceable, Seri
private SQLBinaryOperator operator;
private String dbType;
private boolean bracket = false;
public SQLBinaryOpExpr(){
}
@@ -99,6 +101,14 @@ public class SQLBinaryOpExpr extends SQLExprImpl implements SQLReplaceable, Seri
this.operator = operator;
}
public boolean isBracket() {
return bracket;
}
public void setBracket(boolean bracket) {
this.bracket = bracket;
}
protected void accept0(SQLASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, this.left);
@@ -87,4 +87,14 @@ public class SQLQueryExpr extends SQLExprImpl implements Serializable {
}
return true;
}
public SQLQueryExpr clone() {
SQLQueryExpr x = new SQLQueryExpr();
if (subQuery != null) {
x.setSubQuery(subQuery.clone());
}
return x;
}
}
@@ -43,9 +43,6 @@ public class DB2OutputVisitor extends SQLASTOutputVisitor implements DB2ASTVisit
if (x.isForReadOnly()) {
println();
print0(ucase ? "FOR READ ONLY" : "for read only");
} else if (x.isForUpdate()) {
println();
print0(ucase ? "FOR UPDATE" : "for update");
}
if (x.getIsolation() != null) {
@@ -1695,7 +1695,7 @@ public class OracleStatementParser extends SQLStatementParser {
if (lexer.token() == Token.ALL) {
lexer.nextToken();
stmt.setOption(OracleMultiInsertStatement.Option.ALL);
} else if (lexer.token() == Token.FIRST) {
} else if (lexer.token() == Token.FIRST || identifierEquals("FIRST")) {
lexer.nextToken();
stmt.setOption(OracleMultiInsertStatement.Option.FIRST);
}
@@ -144,8 +144,11 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
}
public boolean visit(OracleDbLinkExpr x) {
x.getExpr().accept(this);
print('@');
SQLExpr expr = x.getExpr();
if (expr != null) {
expr.accept(this);
print('@');
}
print0(x.getDbLink());
return false;
}
@@ -228,6 +228,10 @@ public class SQLExprParser extends SQLParser {
sqlExpr = listExpr;
}
if (sqlExpr instanceof SQLBinaryOpExpr) {
((SQLBinaryOpExpr) sqlExpr).setBracket(true);
}
accept(Token.RPAREN);
break;
@@ -33,6 +33,7 @@ import com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement.TriggerEven
import com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement.TriggerType;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlRepeatStatement;
import com.alibaba.druid.util.JdbcConstants;
import com.alibaba.druid.util.JdbcUtils;
public class SQLStatementParser extends SQLParser {
@@ -129,6 +130,14 @@ public class SQLStatementParser extends SQLParser {
continue;
}
case WITH:
if (!JdbcConstants.POSTGRESQL.equals(dbType)){
SQLStatement stmt = parseSelect();
stmt.setParent(parent);
statementList.add(stmt);
continue;
}
break;
case SELECT: {
SQLStatement stmt = parseSelect();
stmt.setParent(parent);
@@ -476,10 +476,17 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
if (x.getRight() instanceof SQLBinaryOpExpr) {
SQLBinaryOpExpr right = (SQLBinaryOpExpr) x.getRight();
boolean rightRational = right.getOperator() == SQLBinaryOperator.BooleanAnd
|| right.getOperator() == SQLBinaryOperator.BooleanOr;
SQLBinaryOperator rightOp = right.getOperator();
SQLBinaryOperator op = x.getOperator();
boolean rightRational = rightOp == SQLBinaryOperator.BooleanAnd
|| rightOp == SQLBinaryOperator.BooleanOr;
if (right.getOperator().priority >= x.getOperator().priority) {
if (rightOp.priority >= op.priority
|| (right.isBracket()
&& rightOp != op
&& rightOp.isLogical()
&& op.isLogical()
)) {
if (rightRational) {
incrementIndent();
}
@@ -507,10 +514,16 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
private void visitBinaryLeft(SQLExpr left, SQLBinaryOperator op) {
if (left instanceof SQLBinaryOpExpr) {
SQLBinaryOpExpr binaryLeft = (SQLBinaryOpExpr) left;
boolean leftRational = binaryLeft.getOperator() == SQLBinaryOperator.BooleanAnd
|| binaryLeft.getOperator() == SQLBinaryOperator.BooleanOr;
SQLBinaryOperator leftOp = binaryLeft.getOperator();
boolean leftRational = leftOp == SQLBinaryOperator.BooleanAnd
|| leftOp == SQLBinaryOperator.BooleanOr;
if (binaryLeft.getOperator().priority > op.priority) {
if (leftOp.priority > op.priority
|| (binaryLeft.isBracket()
&& leftOp != op
&& leftOp.isLogical()
&& op.isLogical()
)) {
if (leftRational) {
incrementIndent();
}
@@ -0,0 +1,54 @@
/*
* Copyright 1999-2017 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.mysql.createTable;
import com.alibaba.druid.sql.MysqlTest;
import com.alibaba.druid.sql.SQLUtils;
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.Column;
public class MySqlCreateTableTest78_json extends MysqlTest {
public void test_one() throws Exception {
String sql = "CREATE TABLE t1 (jdoc JSON);";
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseCreateTable();
MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
stmt.accept(visitor);
Column column = visitor.getColumn("t1", "jdoc");
assertNotNull(column);
assertEquals("JSON", column.getDataType());
{
String output = SQLUtils.toMySqlString(stmt);
assertEquals("CREATE TABLE t1 (\n" +
"\tjdoc JSON\n" +
")", output);
}
{
String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);
assertEquals("create table t1 (\n" +
"\tjdoc JSON\n" +
")", output);
}
}
}
@@ -0,0 +1,105 @@
/*
* Copyright 1999-2017 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.mysql.select;
import com.alibaba.druid.sql.MysqlTest;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
import com.alibaba.druid.util.JdbcConstants;
import org.junit.Assert;
import java.util.List;
public class MySqlSelectTest_42_with_cte extends MysqlTest {
public void test_0() throws Exception {
String sql = "WITH\n" +
" cte1 AS (SELECT a, b FROM table1),\n" +
" cte2 AS (SELECT c, d FROM table2)\n" +
"SELECT b, d FROM cte1 JOIN cte2\n" +
"WHERE cte1.a = cte2.c;";
List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL, true);
SQLStatement stmt = statementList.get(0);
Assert.assertEquals(1, statementList.size());
SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);
stmt.accept(visitor);
// System.out.println("Tables : " + visitor.getTables());
// System.out.println("fields : " + visitor.getColumns());
// System.out.println("coditions : " + visitor.getConditions());
// System.out.println("orderBy : " + visitor.getOrderByColumns());
// Assert.assertEquals(1, visitor.getTables().size());
// Assert.assertEquals(1, visitor.getColumns().size());
// Assert.assertEquals(0, visitor.getConditions().size());
// Assert.assertEquals(0, visitor.getOrderByColumns().size());
{
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("WITH cte1 AS (\n" +
"\t\tSELECT a, b\n" +
"\t\tFROM table1\n" +
"\t), \n" +
"\tcte2 AS (\n" +
"\t\tSELECT c, d\n" +
"\t\tFROM table2\n" +
"\t)\n" +
"SELECT b, d\n" +
"FROM cte1\n" +
"\tJOIN cte2\n" +
"WHERE cte1.a = cte2.c;", //
output);
}
{
String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);
Assert.assertEquals("with cte1 as (\n" +
"\t\tselect a, b\n" +
"\t\tfrom table1\n" +
"\t), \n" +
"\tcte2 as (\n" +
"\t\tselect c, d\n" +
"\t\tfrom table2\n" +
"\t)\n" +
"select b, d\n" +
"from cte1\n" +
"\tjoin cte2\n" +
"where cte1.a = cte2.c;", //
output);
}
{
String output = SQLUtils.toMySqlString(stmt, new SQLUtils.FormatOption(true, true, true));
Assert.assertEquals("WITH cte1 AS (\n" +
"\t\tSELECT a, b\n" +
"\t\tFROM table1\n" +
"\t), \n" +
"\tcte2 AS (\n" +
"\t\tSELECT c, d\n" +
"\t\tFROM table2\n" +
"\t)\n" +
"SELECT b, d\n" +
"FROM cte1\n" +
"\tJOIN cte2\n" +
"WHERE cte1.a = cte2.c;", //
output);
}
}
}
@@ -0,0 +1,105 @@
/*
* Copyright 1999-2017 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.mysql.select;
import com.alibaba.druid.sql.MysqlTest;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
import com.alibaba.druid.util.JdbcConstants;
import org.junit.Assert;
import java.util.List;
public class MySqlSelectTest_43_with_cte extends MysqlTest {
public void test_0() throws Exception {
String sql = "WITH\n" +
" cte1 AS (SELECT a, b FROM table1),\n" +
" cte2 AS (SELECT c, d FROM table2)\n" +
"SELECT b, d FROM cte1 JOIN cte2\n" +
"WHERE cte1.a = cte2.c;";
List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL, true);
SQLStatement stmt = statementList.get(0);
Assert.assertEquals(1, statementList.size());
SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);
stmt.accept(visitor);
// System.out.println("Tables : " + visitor.getTables());
// System.out.println("fields : " + visitor.getColumns());
// System.out.println("coditions : " + visitor.getConditions());
// System.out.println("orderBy : " + visitor.getOrderByColumns());
// Assert.assertEquals(1, visitor.getTables().size());
// Assert.assertEquals(1, visitor.getColumns().size());
// Assert.assertEquals(0, visitor.getConditions().size());
// Assert.assertEquals(0, visitor.getOrderByColumns().size());
{
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("WITH cte1 AS (\n" +
"\t\tSELECT a, b\n" +
"\t\tFROM table1\n" +
"\t), \n" +
"\tcte2 AS (\n" +
"\t\tSELECT c, d\n" +
"\t\tFROM table2\n" +
"\t)\n" +
"SELECT b, d\n" +
"FROM cte1\n" +
"\tJOIN cte2\n" +
"WHERE cte1.a = cte2.c;", //
output);
}
{
String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);
Assert.assertEquals("with cte1 as (\n" +
"\t\tselect a, b\n" +
"\t\tfrom table1\n" +
"\t), \n" +
"\tcte2 as (\n" +
"\t\tselect c, d\n" +
"\t\tfrom table2\n" +
"\t)\n" +
"select b, d\n" +
"from cte1\n" +
"\tjoin cte2\n" +
"where cte1.a = cte2.c;", //
output);
}
{
String output = SQLUtils.toMySqlString(stmt, new SQLUtils.FormatOption(true, true, true));
Assert.assertEquals("WITH cte1 AS (\n" +
"\t\tSELECT a, b\n" +
"\t\tFROM table1\n" +
"\t), \n" +
"\tcte2 AS (\n" +
"\t\tSELECT c, d\n" +
"\t\tFROM table2\n" +
"\t)\n" +
"SELECT b, d\n" +
"FROM cte1\n" +
"\tJOIN cte2\n" +
"WHERE cte1.a = cte2.c;", //
output);
}
}
}
@@ -0,0 +1,98 @@
/*
* Copyright 1999-2017 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.mysql.select;
import com.alibaba.druid.sql.MysqlTest;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
import com.alibaba.druid.util.JdbcConstants;
import org.junit.Assert;
import java.util.List;
public class MySqlSelectTest_44_with_cte extends MysqlTest {
public void test_0() throws Exception {
String sql = "WITH RECURSIVE cte AS\n" +
"(\n" +
" SELECT 1 AS n, 1 AS p, -1 AS q\n" +
" UNION ALL\n" +
" SELECT n + 1, q * 2, p * 2 FROM cte WHERE n < 5\n" +
")\n" +
"SELECT * FROM cte;";
List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL, true);
SQLStatement stmt = statementList.get(0);
Assert.assertEquals(1, statementList.size());
SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);
stmt.accept(visitor);
// System.out.println("Tables : " + visitor.getTables());
// System.out.println("fields : " + visitor.getColumns());
// System.out.println("coditions : " + visitor.getConditions());
// System.out.println("orderBy : " + visitor.getOrderByColumns());
// Assert.assertEquals(1, visitor.getTables().size());
// Assert.assertEquals(1, visitor.getColumns().size());
// Assert.assertEquals(0, visitor.getConditions().size());
// Assert.assertEquals(0, visitor.getOrderByColumns().size());
{
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("WITH RECURSIVE cte AS (\n" +
"\t\tSELECT 1 AS n, 1 AS p, -1 AS q\n" +
"\t\tUNION ALL\n" +
"\t\tSELECT n + 1, q * 2, p * 2\n" +
"\t\tFROM cte\n" +
"\t\tWHERE n < 5\n" +
"\t)\n" +
"SELECT *\n" +
"FROM cte;", //
output);
}
{
String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);
Assert.assertEquals("with recursive cte as (\n" +
"\t\tselect 1 as n, 1 as p, -1 as q\n" +
"\t\tunion all\n" +
"\t\tselect n + 1, q * 2, p * 2\n" +
"\t\tfrom cte\n" +
"\t\twhere n < 5\n" +
"\t)\n" +
"select *\n" +
"from cte;", //
output);
}
{
String output = SQLUtils.toMySqlString(stmt, new SQLUtils.FormatOption(true, true, true));
Assert.assertEquals("WITH RECURSIVE cte AS (\n" +
"\t\tSELECT ? AS n, ? AS p, ? AS q\n" +
"\t\tUNION ALL\n" +
"\t\tSELECT n + ?, q * ?, p * ?\n" +
"\t\tFROM cte\n" +
"\t\tWHERE n < ?\n" +
"\t)\n" +
"SELECT *\n" +
"FROM cte;", //
output);
}
}
}
@@ -0,0 +1,80 @@
/*
* Copyright 1999-2017 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.mysql.select;
import com.alibaba.druid.sql.MysqlTest;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
import com.alibaba.druid.util.JdbcConstants;
import org.junit.Assert;
import java.util.List;
public class MySqlSelectTest_45_subquery_scalar_operand extends MysqlTest {
public void test_0() throws Exception {
String sql = "SELECT (SELECT s1 FROM t2) FROM t1;";
List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL, true);
SQLStatement stmt = statementList.get(0);
Assert.assertEquals(1, statementList.size());
SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);
stmt.accept(visitor);
// System.out.println("Tables : " + visitor.getTables());
// System.out.println("fields : " + visitor.getColumns());
// System.out.println("coditions : " + visitor.getConditions());
// System.out.println("orderBy : " + visitor.getOrderByColumns());
// Assert.assertEquals(1, visitor.getTables().size());
// Assert.assertEquals(1, visitor.getColumns().size());
// Assert.assertEquals(0, visitor.getConditions().size());
// Assert.assertEquals(0, visitor.getOrderByColumns().size());
{
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("SELECT (\n" +
"\t\tSELECT s1\n" +
"\t\tFROM t2\n" +
"\t)\n" +
"FROM t1;", //
output);
}
{
String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);
Assert.assertEquals("select (\n" +
"\t\tselect s1\n" +
"\t\tfrom t2\n" +
"\t)\n" +
"from t1;", //
output);
}
{
String output = SQLUtils.toMySqlString(stmt, new SQLUtils.FormatOption(true, true, true));
Assert.assertEquals("SELECT (\n" +
"\t\tSELECT s1\n" +
"\t\tFROM t2\n" +
"\t)\n" +
"FROM t1;", //
output);
}
}
}
@@ -0,0 +1,147 @@
/*
* Copyright 1999-2017 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.odps;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
import com.alibaba.druid.util.JdbcConstants;
import junit.framework.TestCase;
import org.junit.Assert;
import java.util.List;
public class OdpsSelectTest22 extends TestCase {
public void test_select() throws Exception {
// 1095288847322
String sql = "select bucket_id,sum(pv) as pv, sum(clk) as clk,sum(clk)/(sum(pv)+1e-10) as ctr,sum(ut_ad_clk) as ut_ad_clk,sum(ad_clk) as ad_clk,sum(cost) as cost\n" +
", sum(cost)*1000/(sum(pv)+1e-10)/100 as rpm\n" +
"from (\n" +
"select bucket_id,UT.pv as pv, UT.clk as clk, UT.ad_clk as ut_ad_clk, CLK.clk as ad_clk,CLK.cost as cost\n" +
"from (\n" +
"\tselect item_id,pv_id,sum(pv) as pv,sum(clk) as clk, sum(if(str_to_map(args,',','=')['sid'] is not null,clk,0)) as ad_clk\n" +
"\t,str_to_map(args,',','=')['sid'] as ad_session,split_part(str_to_map(args,',','=')['scm'],'.',2) as bucket_id\n" +
"\tfrom alimama_algo.fund_mlr_n_chicago_user_track_distinct_shark\n" +
"\twhere ds=20170627 and hh=00 and mm=00 \n" +
"\tgroup by item_id,str_to_map(args,',','=')['sid'],pv_id, split_part(str_to_map(args,',','=')['scm'],'.',2)\n" +
") UT\n" +
"left outer join \n" +
"(\n" +
"SELECT pv_id AS ad_session\n" +
"\t, item_it AS item_id\n" +
"\t, SUM(click_price) AS cost\n" +
"\t, COUNT(*) AS clk\n" +
"FROM alimama_algo.fund_mlr_n_chicago_offline_click\n" +
"WHERE ds = 20170627\n" +
"\tAND hh = 0\n" +
"\tAND mm = 0\n" +
"GROUP BY pv_id, \n" +
"\titem_it\n" +
") CLK on UT.ad_session = CLK.ad_session and UT.item_id = CLK.item_id\n" +
"where UT.ad_clk > 0 or CLK.clk > 0\n" +
") A\n" +
"group by bucket_id;";//
assertEquals("SELECT bucket_id, SUM(pv) AS pv, SUM(clk) AS clk, SUM(clk) / (SUM(pv) + 1E-10) AS ctr, SUM(ut_ad_clk) AS ut_ad_clk\n" +
"\t, SUM(ad_clk) AS ad_clk, SUM(cost) AS cost, SUM(cost) * 1000 / (SUM(pv) + 1E-10) / 100 AS rpm\n" +
"FROM (\n" +
"\tSELECT bucket_id, UT.pv AS pv, UT.clk AS clk, UT.ad_clk AS ut_ad_clk, CLK.clk AS ad_clk\n" +
"\t\t, CLK.cost AS cost\n" +
"\tFROM (\n" +
"\t\tSELECT item_id, pv_id, SUM(pv) AS pv, SUM(clk) AS clk, SUM(IF(str_to_map(args, ',', '=')['sid'] IS NOT NULL, clk, 0)) AS ad_clk\n" +
"\t\t\t, str_to_map(args, ',', '=')['sid'] AS ad_session, split_part(str_to_map(args, ',', '=')['scm'], '.', 2) AS bucket_id\n" +
"\t\tFROM alimama_algo.fund_mlr_n_chicago_user_track_distinct_shark\n" +
"\t\tWHERE ds = 20170627\n" +
"\t\t\tAND hh = 0\n" +
"\t\t\tAND mm = 0\n" +
"\t\tGROUP BY item_id, \n" +
"\t\t\tstr_to_map(args, ',', '=')['sid'], \n" +
"\t\t\tpv_id, \n" +
"\t\t\tsplit_part(str_to_map(args, ',', '=')['scm'], '.', 2)\n" +
"\t) UT\n" +
"\tLEFT OUTER JOIN (\n" +
"\t\tSELECT pv_id AS ad_session, item_it AS item_id, SUM(click_price) AS cost, COUNT(*) AS clk\n" +
"\t\tFROM alimama_algo.fund_mlr_n_chicago_offline_click\n" +
"\t\tWHERE ds = 20170627\n" +
"\t\t\tAND hh = 0\n" +
"\t\t\tAND mm = 0\n" +
"\t\tGROUP BY pv_id, \n" +
"\t\t\titem_it\n" +
"\t) CLK\n" +
"\tON UT.ad_session = CLK.ad_session\n" +
"\t\tAND UT.item_id = CLK.item_id\n" +
"\tWHERE UT.ad_clk > 0\n" +
"\t\tOR CLK.clk > 0\n" +
") A\n" +
"GROUP BY bucket_id;", SQLUtils.formatOdps(sql));
assertEquals("select bucket_id, sum(pv) as pv, sum(clk) as clk, sum(clk) / (sum(pv) + 1E-10) as ctr, sum(ut_ad_clk) as ut_ad_clk\n" +
"\t, sum(ad_clk) as ad_clk, sum(cost) as cost, sum(cost) * 1000 / (sum(pv) + 1E-10) / 100 as rpm\n" +
"from (\n" +
"\tselect bucket_id, UT.pv as pv, UT.clk as clk, UT.ad_clk as ut_ad_clk, CLK.clk as ad_clk\n" +
"\t\t, CLK.cost as cost\n" +
"\tfrom (\n" +
"\t\tselect item_id, pv_id, sum(pv) as pv, sum(clk) as clk, sum(if(str_to_map(args, ',', '=')['sid'] is not null, clk, 0)) as ad_clk\n" +
"\t\t\t, str_to_map(args, ',', '=')['sid'] as ad_session, split_part(str_to_map(args, ',', '=')['scm'], '.', 2) as bucket_id\n" +
"\t\tfrom alimama_algo.fund_mlr_n_chicago_user_track_distinct_shark\n" +
"\t\twhere ds = 20170627\n" +
"\t\t\tand hh = 0\n" +
"\t\t\tand mm = 0\n" +
"\t\tgroup by item_id, \n" +
"\t\t\tstr_to_map(args, ',', '=')['sid'], \n" +
"\t\t\tpv_id, \n" +
"\t\t\tsplit_part(str_to_map(args, ',', '=')['scm'], '.', 2)\n" +
"\t) UT\n" +
"\tleft outer join (\n" +
"\t\tselect pv_id as ad_session, item_it as item_id, sum(click_price) as cost, count(*) as clk\n" +
"\t\tfrom alimama_algo.fund_mlr_n_chicago_offline_click\n" +
"\t\twhere ds = 20170627\n" +
"\t\t\tand hh = 0\n" +
"\t\t\tand mm = 0\n" +
"\t\tgroup by pv_id, \n" +
"\t\t\titem_it\n" +
"\t) CLK\n" +
"\ton UT.ad_session = CLK.ad_session\n" +
"\t\tand UT.item_id = CLK.item_id\n" +
"\twhere UT.ad_clk > 0\n" +
"\t\tor CLK.clk > 0\n" +
") A\n" +
"group by bucket_id;", SQLUtils.formatOdps(sql, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));
List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.ODPS);
SQLStatement stmt = statementList.get(0);
assertEquals(1, statementList.size());
SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.ODPS);
stmt.accept(visitor);
// System.out.println("Tables : " + visitor.getTables());
System.out.println("fields : " + visitor.getColumns());
// System.out.println("coditions : " + visitor.getConditions());
// System.out.println("orderBy : " + visitor.getOrderByColumns());
assertEquals(2, visitor.getTables().size());
assertEquals(17, visitor.getColumns().size());
assertEquals(6, visitor.getConditions().size());
System.out.println(SQLUtils.formatOdps(sql));
// assertTrue(visitor.getColumns().contains(new Column("abc", "name")));
}
}
@@ -0,0 +1,68 @@
/*
* Copyright 1999-2017 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.odps;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
import com.alibaba.druid.util.JdbcConstants;
import junit.framework.TestCase;
import java.util.List;
public class OdpsSelectTest23 extends TestCase {
public void test_select() throws Exception {
// 1095288847322
String sql = "select * FROM dual where 1 = 1 and (2 = 2 or ( 3 = 3 and 4 = 4));";//
assertEquals("SELECT *\n" +
"FROM dual\n" +
"WHERE 1 = 1\n" +
"\tAND (2 = 2\n" +
"\t\tOR (3 = 3\n" +
"\t\t\tAND 4 = 4));", SQLUtils.formatOdps(sql));
assertEquals("select *\n" +
"from dual\n" +
"where 1 = 1\n" +
"\tand (2 = 2\n" +
"\t\tor (3 = 3\n" +
"\t\t\tand 4 = 4));", SQLUtils.formatOdps(sql, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));
List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.ODPS);
SQLStatement stmt = statementList.get(0);
assertEquals(1, statementList.size());
SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.ODPS);
stmt.accept(visitor);
// System.out.println("Tables : " + visitor.getTables());
System.out.println("fields : " + visitor.getColumns());
// System.out.println("coditions : " + visitor.getConditions());
// System.out.println("orderBy : " + visitor.getOrderByColumns());
assertEquals(1, visitor.getTables().size());
assertEquals(1, visitor.getColumns().size());
assertEquals(0, visitor.getConditions().size());
System.out.println(SQLUtils.formatOdps(sql));
// assertTrue(visitor.getColumns().contains(new Column("abc", "name")));
}
}
@@ -0,0 +1,82 @@
/*
* Copyright 1999-2017 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.block;
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.visitor.OracleSchemaStatVisitor;
import com.alibaba.druid.stat.TableStat;
import com.alibaba.druid.util.JdbcConstants;
import java.util.List;
public class OracleBlockTest21 extends OracleTest {
public void test_0() throws Exception {
String sql = "BEGIN\n" +
" FOR someone IN (\n" +
" SELECT * FROM employees\n" +
" WHERE employee_id < 120\n" +
" ORDER BY employee_id\n" +
" )\n" +
" LOOP\n" +
" DBMS_OUTPUT.PUT_LINE('First name = ' || someone.first_name ||\n" +
" ', Last name = ' || someone.last_name);\n" +
" END LOOP;\n" +
"END;"; //
List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE);
assertEquals(1, stmtList.size());
String result = SQLUtils.toOracleString(stmtList.get(0));
System.out.println(result);
assertEquals("BEGIN\n" +
"\tFOR someone IN (\n" +
"\t\tSELECT *\n" +
"\t\tFROM employees\n" +
"\t\tWHERE employee_id < 120\n" +
"\t\tORDER BY employee_id\n" +
"\t)\n" +
"\tLOOP\n" +
"\t\tDBMS_OUTPUT.PUT_LINE('First name = ' || someone.first_name || ', Last name = ' || someone.last_name);\n" +
"\tEND LOOP;\n" +
"END;", result);
assertEquals(1, stmtList.size());
OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();
for (SQLStatement statement : stmtList) {
statement.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());
assertEquals(1, visitor.getTables().size());
assertTrue(visitor.getTables().containsKey(new TableStat.Name("employees")));
assertEquals(2, visitor.getColumns().size());
assertEquals(1, visitor.getConditions().size());
assertEquals(0, visitor.getRelationships().size());
assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "employee_id")));
}
}
@@ -0,0 +1,81 @@
/*
* Copyright 1999-2017 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.block;
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.visitor.OracleSchemaStatVisitor;
import com.alibaba.druid.stat.TableStat;
import com.alibaba.druid.util.JdbcConstants;
import java.util.List;
public class OracleBlockTest22_comment extends OracleTest {
public void test_0() throws Exception {
String sql = "DECLARE\n" +
" howmany NUMBER;\n" +
" num_tables NUMBER;\n" +
"BEGIN\n" +
" -- Begin processing\n" +
" SELECT COUNT(*) INTO howmany\n" +
" FROM USER_OBJECTS\n" +
" WHERE OBJECT_TYPE = 'TABLE'; -- Check number of tables\n" +
" num_tables := howmany; -- Compute another value\n" +
"END;"; //
List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE);
assertEquals(1, stmtList.size());
String result = SQLUtils.toOracleString(stmtList.get(0));
System.out.println(result);
assertEquals("DECLARE\n" +
"\thowmany NUMBER;\n" +
"\tnum_tables NUMBER;\n" +
"BEGIN\n" +
"\t-- Begin processing\n" +
"\tSELECT COUNT(*)\n" +
"\tINTO howmany\n" +
"\tFROM USER_OBJECTS\n" +
"\tWHERE OBJECT_TYPE = 'TABLE';\n" +
"\tnum_tables := howmany;\n" +
"END;", result);
assertEquals(1, stmtList.size());
OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor();
for (SQLStatement statement : stmtList) {
statement.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());
assertEquals(1, visitor.getTables().size());
assertTrue(visitor.getTables().containsKey(new TableStat.Name("USER_OBJECTS")));
assertEquals(1, visitor.getColumns().size());
assertEquals(1, visitor.getConditions().size());
assertEquals(0, visitor.getRelationships().size());
assertTrue(visitor.getColumns().contains(new TableStat.Column("USER_OBJECTS", "OBJECT_TYPE")));
}
}
@@ -160,8 +160,8 @@ public class OracleCreateViewTest1 extends OracleTest {
"\t, c.aboutus_image_path, c.aboutus_image_title, c.chinese_name, c.rowid AS c_rid, v.rowid AS v_rid\n" +
"FROM tb_001 v, tb_002 c\n" +
"WHERE (v.service_type IN ('gs', 'cgs', 'hkgs', 'twgs')\n" +
"\t\tOR v.service_type = 'cnfm'\n" +
"\t\tAND v.stage = 'new_order')\n" +
"\t\tOR (v.service_type = 'cnfm'\n" +
"\t\t\tAND v.stage = 'new_order'))\n" +
"\tAND v.id = c.id",//
SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE));
@@ -0,0 +1,91 @@
/*
* Copyright 1999-2017 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.insert;
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;
import com.alibaba.druid.stat.TableStat;
import com.alibaba.druid.util.JdbcConstants;
import org.junit.Assert;
import java.util.List;
public class OracleInsertTest20_first extends OracleTest {
public void test_0() throws Exception {
String sql = "INSERT FIRST\n" +
" WHEN ottl < 100000 THEN\n" +
" INTO small_orders\n" +
" VALUES(oid, ottl, sid, cid)\n" +
" WHEN ottl > 100000 and ottl < 200000 THEN\n" +
" INTO medium_orders\n" +
" VALUES(oid, ottl, sid, cid)\n" +
" WHEN ottl > 290000 THEN\n" +
" INTO special_orders\n" +
" WHEN ottl > 200000 THEN\n" +
" INTO large_orders\n" +
" VALUES(oid, ottl, sid, cid)\n" +
" SELECT o.order_id oid, o.customer_id cid, o.order_total ottl,\n" +
" o.sales_rep_id sid, c.credit_limit cl, c.cust_email cem\n" +
" FROM orders o, customers c\n" +
" WHERE o.customer_id = c.customer_id;";
OracleStatementParser parser = new OracleStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
SQLStatement stmt = statementList.get(0);
print(statementList);
assertEquals(1, statementList.size());
assertEquals("INSERT FIRST \n" +
"\tWHEN ottl < 100000 THEN\n" +
"\t\tINTO small_orders\n" +
"\t\tVALUES (oid, ottl, sid, cid)\n" +
"\tWHEN ottl > 100000\n" +
"\tAND ottl < 200000 THEN\n" +
"\t\tINTO medium_orders\n" +
"\t\tVALUES (oid, ottl, sid, cid)\n" +
"\tWHEN ottl > 290000 THEN\n" +
"\t\tINTO special_orders\n" +
"\tWHEN ottl > 200000 THEN\n" +
"\t\tINTO large_orders\n" +
"\t\tVALUES (oid, ottl, sid, cid)\n" +
"SELECT o.order_id AS oid, o.customer_id AS cid, o.order_total AS ottl, o.sales_rep_id AS sid, c.credit_limit AS cl\n" +
"\t, c.cust_email AS cem\n" +
"FROM orders o, customers c\n" +
"WHERE o.customer_id = c.customer_id;",//
SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE));
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());
assertEquals(6, visitor.getTables().size());
assertEquals(8, visitor.getColumns().size());
assertTrue(visitor.getTables().containsKey(new TableStat.Name("orders")));
assertTrue(visitor.getColumns().contains(new TableStat.Column("orders", "customer_id")));
}
}