Compare commits

...

3 Commits

Author SHA1 Message Date
ZHENGGUAN LI d6778705b5
Merge 1dd99bb95d into c0a58c10b7 2025-08-01 13:41:13 +08:00
林枸 c0a58c10b7 Fix holo array output.
Java CI / Test JDK ${{ matrix.java }}, ${{ matrix.os }} (11, ubuntu-latest) (push) Has been cancelled Details
Java CI / Test JDK ${{ matrix.java }}, ${{ matrix.os }} (17, ubuntu-latest) (push) Has been cancelled Details
Java CI / Test JDK ${{ matrix.java }}, ${{ matrix.os }} (21, ubuntu-latest) (push) Has been cancelled Details
Java CI / Test JDK ${{ matrix.java }}, ${{ matrix.os }} (8, ubuntu-latest) (push) Has been cancelled Details
2025-07-28 14:22:24 +08:00
zhenggli 1dd99bb95d Support Oracle select collect bulk into clause 2025-02-09 21:37:59 -06:00
9 changed files with 122 additions and 25 deletions

View File

@ -104,4 +104,8 @@ public class HologresOutputVisitor extends PGOutputVisitor {
endLineComment = true;
}
}
public void printArrayExprPrefix() {
print0(ucase ? "ARRAY" : "array");
}
}

View File

@ -32,6 +32,7 @@ public class OracleSelectQueryBlock extends SQLSelectQueryBlock implements Oracl
private ModelClause modelClause;
private boolean skipLocked;
private boolean isBulkCollect;
public OracleSelectQueryBlock clone() {
OracleSelectQueryBlock x = new OracleSelectQueryBlock();
@ -75,6 +76,14 @@ public class OracleSelectQueryBlock extends SQLSelectQueryBlock implements Oracl
this.skipLocked = skipLocked;
}
public boolean isBulkCollect() {
return isBulkCollect;
}
public void setBulkCollect(boolean bulkCollect) {
this.isBulkCollect = bulkCollect;
}
@Override
protected void accept0(SQLASTVisitor visitor) {
if (visitor instanceof OracleASTVisitor) {

View File

@ -937,28 +937,45 @@ public class OracleSelectParser extends SQLSelectParser {
}
protected void parseInto(OracleSelectQueryBlock x) {
if (lexer.token() == Token.INTO) {
if (lexer.identifierEquals("BULK")) {
Lexer.SavePoint mark = lexer.mark();
lexer.nextToken();
if (lexer.token() == Token.FROM) {
return;
}
SQLExpr expr = expr();
if (lexer.token() != Token.COMMA) {
x.setInto(expr);
return;
}
SQLListExpr list = new SQLListExpr();
list.addItem(expr);
while (lexer.token() == Token.COMMA) {
if (lexer.identifierEquals("COLLECT")) {
lexer.nextToken();
list.addItem(expr());
if (lexer.token() == Token.INTO) {
x.setBulkCollect(true);
parseIntoInternal(x);
} else {
// If it's not a "INTO" token, then it's not a "BULK COLLECT" clause
lexer.reset(mark);
}
}
x.setInto(list);
} else if (lexer.token() == Token.INTO) {
parseIntoInternal(x);
}
}
private void parseIntoInternal(OracleSelectQueryBlock x) {
lexer.nextToken();
if (lexer.token() == Token.FROM) {
return;
}
SQLExpr expr = expr();
if (lexer.token() != Token.COMMA) {
x.setInto(expr);
return;
}
SQLListExpr list = new SQLListExpr();
list.addItem(expr);
while (lexer.token() == Token.COMMA) {
lexer.nextToken();
list.addItem(expr());
}
x.setInto(list);
}
private void parseHints(OracleSelectQueryBlock queryBlock) {
this.exprParser.parseHints(queryBlock.getHints());
}

View File

@ -421,7 +421,11 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
return;
}
println();
print0(ucase ? "INTO " : "into ");
if (x.isBulkCollect()) {
print0(ucase ? "BULK COLLECT INTO " : "bulk collect into ");
} else {
print0(ucase ? "INTO " : "into ");
}
into.accept(this);
}

View File

@ -202,4 +202,8 @@ public class PrestoOutputVisitor extends SQLASTOutputVisitor implements PrestoAS
timeZone.accept(this);
return false;
}
public void printArrayExprPrefix() {
print0(ucase ? "ARRAY" : "array");
}
}

