Repository navigation
Query on a single-attribute key schema applies a condition on a non-key attribute to the sort key #674
Description
On a key schema with one HASH and one RANGE attribute, the engine checks only that the key condition has an equality on the HASH attribute. A second clause on any other attribute reaches storage as the sort key condition, and the SQLite and PostgreSQL backends apply a sort key condition that names no RANGE attribute to the first RANGE column (crates/storage-sqlite/src/data/query_scan.rs:79 and crates/storage-postgres/src/data/query_scan.rs:162 on main; lines 90 and 190 on #429, which keeps the fallback). The query returns items whose sort key matches the value, and a value whose type differs from the sort key's answers 500.
Reproduction
main at 3051e50, dev builds with the SQLite and the PostgreSQL backend; both answer the same. Table key pk (S) and sk (N). GSI gsi with HASH h (S) and RANGE a (S), projection ALL. Two items:
pk"p1",sk4,h"o1",a"x",zz9pk"p1",sk5,h"o1",a"p1",zz4
| request | answer |
|---|---|
table, pk = :p AND zz = :v, :p "p1", :v N 4 |
200, one item: sk 4, zz 9 |
table, pk = :p AND zz = :v, :p "p1", :v S "x" |
500 InternalServerError |
gsi, h = :h AND pk = :v, :h "o1", :v S "p1" |
200, one item: a "p1", sk 5 |
gsi, h = :h AND sk = :v, :h "o1", :v N 4 |
500 InternalServerError |
gsi, h = :h AND sk = :v, :h "o1", :v S "x" |
200, one item: a "x", sk 4 |
The first request filters on sk: it returns the item whose sk is 4, and the item whose zz is 4 has sk 5. The third filters on a, the index's RANGE attribute, and returns one of the two items with pk "p1". The last applies sk = "x" to a.
#429 adds a value type check on this path that reads the table's attribute definitions. On the #429 branch the last request answers 400 One or more parameter values were invalid: Condition parameter type does not match schema type, because the table defines sk as N, and the other four answer as on main. A clause on an attribute the table does not define, or one whose value has the defined type, still reaches storage. Once this path refuses non-key conditions, its type check can read the queried key schema's definitions only, as #429 does on a multi-attribute key schema.
Expected
ValidationException with Query condition missed key schema element: <RANGE attribute>, before the request reaches storage, whatever the value's type. Measured on the service on 2026-10-30 on a GSI with HASH GSI2PK (S) and RANGE GSI2SK (S) of a table keyed on PK (S): GSI2PK = :h AND PK = :k answers Query condition missed key schema element: GSI2SK with :k an S and with :k an N, two samples each. #489 has the base table form with a comparison, pk = :x AND z > :x, measured on 2026-10-23: the service answers Query condition missed key schema element: sk. On #429's branch the multi-attribute path refuses such a clause this way, naming the first RANGE attribute without a condition, and the service answers the same on multi-attribute key schemas (three shapes, 2026-10-30). The base table form with an equality (pk = :p AND zz = :v), a table with no RANGE attribute, and conditions with three or more clauses on a single-attribute key schema, where the service's condition count rule may answer first, were not measured and should be before the fix.
Activity
LeeroyHannigan commentedon Nov 1, 2026
Measured on the service on 1 November 2026 at about 13:18 UTC, on a table keyed on
pk(S) with no RANGE attribute, two samples each:pk = :p AND ssn = :sValidationException: The number of query conditions (2) exceeds the number of key attributes defined in the schema (1)pk = :p AND #s = :s,#s=ssnSo on a table with no RANGE attribute the condition count rule answers. A SQLite build with
main's Query code answered the first request with 200 and the item whosessnmatched.