Skip to content

Commit 6ba2bb0

Browse files
mkmoisenmmoisen
andauthored
feat(oracle): Add support for BULK COLLECT INTO (#4181)
* feat(oracle): Add support for BULK COLLECT INTO * feat(oracle): Add support for BULK COLLECT INTO * feat(oracle): Add support for BULK COLLECT INTO * feat(oracle): Add support for BULK COLLECT INTO * feat(oracle): Add support for BULK COLLECT INTO --------- Co-authored-by: mmoisen <[email protected]>
1 parent 1d16ee2 commit 6ba2bb0

File tree

4 files changed

+47
-1
lines changed

4 files changed

+47
-1
lines changed

sqlglot/dialects/oracle.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ class Tokenizer(tokens.Tokenizer):
9595
"(+)": TokenType.JOIN_MARKER,
9696
"BINARY_DOUBLE": TokenType.DOUBLE,
9797
"BINARY_FLOAT": TokenType.FLOAT,
98+
"BULK COLLECT INTO": TokenType.BULK_COLLECT_INTO,
9899
"COLUMNS": TokenType.COLUMN,
99100
"MATCH_RECOGNIZE": TokenType.MATCH_RECOGNIZE,
100101
"MINUS": TokenType.EXCEPT,
@@ -241,6 +242,25 @@ def _parse_json_exists(self) -> exp.JSONExists:
241242
on_condition=self._parse_on_condition(),
242243
)
243244

245+
def _parse_into(self) -> t.Optional[exp.Into]:
246+
# https://docs.oracle.com/en/database/oracle/oracle-database/19/lnpls/SELECT-INTO-statement.html
247+
bulk_collect_into = self._match(TokenType.BULK_COLLECT_INTO)
248+
249+
if not bulk_collect_into and not self._match(TokenType.INTO):
250+
return None
251+
252+
expressions = self._parse_expressions()
253+
this = None
254+
if len(expressions) == 1:
255+
self._advance(-1)
256+
expressions = []
257+
self._match(TokenType.TABLE)
258+
this = self._parse_table(schema=True)
259+
260+
return self.expression(
261+
exp.Into, this=this, bulk_collect=bulk_collect_into, expressions=expressions
262+
)
263+
244264
class Generator(generator.Generator):
245265
LOCKING_READS_SUPPORTED = True
246266
JOIN_HINTS = False
@@ -344,3 +364,10 @@ def queryoption_sql(self, expression: exp.QueryOption) -> str:
344364
def coalesce_sql(self, expression: exp.Coalesce) -> str:
345365
func_name = "NVL" if expression.args.get("is_nvl") else "COALESCE"
346366
return rename_func(func_name)(self, expression)
367+
368+
def into_sql(self, expression: exp.Into) -> str:
369+
into = "INTO" if not expression.args.get("bulk_collect") else "BULK COLLECT INTO"
370+
if expression.this:
371+
return f"{self.seg(into)} {self.sql(expression, 'this')}"
372+
373+
return f"{self.seg(into)} {self.expressions(expression)}"

sqlglot/expressions.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2106,7 +2106,13 @@ class PrimaryKey(Expression):
21062106
# https://www.postgresql.org/docs/9.1/sql-selectinto.html
21072107
# https://docs.aws.amazon.com/redshift/latest/dg/r_SELECT_INTO.html#r_SELECT_INTO-examples
21082108
class Into(Expression):
2109-
arg_types = {"this": True, "temporary": False, "unlogged": False}
2109+
arg_types = {
2110+
"this": False,
2111+
"temporary": False,
2112+
"unlogged": False,
2113+
"bulk_collect": False,
2114+
"expressions": False,
2115+
}
21102116

21112117

21122118
class From(Expression):

sqlglot/tokens.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ class TokenType(AutoName):
221221
AUTO_INCREMENT = auto()
222222
BEGIN = auto()
223223
BETWEEN = auto()
224+
BULK_COLLECT_INTO = auto()
224225
CACHE = auto()
225226
CASE = auto()
226227
CHARACTER_SET = auto()

tests/dialects/test_oracle.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,18 @@ def test_oracle(self):
6666
self.validate_identity(
6767
"SELECT COUNT(1) INTO V_Temp FROM TABLE(CAST(somelist AS data_list)) WHERE col LIKE '%contact'"
6868
)
69+
self.validate_identity(
70+
"SELECT department_id INTO v_department_id FROM departments FETCH FIRST 1 ROWS ONLY"
71+
)
72+
self.validate_identity(
73+
"SELECT department_id, department_name INTO v_department_id, v_department_name FROM departments FETCH FIRST 1 ROWS ONLY"
74+
)
75+
self.validate_identity(
76+
"SELECT department_id BULK COLLECT INTO v_department_ids FROM departments"
77+
)
78+
self.validate_identity(
79+
"SELECT department_id, department_name BULK COLLECT INTO v_department_ids, v_department_names FROM departments"
80+
)
6981
self.validate_identity(
7082
"SELECT MIN(column_name) KEEP (DENSE_RANK FIRST ORDER BY column_name DESC) FROM table_name"
7183
)

0 commit comments

Comments
 (0)