View File

@ -5916,10 +5916,23 @@ public class SQLExprParser extends SQLParser {
if (token == Token.IDENTIFIER
&& hash_lower != FnvHash.Constants.CURRENT) {
Pair<String, SQLExpr> pair = parseSelectItemIdentifier(expr);
String as = pair.getKey();
expr = pair.getValue();
return new SQLSelectItem(expr, as, connectByRoot);
// Do not set "bulk" as alias for bulk collect into clause
if (lexer.identifierEquals("BULK")) {
Lexer.SavePoint mark = lexer.mark();
lexer.nextToken();
if (lexer.identifierEquals("COLLECT")) {
lexer.nextToken();
if (lexer.token == Token.INTO) {
lexer.reset(mark);
return new SQLSelectItem(expr, (String) null, connectByRoot);
}
}
} else {
Pair<String, SQLExpr> pair = parseSelectItemIdentifier(expr);
String as = pair.getKey();
expr = pair.getValue();
return new SQLSelectItem(expr, as, connectByRoot);
}
}
if (token == Token.LPAREN) {

View File

@ -7650,6 +7650,8 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
return false;
}
public void printArrayExprPrefix() {
}
@Override
public boolean visit(SQLArrayExpr x) {
SQLExpr expr = x.getExpr();
@ -7661,10 +7663,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
} else if (expr != null) {
expr.accept(this);
} else {
boolean trino = dbType == DbType.trino || dbType == DbType.presto || dbType == DbType.supersql;
if (trino) {
print0(ucase ? "ARRAY" : "array");
}
printArrayExprPrefix();
}
if (x.getDataType() != null) {

View File

@ -0,0 +1,43 @@
package com.alibaba.druid.bvt.sql.oracle.pl;
import java.util.List;
import com.alibaba.druid.sql.OracleTest;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.util.JdbcConstants;
public class Oracle_pl_select_bulk_collect extends OracleTest {
public void test_0() throws Exception {
String sql = "DECLARE\n" +
"\tTYPE NumList IS TABLE OF NUMBER;\n" +
"\tTYPE NameList IS TABLE OF VARCHAR2(20);\n" +
"\temp_id NumList;\n" +
"\temp_name NameList;\n" +
"BEGIN\n" +
"\tSELECT employee_id, last_name\n" +
"\tBULK COLLECT INTO (emp_id, emp_name)\n" +
"\tFROM employees\n" +
"\tWHERE department_id = 90;\n" +
"END;";
List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE);
SQLStatement stmt = statementList.get(0);
assertEquals(1, statementList.size());
String output = SQLUtils.toOracleString(stmt);
assertEquals("DECLARE\n" +
"\tTYPE NumList IS TABLE OF NUMBER;\n" +
"\tTYPE NameList IS TABLE OF VARCHAR2(20);\n" +
"\temp_id NumList;\n" +
"\temp_name NameList;\n" +
"BEGIN\n" +
"\tSELECT employee_id, last_name\n" +
"\tBULK COLLECT INTO (emp_id, emp_name)\n" +
"\tFROM employees\n" +
"\tWHERE department_id = 90;\n" +
"END;", output);
}
}

View File

@ -1,3 +1,7 @@
select []
--------------------
SELECT ARRAY[]
------------------------------------------------------------------------------------------------------------------------
select cast(($0 + interval $1 week) as date)
--------------------
SELECT CAST(($0 + INTERVAL '$1' WEEK) AS date)