Skip to content

sql

pinky_core.sql

Pure SQL parsing helpers — powered by sqlglot (Snowflake dialect).

The previous hand-rolled parser is preserved in sql_custom.py for reference and as a fallback if sqlglot is not available in a constrained UDF environment.

is_select(statement)

Return True if the statement is a read-only SELECT query.

Uses sqlglot (Snowflake dialect) to parse the statement and inspect its AST node type. SELECT, WITH … SELECT, and SHOW are considered read-only. All DML / DDL / session commands (CREATE, INSERT, UPDATE, DELETE, MERGE, DROP, ALTER, SET, USE, CALL, TRUNCATE) return False.

Parameters:

Name Type Description Default
statement str

A single SQL statement without trailing ;.

required

Returns:

Type Description
bool

True for SELECT / WITH / SHOW queries, False for DML / DDL.

Source code in src/pinky_core/sql.py
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
def is_select(statement: str) -> bool:
    """Return ``True`` if the statement is a read-only SELECT query.

    Uses sqlglot (Snowflake dialect) to parse the statement and inspect its
    AST node type.  ``SELECT``, ``WITH … SELECT``, and ``SHOW`` are considered
    read-only.  All DML / DDL / session commands (CREATE, INSERT, UPDATE,
    DELETE, MERGE, DROP, ALTER, SET, USE, CALL, TRUNCATE) return ``False``.

    Args:
        statement: A single SQL statement without trailing ``;``.

    Returns:
        ``True`` for SELECT / WITH / SHOW queries, ``False`` for DML / DDL.
    """
    try:
        tree = sqlglot.parse_one(
            statement.strip(),
            dialect="snowflake",
            error_level=ErrorLevel.WARN,
        )
        return not isinstance(tree, _NON_SELECT_TYPES)
    except Exception:
        return False

split_sql_statements(sql)

Split a SQL file into individual statements.

Uses sqlglot (Snowflake dialect) to tokenize and parse the input, correctly handling:

  • Inline (--) and block (/* */) comments — stripped from output
  • Semicolons inside string literals — ignored as separators
  • $$-delimited procedure bodies
  • Multi-statement files

Parameters:

Name Type Description Default
sql str

Raw SQL file content.

required

Returns:

Type Description
list[str]

List of non-empty statements without trailing ;, comments removed.

Source code in src/pinky_core/sql.py
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
def split_sql_statements(sql: str) -> list[str]:
    """Split a SQL file into individual statements.

    Uses sqlglot (Snowflake dialect) to tokenize and parse the input,
    correctly handling:

    - Inline (``--``) and block (``/* */``) comments — stripped from output
    - Semicolons inside string literals — ignored as separators
    - ``$$``-delimited procedure bodies
    - Multi-statement files

    Args:
        sql: Raw SQL file content.

    Returns:
        List of non-empty statements without trailing ``;``, comments removed.
    """
    trees = sqlglot.parse(sql, dialect="snowflake", error_level=ErrorLevel.WARN)
    return [
        stmt
        for tree in trees
        if tree is not None
        for stmt in [tree.sql(dialect="snowflake", comments=False).strip()]
        if stmt
    ]