Skip to content

Cassandra: paging a Query on a GSI with two HASH attributes reads the second HASH attribute as the sort key #673

Open

Description

@LeeroyHannigan

On the Cassandra backend, a Query with an ExclusiveStartKey on a GSI whose key schema has two HASH attributes and one RANGE attribute reads the cursor's sort key value from the wrong attribute. crates/storage-cassandra/src/data/query.rs takes query_key_schema[1] as the sort key (line 234 on main, line 264 on #429). For HASH h1, h2 and RANGE r that is h2, so page 2 starts from h2's value instead of r's.

Reproduction

main at 3051e50, dev build with the Cassandra backend, cassandra:4.1 with PasswordAuthenticator. Table key PK (S). GSI two-hash with HASH h1 (S) and h2, RANGE r (N), projection ALL. Five items, p1 to p5, all with h1 = "1", and r = 1, 2, 3, 3, 3. Each request sets Limit: 2 and passes the previous page's LastEvaluatedKey as ExclusiveStartKey. All five items were in the index before the first page.

h2 defined as N, every item at h2 = 0:

key condition page 1 page 2 later pages
h1 = :x AND h2 = :y p1, p2 p1, p2 pages 3 to 5 return p1, p2 again
h1 = :x AND h2 = :y AND r > :z (:z = 0) p1, p2 500
h1 = :x AND h2 = :y AND r = :z (:z = 3) p3, p4 500

Page 1's LastEvaluatedKey for the first query is {"PK": {"S": "p2"}, "h1": {"S": "1"}, "h2": {"N": "0"}, "r": {"N": "2"}}. Page 2 repeats p1 and p2 because the cursor compares r with 0, the value of h2.

h2 defined as S, every item at h2 = "2": page 2 of each of the three queries answers 500, and the server logs storage internal error internal_error=sort key type mismatch, because the S value of h2 is parsed as the N sort key.

SQLite and PostgreSQL on the same commit page the h2 N table correctly: p1, p2, then p3, p4, then p5, and p3, p4 then p5 for r = :z.

The 500 with a condition on r also happens with one HASH attribute

The same items on a GSI with HASH h1 and RANGE r page correctly for h1 = :x (p1, p2, then p3, p4, then p5). Page 2 still answers 500 for h1 = :x AND r > :z and for h1 = :x AND r = :z. The server logs these Cassandra errors from the cursor's same_sk query:

  • r > :z: Column "sk_n" cannot be restricted by both an equality and an inequality relation
  • r = :z: sk_n cannot be restricted by more than one relation if it includes an Equal

So on Cassandra, a key condition on the RANGE attribute of a GSI cannot be combined with an ExclusiveStartKey, whatever the number of HASH attributes. That part may need its own issue.

Expected

Page 2 continues after the last item of page 1, as on SQLite and PostgreSQL: the cursor reads the RANGE attribute's value from the ExclusiveStartKey, and a key condition on the RANGE attribute and the cursor are applied together.

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