Skip to content

PartiQL (#411): an UPDATE or DELETE whose 32-level parameter is never stored is refused; the service runs it #813

Open

Description

@LeeroyHannigan

Follow-up to #411. A PartiQL UPDATE or DELETE whose parameter holds a value nested 32 levels deep runs on the service when the statement does not store that value: SET a = if_not_exists(a, ?) on an item that already has a, and a parameter used only in the WHERE clause. On the #411 branch ExtendDB refuses these statements, because the PartiQL layer runs an UPDATE through handle_update_item and a DELETE through handle_delete_item with the parameters as ExpressionAttributeValues, and those handlers refuse every value nested 32 levels deep. For the classic operations that refusal matches the service, which refuses a 32-level ExpressionAttributeValues entry on UpdateItem and DeleteItem even when only the condition reads it, and main does the same, so the PartiQL statements are the only ones that differ.

Measured against Amazon DynamoDB in us-east-1 on 2 November 2026 (PartiQL rows) and on 24 August 2026 (UpdateItem and DeleteItem rows, the measurement behind the comment above the depth check in crates/engine/src/update_item.rs). Table pk S HASH; the item holds a = {"N": "1"}; the parameter or :v is 32 maps around {"S": "leaf"}. ExtendDB answers for the classic rows are from main eaf16e89e (SQLite, debug build). Main has no PartiQL, so the PartiQL rows give the #411 branch's answer: the three ExecuteStatement rows are tests marked strict xfail there (UNSTORED_DEEP_VALUE in tests/test_partiql_item_depth.py), and the ExecuteTransaction rows were measured on that branch on 2 November 2026.

Request DynamoDB ExtendDB
ExecuteStatement UPDATE "<t>" SET a = if_not_exists(a, ?) WHERE pk = 'k' 200, item unchanged #411: refused (strict xfail)
ExecuteStatement UPDATE "<t>" SET y = 1 WHERE pk = 'k' AND a <> ? 200, y stored #411: refused (strict xfail)
ExecuteStatement DELETE FROM "<t>" WHERE pk = 'k' AND a <> ? 200, item deleted #411: refused (strict xfail)
ExecuteTransaction with the if_not_exists UPDATE alone 200 #411: refused
ExecuteTransaction with the WHERE-only UPDATE alone 200 #411: 200
UpdateItem SET y = :one, ConditionExpression a <> :v ValidationException with the nesting text main: ValidationException: Nesting Levels have exceeded supported limits: Attributes in the item have nested levels beyond supported limit
UpdateItem SET a = if_not_exists(a, :v) not sent with a present; the row above shows the service checks a value the request never stores main: the same text
DeleteItem, ConditionExpression a <> :v ValidationException with the nesting text main: the same text
the three classic requests with 31 levels accepted main: accepted

Where the answer comes from

On the #411 branch, crates/engine/src/partiql/write/update.rs (line 67) calls handle_update_item_with, the body of handle_update_item, and crates/engine/src/partiql/write/delete.rs (line 62) calls handle_delete_item, with the statement's parameters as ExpressionAttributeValues. On main, handle_update_item checks every value with validate_attribute_values_nesting_depth (crates/engine/src/update_item.rs, line 240), and handle_delete_item does the same (crates/engine/src/delete_item.rs, line 106). The check refuses at 32 levels with nesting_depth_error (crates/core/src/validation/mod.rs, line 2561). On the #411 branch the PartiQL parameter check already refuses a parameter nested 33 levels or more, and the item check still applies to what the statement stores; neither of them depends on the handlers' check.

Not measured

The same statements inside BatchExecuteStatement, on either side. The exact refusal text on the #411 branch for the three ExecuteStatement rows was not captured in this pass. A SELECT that compares an existing item with a 32-level parameter returns the item on the service (2 November 2026) and on the #411 branch, so it is not part of this issue.

Related

#411. #720 and #721 cover 32-level values on Query and Scan, where the service also refuses values it never stores. #574 and #590 cover the nesting of the item an update produces.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions