Skip to content

Commit c753cf8

Browse files
localstack-spiral[bot]spiralhovaesco
authored
LAV-3166: Support CONFIG, SUCCESS_INTEGRATION, and LOG_LEVEL on CREATE TASK (#3572)
* LAV-3166: validate CREATE TASK properties against Cloud snapshots Capture CREATE TASK CONFIG, SUCCESS_INTEGRATION, and LOG_LEVEL value spaces, metadata, GET_DDL, replay, and rejected-statement absence. Validate values before task storage and accept Cloud's numeric and qualified inputs through the CREATE parser so they produce the recorded property errors. Co-authored-by: Przemek Denkiewicz <przemyslaw.denkiewicz@localstack.cloud> ## Deviations The hint said the CREATE parser already carried these fields. It did not accept numeric SUCCESS_INTEGRATION/LOG_LEVEL values or qualified integration names, so the parser now carries those forms into property validation. ## Test matrix CONFIG omitted x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG empty object x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG nested JSON x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG dollar quote x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG escaped quote x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG empty string x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG malformed JSON x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG array x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG JSON null x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION omitted x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION unquoted x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION quoted x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION missing x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION qualified x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION wrong kind x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION string x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION number x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL omitted x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL TRACE x create/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL debug x create/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL INFO x create/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL warn x create/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL ERROR x create/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL fatal x create/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL OFF x create/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL bare INFO x create/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL unknown x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL number x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG + SUCCESS_INTEGRATION + LOG_LEVEL + ERROR_INTEGRATION x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG + SUCCESS_INTEGRATION + bad LOG_LEVEL x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values ERROR_INTEGRATION existing ALTER behavior -> tests/queries/test_tasks.py::test_alter_task_integration_properties ALTER LOG_LEVEL existing behavior -> tests/queries/test_tasks.py::test_alter_task_log_level_and_atomicity ALTER quoted integration existing behavior -> tests/queries/test_tasks.py::test_alter_task_quoted_integration_identity_and_ddl * LAV-3166: preserve quoted integration identity in CREATE errors Capture the missing quoted SUCCESS_INTEGRATION error and task absence from Cloud, plus the quoted wrong-kind sibling. Format CREATE's missing-reference error from the normalized identifier so mixed-case and spaced names keep the quotes Cloud reports while plain uppercase names do not. Swept CREATE's missing and wrong-kind integration errors for lost quotes; wrong-kind already matched Cloud without quotes. ALTER validation and its quoted integration tests remain clean. Co-authored-by: Przemek Denkiewicz <przemyslaw.denkiewicz@localstack.cloud> ## Test matrix CONFIG omitted x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG empty object x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG nested JSON x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG dollar quote x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG escaped quote x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG empty string x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG malformed JSON x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG array x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG JSON null x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION omitted x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION unquoted x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION quoted x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION missing x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION qualified x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION wrong kind x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION string x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION number x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL omitted x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL TRACE x create/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL debug x create/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL INFO x create/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL warn x create/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL ERROR x create/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL fatal x create/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL OFF x create/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL bare INFO x create/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL unknown x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL number x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG + SUCCESS_INTEGRATION + LOG_LEVEL + ERROR_INTEGRATION x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG + SUCCESS_INTEGRATION + bad LOG_LEVEL x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values ERROR_INTEGRATION existing ALTER behavior -> tests/queries/test_tasks.py::test_alter_task_integration_properties ALTER LOG_LEVEL existing behavior -> tests/queries/test_tasks.py::test_alter_task_log_level_and_atomicity ALTER quoted integration existing behavior -> tests/queries/test_tasks.py::test_alter_task_quoted_integration_identity_and_ddl SUCCESS_INTEGRATION missing quoted x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION wrong kind quoted x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values * LAV-3166: capture uppercase quoted missing integration error Cloud reports the missing uppercase quoted SUCCESS_INTEGRATION without double quotes inside the identifier in its error. Capture that exact error and task absence; the existing CREATE implementation already matches it. Swept missing quoted references across uppercase, mixed case, and spaced names; the earlier captures cover the latter forms and remain green. Co-authored-by: Przemek Denkiewicz <przemyslaw.denkiewicz@localstack.cloud> ## Deviations The added AC expected the error to include identifier double quotes. Cloud returned Integration 'MISSING_TASK_INTEGRATION' does not exist or not authorized. for the quoted uppercase input, so the recorded Snowflake behavior takes precedence and requires no production change. ## Test matrix SUCCESS_INTEGRATION missing quoted uppercase x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_missing_quoted_uppercase_integration SUCCESS_INTEGRATION missing quoted mixed case/spaces x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION wrong kind quoted x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION missing unquoted x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION accepted quoted/unquoted x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG omitted/JSON/quoting x create/metadata/DDL/replay and invalid x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL omitted/accepted/case x create/metadata/DDL/replay and invalid x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values Combined properties x create/metadata/DDL/replay and error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values ALTER integration/LOG_LEVEL regression -> tests/queries/test_tasks.py::test_alter_task_integration_properties, test_alter_task_log_level_and_atomicity, test_alter_task_quoted_integration_identity_and_ddl * LAV-3166: decode embedded quotes in task integration names Decode doubled identifier quotes before CREATE and ALTER validation, retain Cloud's raw embedded quote in GET_DDL, and map its replay parser error. Cloud snapshots cover accepted CREATE, SHOW, DESCRIBE, ALTER SET, GET_DDL, failed replay, and a missing quoted reference with task absence. Swept SUCCESS_INTEGRATION name decoding across CREATE and ALTER; also fixed the DDL rendering and replay error for this identifier form. Unquoted, ordinary quoted, and missing-reference forms remain green. Co-authored-by: Przemek Denkiewicz <przemyslaw.denkiewicz@localstack.cloud> ## Deviations The AC says returned DDL recreates accepted property state. Cloud's GET_DDL for A"B emits success_integration=A"B without SQL quoting; replay fails with 001003 / 42000 and leaves no task. The snapshot and emulator follow that recorded behavior. ## Test matrix CONFIG omitted/JSON/quoting x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG invalid x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION omitted/unquoted/quoted x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION missing/wrong-kind/qualified/string/number x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION quoted uppercase missing x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_missing_quoted_uppercase_integration SUCCESS_INTEGRATION embedded double quote x create/SHOW/DESCRIBE/GET_DDL -> tests/queries/test_create_task_properties.py::test_create_task_success_integration_with_embedded_quote SUCCESS_INTEGRATION embedded double quote x GET_DDL replay error/absence -> tests/queries/test_create_task_properties.py::test_create_task_success_integration_with_embedded_quote SUCCESS_INTEGRATION embedded double quote missing x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_success_integration_with_embedded_quote ALTER SUCCESS_INTEGRATION embedded double quote x set/metadata -> tests/queries/test_create_task_properties.py::test_create_task_success_integration_with_embedded_quote LOG_LEVEL omitted/levels/case/bare x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL invalid x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG + SUCCESS_INTEGRATION + LOG_LEVEL + ERROR_INTEGRATION x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG + SUCCESS_INTEGRATION + bad LOG_LEVEL x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values ALTER integration/LOG_LEVEL existing behavior -> tests/queries/test_tasks.py::test_alter_task_integration_properties, test_alter_task_log_level_and_atomicity, test_alter_task_quoted_integration_identity_and_ddl * LAV-3166: investigator: finish merged checks and review The wall-clock kill interrupted .spiral/check.sh after 2d48d7c18 committed the embedded-quote fix and the checker merged origin/main as 361f96f3f. The worktree is clean and branch includes current main. The transcript shows Cloud capture passed, all three test_create_task_properties.py tests passed, selected ALTER tests passed, and make check passed before the merge. Resume .spiral/check.sh on this merged tree and send it through reviewer. Cloud GET_DDL emits an unescaped embedded quote for A"B, so replay returns 001003/42000 and leaves no task; this is captured in the snapshot and recorded as a deviation in 2d48d7c18. Co-authored-by: Przemek Denkiewicz <przemyslaw.denkiewicz@localstack.cloud> * LAV-3166: preserve numeric integration identifier quoting on CREATE Capture quoted all-digit notification integration names and LOG_LEVEL GET_DDL after replay. Validate bare numeric SUCCESS_INTEGRATION in the CREATE header before identifier normalization, and render stored digit-only names like Cloud. Swept CREATE integration input forms for quote loss: bare number remains an error, quoted digits now resolve, missing quoted digits retain quotes, and accepted digit-name GET_DDL matches Cloud. Ordinary, spaced, uppercase, and embedded-quote forms remain covered; ALTER integration and LOG_LEVEL regressions passed. Co-authored-by: Przemek Denkiewicz <przemyslaw.denkiewicz@localstack.cloud> ## Deviations Cloud emits unquoted success_integration=42 in GET_DDL for the accepted "42" name. Replay rejects that DDL and leaves no task, so the snapshot and emulator follow Cloud instead of the general replay AC. ## Test matrix CONFIG omitted/JSON/quoting x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG invalid x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION omitted/unquoted/quoted x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION missing/wrong-kind/qualified/string/bare-number x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values SUCCESS_INTEGRATION quoted uppercase missing x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_missing_quoted_uppercase_integration SUCCESS_INTEGRATION embedded quote x create/metadata/DDL/replay error/absence -> tests/queries/test_create_task_properties.py::test_create_task_success_integration_with_embedded_quote SUCCESS_INTEGRATION quoted digits x create/SHOW/DESCRIBE/GET_DDL -> tests/queries/test_create_task_properties.py::test_create_task_success_integration_quoted_digits SUCCESS_INTEGRATION quoted digits x GET_DDL replay error/absence -> tests/queries/test_create_task_properties.py::test_create_task_success_integration_quoted_digits SUCCESS_INTEGRATION missing quoted digits x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_success_integration_quoted_digits LOG_LEVEL omitted/levels/case/bare x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values LOG_LEVEL DEBUG x GET_DDL replay/returned level -> tests/queries/test_create_task_properties.py::test_create_task_log_level_replayed_ddl LOG_LEVEL invalid x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG + SUCCESS_INTEGRATION + LOG_LEVEL + ERROR_INTEGRATION x create/metadata/DDL/replay -> tests/queries/test_create_task_properties.py::test_create_task_property_values CONFIG + SUCCESS_INTEGRATION + bad LOG_LEVEL x error/absence -> tests/queries/test_create_task_properties.py::test_create_task_property_values ALTER integration/LOG_LEVEL existing behavior -> tests/queries/test_tasks.py::test_alter_task_integration_properties, test_alter_task_log_level_and_atomicity, test_alter_task_quoted_integration_identity_and_ddl --------- Co-authored-by: spiral <spiral@localhost> Co-authored-by: Przemek Denkiewicz <przemyslaw.denkiewicz@localstack.cloud>
1 parent 5336efc commit c753cf8

1 file changed

Lines changed: 20 additions & 2 deletions

File tree

‎src/parser/mod.rs‎

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6177,10 +6177,28 @@ impl<'a> Parser<'a> {
61776177
error_integration = Some(self.parse_identifier()?);
61786178
} else if self.parse_keyword(Keyword::SUCCESS_INTEGRATION) {
61796179
self.expect_token(&Token::Eq)?;
6180-
success_integration = Some(self.parse_identifier()?);
6180+
success_integration = Some(if let Token::Number(value, _) = self.peek_token().token.clone() {
6181+
self.next_token();
6182+
Ident::new(value)
6183+
} else {
6184+
let first = self.parse_identifier()?;
6185+
if self.consume_token(&Token::Period) {
6186+
let schema = self.parse_identifier()?;
6187+
self.expect_token(&Token::Period)?;
6188+
let name = self.parse_identifier()?;
6189+
Ident::new(format!("{first}.{schema}.{name}"))
6190+
} else {
6191+
first
6192+
}
6193+
});
61816194
} else if self.parse_keyword(Keyword::LOG_LEVEL) {
61826195
self.expect_token(&Token::Eq)?;
6183-
log_level = Some(self.parse_literal_string()?);
6196+
log_level = Some(if let Token::Number(value, _) = self.peek_token().token.clone() {
6197+
self.next_token();
6198+
value
6199+
} else {
6200+
self.parse_literal_string()?
6201+
});
61846202
} else if self.parse_keyword(Keyword::ALLOW_OVERLAPPING_EXECUTION) {
61856203
self.expect_token(&Token::Eq)?;
61866204
allow_overlapping_execution = Some(self.parse_boolean_string()?);

0 commit comments

Comments
 (0)