diff --git a/crates/squawk_syntax/src/snapshots/squawk_syntax__test__create_aggregate_params_validation.snap b/crates/squawk_syntax/src/snapshots/squawk_syntax__test__create_aggregate_params_validation.snap index 9e066cc7..978c6445 100644 --- a/crates/squawk_syntax/src/snapshots/squawk_syntax__test__create_aggregate_params_validation.snap +++ b/crates/squawk_syntax/src/snapshots/squawk_syntax__test__create_aggregate_params_validation.snap @@ -2,7 +2,7 @@ source: crates/squawk_syntax/src/test.rs input_file: crates/squawk_syntax/test_data/validation/create_aggregate_params.sql --- -SOURCE_FILE@0..366 +SOURCE_FILE@0..484 COMMENT@0..38 "-- can't have out par ..." WHITESPACE@38..39 "\n" CREATE_AGGREGATE@39..119 @@ -147,80 +147,149 @@ SOURCE_FILE@0..366 R_PAREN@229..230 ")" SEMICOLON@230..231 ";" WHITESPACE@231..233 "\n\n" - CREATE_AGGREGATE@233..365 + CREATE_AGGREGATE@233..349 CREATE_KW@233..239 "create" WHITESPACE@239..240 " " AGGREGATE_KW@240..249 "aggregate" WHITESPACE@249..250 " " - AGGREGATE_NAME@250..267 - PATH@250..267 - PATH_SEGMENT@250..267 - IDENT@250..267 "ordered_aggregate" - PARAM_LIST@267..319 - L_PAREN@267..268 "(" - WHITESPACE@268..271 "\n " - PARAM@271..285 - PARAM_NAME@271..277 - IDENT@271..277 "direct" - WHITESPACE@277..278 " " - PATH_TYPE@278..285 - PATH_REF@278..285 - PATH_SEGMENT_REF@278..285 - INTEGER_KW@278..285 "integer" - WHITESPACE@285..286 " " - AGGREGATE_ORDER_BY@286..317 - ORDER_KW@286..291 "order" - WHITESPACE@291..292 " " - BY_KW@292..294 "by" - WHITESPACE@294..295 " " - PARAM@295..317 - PARAM_NAME@295..305 - IDENT@295..305 "aggregated" - WHITESPACE@305..306 " " - PATH_TYPE@306..313 - PATH_REF@306..313 - PATH_SEGMENT_REF@306..313 - INTEGER_KW@306..313 "integer" - WHITESPACE@313..314 " " - PARAM_DEFAULT@314..317 - EQ@314..315 "=" - WHITESPACE@315..316 " " - LITERAL@316..317 - INT_NUMBER@316..317 "1" - WHITESPACE@317..318 "\n" - R_PAREN@318..319 ")" - WHITESPACE@319..320 " " - ATTRIBUTE_LIST@320..364 - L_PAREN@320..321 "(" - WHITESPACE@321..324 "\n " - ATTRIBUTE_OPTION@324..343 - ATTRIBUTE_NAME@324..329 - IDENT@324..329 "sfunc" - WHITESPACE@329..330 " " - EQ@330..331 "=" - WHITESPACE@331..332 " " - ATTRIBUTE_VALUE@332..343 - PATH_TYPE@332..343 - PATH_REF@332..343 - PATH_SEGMENT_REF@332..343 - IDENT@332..343 "integer_sum" - COMMA@343..344 "," - WHITESPACE@344..347 "\n " - ATTRIBUTE_OPTION@347..362 - ATTRIBUTE_NAME@347..352 - IDENT@347..352 "stype" - WHITESPACE@352..353 " " - EQ@353..354 "=" - WHITESPACE@354..355 " " - ATTRIBUTE_VALUE@355..362 - PATH_TYPE@355..362 - PATH_REF@355..362 - PATH_SEGMENT_REF@355..362 - INTEGER_KW@355..362 "integer" - WHITESPACE@362..363 "\n" - R_PAREN@363..364 ")" - SEMICOLON@364..365 ";" - WHITESPACE@365..366 "\n" + AGGREGATE_NAME@250..266 + PATH@250..266 + PATH_SEGMENT@250..266 + IDENT@250..266 "invalid_variadic" + PARAM_LIST@266..303 + L_PAREN@266..267 "(" + PARAM@267..287 + PARAM_VARIADIC@267..275 + VARIADIC_KW@267..275 "variadic" + WHITESPACE@275..276 " " + PARAM_NAME@276..281 + IDENT@276..281 "items" + WHITESPACE@281..282 " " + ARRAY_TYPE@282..287 + PATH_TYPE@282..285 + PATH_REF@282..285 + PATH_SEGMENT_REF@282..285 + INT_KW@282..285 "int" + ARRAY_BOUND@285..287 + L_BRACK@285..286 "[" + R_BRACK@286..287 "]" + COMMA@287..288 "," + WHITESPACE@288..289 " " + PARAM@289..302 + PARAM_NAME@289..298 + FOLLOWING_KW@289..298 "following" + WHITESPACE@298..299 " " + PATH_TYPE@299..302 + PATH_REF@299..302 + PATH_SEGMENT_REF@299..302 + INT_KW@299..302 "int" + R_PAREN@302..303 ")" + WHITESPACE@303..304 " " + ATTRIBUTE_LIST@304..348 + L_PAREN@304..305 "(" + WHITESPACE@305..308 "\n " + ATTRIBUTE_OPTION@308..327 + ATTRIBUTE_NAME@308..313 + IDENT@308..313 "sfunc" + WHITESPACE@313..314 " " + EQ@314..315 "=" + WHITESPACE@315..316 " " + ATTRIBUTE_VALUE@316..327 + PATH_TYPE@316..327 + PATH_REF@316..327 + PATH_SEGMENT_REF@316..327 + IDENT@316..327 "integer_sum" + COMMA@327..328 "," + WHITESPACE@328..331 "\n " + ATTRIBUTE_OPTION@331..346 + ATTRIBUTE_NAME@331..336 + IDENT@331..336 "stype" + WHITESPACE@336..337 " " + EQ@337..338 "=" + WHITESPACE@338..339 " " + ATTRIBUTE_VALUE@339..346 + PATH_TYPE@339..346 + PATH_REF@339..346 + PATH_SEGMENT_REF@339..346 + INTEGER_KW@339..346 "integer" + WHITESPACE@346..347 "\n" + R_PAREN@347..348 ")" + SEMICOLON@348..349 ";" + WHITESPACE@349..351 "\n\n" + CREATE_AGGREGATE@351..483 + CREATE_KW@351..357 "create" + WHITESPACE@357..358 " " + AGGREGATE_KW@358..367 "aggregate" + WHITESPACE@367..368 " " + AGGREGATE_NAME@368..385 + PATH@368..385 + PATH_SEGMENT@368..385 + IDENT@368..385 "ordered_aggregate" + PARAM_LIST@385..437 + L_PAREN@385..386 "(" + WHITESPACE@386..389 "\n " + PARAM@389..403 + PARAM_NAME@389..395 + IDENT@389..395 "direct" + WHITESPACE@395..396 " " + PATH_TYPE@396..403 + PATH_REF@396..403 + PATH_SEGMENT_REF@396..403 + INTEGER_KW@396..403 "integer" + WHITESPACE@403..404 " " + AGGREGATE_ORDER_BY@404..435 + ORDER_KW@404..409 "order" + WHITESPACE@409..410 " " + BY_KW@410..412 "by" + WHITESPACE@412..413 " " + PARAM@413..435 + PARAM_NAME@413..423 + IDENT@413..423 "aggregated" + WHITESPACE@423..424 " " + PATH_TYPE@424..431 + PATH_REF@424..431 + PATH_SEGMENT_REF@424..431 + INTEGER_KW@424..431 "integer" + WHITESPACE@431..432 " " + PARAM_DEFAULT@432..435 + EQ@432..433 "=" + WHITESPACE@433..434 " " + LITERAL@434..435 + INT_NUMBER@434..435 "1" + WHITESPACE@435..436 "\n" + R_PAREN@436..437 ")" + WHITESPACE@437..438 " " + ATTRIBUTE_LIST@438..482 + L_PAREN@438..439 "(" + WHITESPACE@439..442 "\n " + ATTRIBUTE_OPTION@442..461 + ATTRIBUTE_NAME@442..447 + IDENT@442..447 "sfunc" + WHITESPACE@447..448 " " + EQ@448..449 "=" + WHITESPACE@449..450 " " + ATTRIBUTE_VALUE@450..461 + PATH_TYPE@450..461 + PATH_REF@450..461 + PATH_SEGMENT_REF@450..461 + IDENT@450..461 "integer_sum" + COMMA@461..462 "," + WHITESPACE@462..465 "\n " + ATTRIBUTE_OPTION@465..480 + ATTRIBUTE_NAME@465..470 + IDENT@465..470 "stype" + WHITESPACE@470..471 " " + EQ@471..472 "=" + WHITESPACE@472..473 " " + ATTRIBUTE_VALUE@473..480 + PATH_TYPE@473..480 + PATH_REF@473..480 + PATH_SEGMENT_REF@473..480 + INTEGER_KW@473..480 "integer" + WHITESPACE@480..481 "\n" + R_PAREN@481..482 ")" + SEMICOLON@482..483 ";" + WHITESPACE@483..484 "\n" error[syntax-error]: Out params are not allowed with aggregates. ╭▸ @@ -238,7 +307,11 @@ error[syntax-error]: Defaults are not allowed. ╭▸ 7 │ create aggregate aggregate_with_default(value integer default 1) ( ╰╴ ━━━━━━━━━ +error[syntax-error]: VARIADIC param must be last input param. + ╭▸ +12 │ create aggregate invalid_variadic(variadic items int[], following int) ( + ╰╴ ━━━━━━━━━━━━━ error[syntax-error]: Defaults are not allowed. ╭▸ -13 │ direct integer order by aggregated integer = 1 +18 │ direct integer order by aggregated integer = 1 ╰╴ ━━━ diff --git a/crates/squawk_syntax/src/snapshots/squawk_syntax__test__create_function_params_validation.snap b/crates/squawk_syntax/src/snapshots/squawk_syntax__test__create_function_params_validation.snap new file mode 100644 index 00000000..8a3f9a7e --- /dev/null +++ b/crates/squawk_syntax/src/snapshots/squawk_syntax__test__create_function_params_validation.snap @@ -0,0 +1,137 @@ +--- +source: crates/squawk_syntax/src/test.rs +input_file: crates/squawk_syntax/test_data/validation/create_function_params.sql +--- +SOURCE_FILE@0..271 + CREATE_FUNCTION@0..102 + CREATE_KW@0..6 "create" + WHITESPACE@6..7 " " + FUNCTION_KW@7..15 "function" + WHITESPACE@15..16 " " + FUNCTION_NAME@16..32 + PATH@16..32 + PATH_SEGMENT@16..32 + IDENT@16..32 "invalid_variadic" + PARAM_LIST@32..69 + L_PAREN@32..33 "(" + PARAM@33..53 + PARAM_VARIADIC@33..41 + VARIADIC_KW@33..41 "variadic" + WHITESPACE@41..42 " " + PARAM_NAME@42..47 + IDENT@42..47 "items" + WHITESPACE@47..48 " " + ARRAY_TYPE@48..53 + PATH_TYPE@48..51 + PATH_REF@48..51 + PATH_SEGMENT_REF@48..51 + INT_KW@48..51 "int" + ARRAY_BOUND@51..53 + L_BRACK@51..52 "[" + R_BRACK@52..53 "]" + COMMA@53..54 "," + WHITESPACE@54..55 " " + PARAM@55..68 + PARAM_NAME@55..64 + FOLLOWING_KW@55..64 "following" + WHITESPACE@64..65 " " + PATH_TYPE@65..68 + PATH_REF@65..68 + PATH_SEGMENT_REF@65..68 + INT_KW@65..68 "int" + R_PAREN@68..69 ")" + WHITESPACE@69..70 "\n" + RET_TYPE@70..82 + RETURNS_KW@70..77 "returns" + WHITESPACE@77..78 " " + PATH_TYPE@78..82 + PATH_REF@78..82 + PATH_SEGMENT_REF@78..82 + IDENT@78..82 "void" + WHITESPACE@82..83 "\n" + FUNC_OPTION_LIST@83..101 + LANGUAGE_FUNC_OPTION@83..95 + LANGUAGE_KW@83..91 "language" + WHITESPACE@91..92 " " + LANGUAGE_REF@92..95 + SQL_KW@92..95 "sql" + WHITESPACE@95..96 "\n" + AS_FUNC_OPTION@96..101 + AS_KW@96..98 "as" + WHITESPACE@98..99 " " + AS_DEFINITION@99..101 + LITERAL@99..101 + STRING@99..101 "''" + SEMICOLON@101..102 ";" + WHITESPACE@102..104 "\n\n" + COMMENT@104..168 "-- Functions can have ..." + WHITESPACE@168..169 "\n" + CREATE_FUNCTION@169..270 + CREATE_KW@169..175 "create" + WHITESPACE@175..176 " " + FUNCTION_KW@176..184 "function" + WHITESPACE@184..185 " " + FUNCTION_NAME@185..199 + PATH@185..199 + PATH_SEGMENT@185..199 + IDENT@185..199 "valid_variadic" + PARAM_LIST@199..237 + L_PAREN@199..200 "(" + PARAM@200..220 + PARAM_VARIADIC@200..208 + VARIADIC_KW@200..208 "variadic" + WHITESPACE@208..209 " " + PARAM_NAME@209..214 + IDENT@209..214 "items" + WHITESPACE@214..215 " " + ARRAY_TYPE@215..220 + PATH_TYPE@215..218 + PATH_REF@215..218 + PATH_SEGMENT_REF@215..218 + INT_KW@215..218 "int" + ARRAY_BOUND@218..220 + L_BRACK@218..219 "[" + R_BRACK@219..220 "]" + COMMA@220..221 "," + WHITESPACE@221..222 " " + PARAM@222..236 + PARAM_OUT@222..225 + OUT_KW@222..225 "out" + WHITESPACE@225..226 " " + PARAM_NAME@226..232 + IDENT@226..232 "result" + WHITESPACE@232..233 " " + PATH_TYPE@233..236 + PATH_REF@233..236 + PATH_SEGMENT_REF@233..236 + INT_KW@233..236 "int" + R_PAREN@236..237 ")" + WHITESPACE@237..238 "\n" + RET_TYPE@238..250 + RETURNS_KW@238..245 "returns" + WHITESPACE@245..246 " " + PATH_TYPE@246..250 + PATH_REF@246..250 + PATH_SEGMENT_REF@246..250 + IDENT@246..250 "void" + WHITESPACE@250..251 "\n" + FUNC_OPTION_LIST@251..269 + LANGUAGE_FUNC_OPTION@251..263 + LANGUAGE_KW@251..259 "language" + WHITESPACE@259..260 " " + LANGUAGE_REF@260..263 + SQL_KW@260..263 "sql" + WHITESPACE@263..264 "\n" + AS_FUNC_OPTION@264..269 + AS_KW@264..266 "as" + WHITESPACE@266..267 " " + AS_DEFINITION@267..269 + LITERAL@267..269 + STRING@267..269 "''" + SEMICOLON@269..270 ";" + WHITESPACE@270..271 "\n" + +error[syntax-error]: VARIADIC param must be last input param. + ╭▸ +1 │ create function invalid_variadic(variadic items int[], following int) + ╰╴ ━━━━━━━━━━━━━ diff --git a/crates/squawk_syntax/src/snapshots/squawk_syntax__test__create_procedure_params_validation.snap b/crates/squawk_syntax/src/snapshots/squawk_syntax__test__create_procedure_params_validation.snap new file mode 100644 index 00000000..4b8cac20 --- /dev/null +++ b/crates/squawk_syntax/src/snapshots/squawk_syntax__test__create_procedure_params_validation.snap @@ -0,0 +1,123 @@ +--- +source: crates/squawk_syntax/src/test.rs +input_file: crates/squawk_syntax/test_data/validation/create_procedure_params.sql +--- +SOURCE_FILE@0..188 + CREATE_PROCEDURE@0..90 + CREATE_KW@0..6 "create" + WHITESPACE@6..7 " " + PROCEDURE_KW@7..16 "procedure" + WHITESPACE@16..17 " " + PROCEDURE_NAME@17..33 + PATH@17..33 + PATH_SEGMENT@17..33 + IDENT@17..33 "invalid_variadic" + PARAM_LIST@33..70 + L_PAREN@33..34 "(" + PARAM@34..54 + PARAM_VARIADIC@34..42 + VARIADIC_KW@34..42 "variadic" + WHITESPACE@42..43 " " + PARAM_NAME@43..48 + IDENT@43..48 "items" + WHITESPACE@48..49 " " + ARRAY_TYPE@49..54 + PATH_TYPE@49..52 + PATH_REF@49..52 + PATH_SEGMENT_REF@49..52 + INT_KW@49..52 "int" + ARRAY_BOUND@52..54 + L_BRACK@52..53 "[" + R_BRACK@53..54 "]" + COMMA@54..55 "," + WHITESPACE@55..56 " " + PARAM@56..69 + PARAM_NAME@56..65 + FOLLOWING_KW@56..65 "following" + WHITESPACE@65..66 " " + PATH_TYPE@66..69 + PATH_REF@66..69 + PATH_SEGMENT_REF@66..69 + INT_KW@66..69 "int" + R_PAREN@69..70 ")" + WHITESPACE@70..71 "\n" + FUNC_OPTION_LIST@71..89 + LANGUAGE_FUNC_OPTION@71..83 + LANGUAGE_KW@71..79 "language" + WHITESPACE@79..80 " " + LANGUAGE_REF@80..83 + SQL_KW@80..83 "sql" + WHITESPACE@83..84 "\n" + AS_FUNC_OPTION@84..89 + AS_KW@84..86 "as" + WHITESPACE@86..87 " " + AS_DEFINITION@87..89 + LITERAL@87..89 + STRING@87..89 "''" + SEMICOLON@89..90 ";" + WHITESPACE@90..92 "\n\n" + CREATE_PROCEDURE@92..187 + CREATE_KW@92..98 "create" + WHITESPACE@98..99 " " + PROCEDURE_KW@99..108 "procedure" + WHITESPACE@108..109 " " + PROCEDURE_NAME@109..129 + PATH@109..129 + PATH_SEGMENT@109..129 + IDENT@109..129 "invalid_variadic_out" + PARAM_LIST@129..167 + L_PAREN@129..130 "(" + PARAM@130..150 + PARAM_VARIADIC@130..138 + VARIADIC_KW@130..138 "variadic" + WHITESPACE@138..139 " " + PARAM_NAME@139..144 + IDENT@139..144 "items" + WHITESPACE@144..145 " " + ARRAY_TYPE@145..150 + PATH_TYPE@145..148 + PATH_REF@145..148 + PATH_SEGMENT_REF@145..148 + INT_KW@145..148 "int" + ARRAY_BOUND@148..150 + L_BRACK@148..149 "[" + R_BRACK@149..150 "]" + COMMA@150..151 "," + WHITESPACE@151..152 " " + PARAM@152..166 + PARAM_OUT@152..155 + OUT_KW@152..155 "out" + WHITESPACE@155..156 " " + PARAM_NAME@156..162 + IDENT@156..162 "result" + WHITESPACE@162..163 " " + PATH_TYPE@163..166 + PATH_REF@163..166 + PATH_SEGMENT_REF@163..166 + INT_KW@163..166 "int" + R_PAREN@166..167 ")" + WHITESPACE@167..168 "\n" + FUNC_OPTION_LIST@168..186 + LANGUAGE_FUNC_OPTION@168..180 + LANGUAGE_KW@168..176 "language" + WHITESPACE@176..177 " " + LANGUAGE_REF@177..180 + SQL_KW@177..180 "sql" + WHITESPACE@180..181 "\n" + AS_FUNC_OPTION@181..186 + AS_KW@181..183 "as" + WHITESPACE@183..184 " " + AS_DEFINITION@184..186 + LITERAL@184..186 + STRING@184..186 "''" + SEMICOLON@186..187 ";" + WHITESPACE@187..188 "\n" + +error[syntax-error]: VARIADIC param must be last input param. + ╭▸ +1 │ create procedure invalid_variadic(variadic items int[], following int) + ╰╴ ━━━━━━━━━━━━━ +error[syntax-error]: VARIADIC param must be last. + ╭▸ +5 │ create procedure invalid_variadic_out(variadic items int[], out result int) + ╰╴ ━━━━━━━━━━━━━━ diff --git a/crates/squawk_syntax/src/validation.rs b/crates/squawk_syntax/src/validation.rs index 74707ebf..2e98735b 100644 --- a/crates/squawk_syntax/src/validation.rs +++ b/crates/squawk_syntax/src/validation.rs @@ -21,9 +21,12 @@ pub(crate) fn validate(root: &SyntaxNode, errors: &mut Vec) { ast::AtomicBody(it) => validate_atomic_body(it, errors), ast::BinExpr(it) => validate_bin_expr(it, errors), ast::CastExpr(it) => validate_cast_expr(it, errors), - ast::CreateAggregate(it) => validate_aggregate_params(it.param_list(), errors), + ast::CreateAggregate(it) => { + validate_aggregate_params(it.param_list(), errors); + validate_aggregate_variadic_params(it.param_list(), errors); + }, ast::CreateFunction(it) => validate_create_function(it, errors), - ast::CreateProcedure(it) => validate_routine_body(it.option_list(), it.body(), errors), + ast::CreateProcedure(it) => validate_create_procedure(it, errors), ast::CreateTable(it) => validate_create_table(it, errors), ast::CreateViewLike(it) => validate_non_empty_column_list(it.column_list(), errors), ast::CustomOp(it) => validate_custom_op_length(it, errors), @@ -870,6 +873,7 @@ fn validate_custom_op(op: ast::CustomOp, acc: &mut Vec) { fn validate_create_function(function: ast::CreateFunction, acc: &mut Vec) { validate_routine_body(function.option_list(), function.body(), acc); + validate_variadic_params(function.param_list(), ParamContext::Func, acc); let returns_table = function .ret_type() @@ -898,6 +902,67 @@ fn validate_create_function(function: ast::CreateFunction, acc: &mut Vec) { + validate_routine_body(procedure.option_list(), procedure.body(), acc); + validate_variadic_params(procedure.param_list(), ParamContext::Procedure, acc); +} + +#[derive(Clone, Copy, PartialEq, Eq)] +enum ParamContext { + Func, + Agg, + Procedure, +} + +fn validate_variadic_params( + params: Option, + context: ParamContext, + acc: &mut Vec, +) { + let Some(params) = params else { + return; + }; + validate_variadic_param_iter(params.all_params(), context, acc); +} + +fn validate_aggregate_variadic_params(params: Option, acc: &mut Vec) { + let Some(params) = params else { + return; + }; + validate_variadic_param_iter(params.params(), ParamContext::Agg, acc); + if let Some(order_by) = params.aggregate_order_by() { + validate_variadic_param_iter(order_by.params(), ParamContext::Agg, acc); + } +} + +fn validate_variadic_param_iter( + params: impl Iterator, + context: ParamContext, + acc: &mut Vec, +) { + let mut seen_variadic = false; + for param in params { + if !seen_variadic { + seen_variadic = matches!(param.mode(), Some(ast::ParamMode::ParamVariadic(_))); + continue; + } + if matches!(param.mode(), Some(ast::ParamMode::ParamOut(_))) { + if matches!(context, ParamContext::Func | ParamContext::Agg) { + continue; + } + acc.push(SyntaxError::new( + "VARIADIC param must be last.", + param.syntax().text_range(), + )); + continue; + } + acc.push(SyntaxError::new( + "VARIADIC param must be last input param.", + param.syntax().text_range(), + )); + } +} + fn validate_param_defaults(params: Option, acc: &mut Vec) { let Some(params) = params else { return; diff --git a/crates/squawk_syntax/test_data/validation/create_aggregate_params.sql b/crates/squawk_syntax/test_data/validation/create_aggregate_params.sql index 1a7aae45..8e0838fd 100644 --- a/crates/squawk_syntax/test_data/validation/create_aggregate_params.sql +++ b/crates/squawk_syntax/test_data/validation/create_aggregate_params.sql @@ -9,6 +9,11 @@ create aggregate aggregate_with_default(value integer default 1) ( stype = integer ); +create aggregate invalid_variadic(variadic items int[], following int) ( + sfunc = integer_sum, + stype = integer +); + create aggregate ordered_aggregate( direct integer order by aggregated integer = 1 ) ( diff --git a/crates/squawk_syntax/test_data/validation/create_function_params.sql b/crates/squawk_syntax/test_data/validation/create_function_params.sql new file mode 100644 index 00000000..56b073ad --- /dev/null +++ b/crates/squawk_syntax/test_data/validation/create_function_params.sql @@ -0,0 +1,10 @@ +create function invalid_variadic(variadic items int[], following int) +returns void +language sql +as ''; + +-- Functions can have OUT parameters after a VARIADIC parameter. +create function valid_variadic(variadic items int[], out result int) +returns void +language sql +as ''; diff --git a/crates/squawk_syntax/test_data/validation/create_procedure_params.sql b/crates/squawk_syntax/test_data/validation/create_procedure_params.sql new file mode 100644 index 00000000..0ed5a3ff --- /dev/null +++ b/crates/squawk_syntax/test_data/validation/create_procedure_params.sql @@ -0,0 +1,7 @@ +create procedure invalid_variadic(variadic items int[], following int) +language sql +as ''; + +create procedure invalid_variadic_out(variadic items int[], out result int) +language sql +as ''; diff --git a/crates/xtask/src/sync_pg.rs b/crates/xtask/src/sync_pg.rs index 05bd63e5..cf037e18 100644 --- a/crates/xtask/src/sync_pg.rs +++ b/crates/xtask/src/sync_pg.rs @@ -97,6 +97,8 @@ const IGNORED_LINES: &[&str] = &[ "SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a int exists empty object on empty));", "CREATE TABLE error_tbl (i int DEFAULT (100, ));", " AS $$ SELECT x * 2 $$", + "CREATE PROCEDURE ptestx(a VARIADIC int[], b OUT int) LANGUAGE SQL", + " AS $$ SELECT a[1] $$;", "CREATE STATISTICS alt_stat2 ON a FROM tftest(1);", "ALTER STATISTICS IF EXISTS ab1_a_b_stats SET STATISTICS 0;", "CHECKPOINT (WRONG);", @@ -558,6 +560,11 @@ mod tests { "-- CREATE TABLE error_tbl (i int DEFAULT (100, ));", ), (" AS $$ SELECT x * 2 $$", "-- AS $$ SELECT x * 2 $$"), + ( + "CREATE PROCEDURE ptestx(a VARIADIC int[], b OUT int) LANGUAGE SQL", + "-- CREATE PROCEDURE ptestx(a VARIADIC int[], b OUT int) LANGUAGE SQL", + ), + (" AS $$ SELECT a[1] $$;", "-- AS $$ SELECT a[1] $$;"), ( r#"ALTER DATABASE :"datname" REFRESH COLLATION VERSION;"#, r#"ALTER DATABASE "datname" REFRESH COLLATION VERSION;"#, diff --git a/postgres/regression_suite/create_procedure.sql b/postgres/regression_suite/create_procedure.sql index 4e8c5f02..398dfc26 100644 --- a/postgres/regression_suite/create_procedure.sql +++ b/postgres/regression_suite/create_procedure.sql @@ -238,8 +238,8 @@ CALL sum(1); -- error: not a procedure CREATE PROCEDURE ptestx() LANGUAGE SQL WINDOW AS $$ INSERT INTO cp_test VALUES (1, 'a') $$; CREATE PROCEDURE ptestx() LANGUAGE SQL STRICT AS $$ INSERT INTO cp_test VALUES (1, 'a') $$; -CREATE PROCEDURE ptestx(a VARIADIC int[], b OUT int) LANGUAGE SQL - AS $$ SELECT a[1] $$; +-- CREATE PROCEDURE ptestx(a VARIADIC int[], b OUT int) LANGUAGE SQL +-- AS $$ SELECT a[1] $$; CREATE PROCEDURE ptestx(a int DEFAULT 42, b OUT int) LANGUAGE SQL AS $$ SELECT a $$;