Skip to content

CASE...END inside function arguments produces parse errors #431

@cpsievert

Description

@cpsievert

The grammar structurally parses function_call (and cast_expression, window_function) inside the SQL portion. This works for most function arguments but breaks when the argument contains CASE...END, because END has no structural meaning to the parser — it gets consumed as a bare identifier, leaving the function call's ) unmatched.

import ggsql

v = ggsql.validate("""
SELECT COUNT(CASE WHEN status = 'Charged Off' THEN 1 END) AS n
FROM loans
VISUALISE n AS y DRAW bar
""")
print(v.valid())
# False
print(v.errors())
# [{'message': 'Parse error: Parse tree contains errors', 'location': None}]

These parse fine (CASE not inside function parens, or no CASE at all):

import ggsql

# CASE in select list (not inside function) — works
print(ggsql.validate("""
SELECT CASE WHEN grade = 'A' THEN 1 ELSE 0 END AS flag
FROM loans
VISUALISE flag AS y DRAW bar
""").valid())
# True

# Aggregate without CASE — works
print(ggsql.validate("""
SELECT COUNT(DISTINCT grade) AS n FROM loans
VISUALISE n AS y DRAW bar
""").valid())
# True

This isn't a request to parse more SQL — it's that the existing function_call rule rejects CASE...END as a valid position_arg. The same architectural pattern used for cast_expression (bracket the construct so its interior tokens don't leak) would fix it.

Conditional aggregation (COUNT(CASE WHEN...), SUM(CASE WHEN...)) is standard SQL-92 and the primary pattern for computing rates and proportions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions