Skip to content

parse/split methods break BEGIN...END blocks containing FOR/IF/WHILE or inline CASE outside CREATE PROCEDURE #845

@bojito

Description

@bojito

Describe the bug
sqlparse.parse() and sqlparse.split() split a compound BEGIN ... END; block into multiple statements when the block contains an END FOR; / END IF; / END WHILE; construct, or an inline CASE ... END expression inside a SELECT, and the block is not wrapped in CREATE PROCEDURE/FUNCTION.

The docs state that "semicolons within certain SQL constructs like BEGIN ... END blocks are handled correctly", but this only holds when the splitter has previously seen a CREATE keyword. Anonymous compound blocks — valid in ANSI SQL/PSM, Oracle PL/SQL, Databricks SQL scripting, and other dialects — get incorrectly split.

To Reproduce
Case 1 - END FOR; is treated as terminating the outer block:

import sqlparse

sql = """
BEGIN
    SELECT 1;
    FOR R DO
        SELECT 1;
    END FOR;
END;
"""

for i, stmt in enumerate(sqlparse.parse(sql)):
    print(f"--- statement {i} ---")
    print(str(stmt))

Actual output (2 statements):

--- statement 0 ---
BEGIN
    SELECT 1;
    FOR R DO
        SELECT 1;
    END FOR;
--- statement 1 ---
END;

Case 2 - inline CASE ... END inside a SELECT causes a split:

import sqlparse

sql = """
BEGIN
    SELECT 1;
    IF 1 THEN
        SELECT CASE WHEN 1 THEN 2 ELSE 3 END AS COUNT;
    ELSE
        SELECT 2;
    END IF;
END;
"""

for i, stmt in enumerate(sqlparse.parse(sql)):
    print(f"--- statement {i} ---")
    print(str(stmt))

Actual output (4 statements instead of 1):

--- statement 0 --- BEGIN ... SELECT CASE WHEN 1 THEN 2 ELSE 3 END AS COUNT;
--- statement 1 --- ELSE SELECT 2;
--- statement 2 --- END IF;
--- statement 3 --- END;

For comparison, wrapping the same input in CREATE PROCEDURE p() BEGIN ... END; yields a single statement.

Expected behavior
Each compound block should be returned as a single statement, matching the behavior already in place for CREATE PROCEDURE ... BEGIN ... END;.

Versions

  • Python: 3.12.3
  • sqlparse: 0.5.5

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions