diff --git a/coverage/syntax/receipt-disagreements.toml b/coverage/syntax/receipt-disagreements.toml index 3bef4c070..284a30efd 100644 --- a/coverage/syntax/receipt-disagreements.toml +++ b/coverage/syntax/receipt-disagreements.toml @@ -136,7 +136,6 @@ other_receipts_contradicted = [ "sf.ddl.create-iceberg-table.table.kdeb38bc667b1", "sf.expressions.snowflake-db-classes.k9eccc2186fa2", "sf.functions.abs.k6169455e23b9", - "sf.functions.abs.k93f76764032f", "sf.functions.acos.k9277749f1514", "sf.functions.acosh.k2bfcf40e4874", "sf.functions.ai-summarize-agg.k96152ee79950", @@ -173,7 +172,6 @@ other_receipts_contradicted = [ "sf.functions.ceil.kadb89c6ce35e", "sf.functions.check-xml.check-xml.kebab6f35e2a9", "sf.functions.chr.ke91db843fd30", - "sf.functions.coalesce.k25882bf706ba", "sf.functions.collate.collate.syntax.kd9832a5c1f19", "sf.functions.cos.k5ffbc006170e", "sf.functions.cosh.k26b88d9dac0b", diff --git a/crates/sqlquack-syntax-snowflake/src/parser/tests/test_duckdb_syntax.rs b/crates/sqlquack-syntax-snowflake/src/parser/tests/test_duckdb_syntax.rs index 398c6e197..54e26898a 100644 --- a/crates/sqlquack-syntax-snowflake/src/parser/tests/test_duckdb_syntax.rs +++ b/crates/sqlquack-syntax-snowflake/src/parser/tests/test_duckdb_syntax.rs @@ -57,12 +57,19 @@ fn given_parser_depth_limits_when_parsing_then_deep_input_is_refused_by_its_guar expected_outcome_part: "Parse error", }, GuardedParseTestCase { - description: "the function nesting guard is independent", - sql: nested_calls(100, "abs"), + description: "the function nesting guard is independent: 257 nested calls are refused", + sql: nested_calls(257, "abs"), max_parser_depth: None, outcome: configured_outcome, expected_outcome_part: "E_GUARD_FUNCTION_NESTING_DEPTH_EXCEEDED", }, + GuardedParseTestCase { + description: "256 nested calls, deeper than the 100 Snowflake parses, are read", + sql: nested_calls(256, "abs"), + max_parser_depth: None, + outcome: configured_outcome, + expected_outcome_part: "parsed", + }, GuardedParseTestCase { description: "16 lambda wrappers consume parser depth", sql: wrapped_lambda(16), diff --git a/crates/sqlquack-syntax/src/guard/constants.rs b/crates/sqlquack-syntax/src/guard/constants.rs index a29a631db..8baf588d5 100644 --- a/crates/sqlquack-syntax/src/guard/constants.rs +++ b/crates/sqlquack-syntax/src/guard/constants.rs @@ -10,7 +10,7 @@ pub(crate) const DEFAULT_MAX_AST_DEPTH: usize = 512; pub(crate) const DEFAULT_MAX_PARENTHESES_DEPTH: usize = 512; -pub(crate) const DEFAULT_MAX_FUNCTION_CALL_DEPTH: usize = 64; +pub(crate) const DEFAULT_MAX_FUNCTION_CALL_DEPTH: usize = 256; /// Deepest type nesting, every `[]`, `ARRAY<`, `ARRAY(`, `OBJECT(` or `MAP(` level counted as one. pub const MAX_DATA_TYPE_DEPTH: usize = 512; diff --git a/tools/sqlquack-coverage-check/src/depth/_helpers/analysed.rs b/tools/sqlquack-coverage-check/src/depth/_helpers/analysed.rs index d03293da5..ae5d7cb2d 100644 --- a/tools/sqlquack-coverage-check/src/depth/_helpers/analysed.rs +++ b/tools/sqlquack-coverage-check/src/depth/_helpers/analysed.rs @@ -198,6 +198,12 @@ fn nested_arithmetic(depth: usize) -> String { format!("SELECT {value} AS x FROM orders") } +fn nested_calls(depth: usize) -> String { + let value: String = + (0..depth).fold("id".to_owned(), |value, _| format!("COALESCE({value}, 0)")); + format!("SELECT {value} AS x FROM orders") +} + fn scalar_subqueries(depth: usize) -> String { let value: String = (0..depth).fold("id".to_owned(), |value, _| { format!("(SELECT {value} FROM orders AS o LIMIT 1)") @@ -243,6 +249,10 @@ pub(crate) fn analysed_constructs() -> Vec { name: "analysed_arithmetic", text: |parser, depth| analysed(parser, depth, nested_arithmetic), }, + Construct { + name: "analysed_function_calls", + text: |parser, depth| analysed(parser, depth, nested_calls), + }, Construct { name: "analysed_scalar_subqueries", text: |parser, depth| analysed(parser, depth, scalar_subqueries),