Skip to content

Commit 62ee58f

Browse files
committed
fix: recognize BEGIN READ WRITE/ONLY as transaction statements
The statement splitter checks if a keyword after BEGIN is a transaction keyword to distinguish transaction statements from PL/SQL blocks. READ, ONLY and WRITE were missing from this list, causing Redshift's BEGIN READ WRITE to be treated as a block start — split() would return the entire content as one statement. Add READ, ONLY, WRITE to the transaction keyword list so BEGIN READ WRITE and BEGIN READ ONLY are correctly split as standalone transaction statements. Fixes: #843 Signed-off-by: Vincent Gao <gaobing1230@gmail.com>
1 parent f80af6a commit 62ee58f

2 files changed

Lines changed: 26 additions & 1 deletion

File tree

sqlparse/engine/statement_splitter.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@ def _change_splitlevel(self, ttype, value):
132132
(ttype is T.Keyword or ttype is T.Name) and \
133133
unified in ('TRANSACTION', 'WORK', 'TRAN',
134134
'DISTRIBUTED', 'DEFERRED',
135-
'IMMEDIATE', 'EXCLUSIVE'):
135+
'IMMEDIATE', 'EXCLUSIVE',
136+
'READ'):
136137
self._seen_begin = False
137138
if self._block_stack and self._block_stack[-1] == 'BEGIN':
138139
self._block_stack.pop()

tests/test_split.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,30 @@ def test_split_begin_transaction_formatted(): # issue826
286286
assert stmts[3] == 'END\nTRANSACTION;'
287287

288288

289+
@pytest.mark.parametrize('mode', ['READ WRITE', 'READ ONLY'])
290+
def test_split_begin_read_transaction(mode): # issue843
291+
sql = f"""BEGIN {mode};
292+
SELECT 1;
293+
COMMIT;"""
294+
stmts = sqlparse.split(sql)
295+
assert len(stmts) == 3
296+
assert stmts[0] == f'BEGIN {mode};'
297+
assert stmts[1] == 'SELECT 1;'
298+
assert stmts[2] == 'COMMIT;'
299+
300+
301+
@pytest.mark.parametrize('keyword', ['WRITE', 'ONLY'])
302+
def test_split_begin_invalid_transaction_keyword_as_block(keyword):
303+
sql = f"""BEGIN {keyword};
304+
SELECT 1;
305+
END;
306+
SELECT 2;"""
307+
stmts = sqlparse.split(sql)
308+
assert len(stmts) == 2
309+
assert stmts[0].startswith(f'BEGIN {keyword};')
310+
assert stmts[1] == 'SELECT 2;'
311+
312+
289313
def test_split_anonymous_begin_end_for(): # issue845 Case 1
290314
sql = """
291315
BEGIN

0 commit comments

Comments
 (0)