Skip to content

UpdateItem: ADD l[0] :v is refused and DELETE l[0] :v changes nothing; the service applies both to the set in the list element #812

Open

Description

@LeeroyHannigan

ADD and DELETE with a path that ends in a list element, such as ADD l[0] :v where l[0] holds a string set, apply to that set on the service: ADD adds the members of :v and DELETE removes them. On ExtendDB, ADD answers The document path provided in the update expression is invalid for update, and DELETE answers 200 and leaves the set as it was, so a client that removes a member this way gets a success response and the member stays.

Measured against Amazon DynamoDB in us-east-1 on 2 November 2026, one request per row, the first two rows in that order on one item. Table pk S HASH; item l2 holds l = {"L": [{"SS": ["a"]}]}; every request has ReturnValues ALL_NEW. ExtendDB answers are from main eaf16e89e (SQLite, debug build).

Request DynamoDB ExtendDB main eaf16e89e (SQLite)
ADD l[0] :v, :v = {"SS": ["b"]}, on l = [{"SS": ["a"]}] 200, l = [{"SS": ["a", "b"]}] ValidationException: The document path provided in the update expression is invalid for update; item unchanged
DELETE l[0] :v, :v = {"SS": ["a"]}, on l = [{"SS": ["a", "b"]}] 200, l = [{"SS": ["b"]}] (the item the ADD above left) 200, l = [{"SS": ["a", "b"]}] (an item written with that value)
DELETE l[0] :v, :v = {"SS": ["a"]}, on l = [{"SS": ["a"]}] not sent 200, l = [{"SS": ["a"]}]
ADD m.k :v, :v = {"SS": ["b"]}, on m = {"k": {"SS": ["a"]}} not sent 200, m.k = {"SS": ["a", "b"]}

The last row shows that the same ADD through a map member is applied on main.

Where the answer comes from

crates/core/src/expression/update_evaluator.rs. apply_add (line 245) finds the parent of the last path element with navigate_to_parent_map_or_create (line 376). For l[0] the parent is the list l, and that function answers the invalid-path text for any parent that is not a map (lines 422 to 426). apply_delete (line 318) uses navigate_to_parent_map (line 433), which returns None for a parent that is not a map (lines 471 to 473); apply_delete then returns without a change (lines 324 and 325). Neither function has a branch for a path that ends in a list index.

Not measured

ADD l[0] :n with a number on a list element that holds a number, an index past the end of the list, a list element that holds a set of a different type, and the same actions inside TransactWriteItems, on either side.

Related

#411 translates the PartiQL set_add and set_delete functions into these two actions. The service applies both to a list element (SET l[0] = set_add(l[0], <<'b'>>), measured on the same day). On the #411 branch the set_add case is a test marked strict xfail for ExtendDB (test_set_add_applies_to_a_list_element in tests/test_partiql_update_paths.py), and set_delete on a list element answers 200 with the set unchanged.

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