Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions crates/core/src/expression/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,21 +200,21 @@ pub fn resolve_element_name<'a>(
}

/// Reject `ExpressionAttributeNames`/`Values` supplied with no expression that
/// can reference them. Matches Amazon `DynamoDB`:
/// can reference them:
///
/// - names: `ExpressionAttributeNames can only be specified when using expressions`
/// (no suffix), for every API.
/// - values: `ExpressionAttributeValues can only be specified when using
/// expressions: <params> is/are null`, listing the value-capable expression
/// parameter(s) of the API.
/// expressions`, followed by `: <param> is null` or `: <a> and <b> are null`
/// when `value_expr_params` is not empty.
///
/// `name_expr_present` is true when any expression that can carry a `#name` is
/// present (projection, condition, filter, key condition, update).
/// `value_expr_present` is true when any expression that can carry a `:value` is
/// present (condition, filter, key condition, update; not projection).
/// `value_expr_params` is the API's static list of value-capable expression
/// parameter kinds, used to build the values suffix. An empty list yields no
/// suffix (matching Query).
/// `value_expr_params` lists the expression parameters the values message names
/// as null. Query and Scan pass an empty list, because the service's message for
/// them has no suffix.
///
/// # Errors
///
Expand Down
3 changes: 2 additions & 1 deletion crates/engine/src/scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,13 @@ pub async fn handle_scan(
.projection_expression
.as_ref()
.is_some_and(|s| !s.is_empty());
// Scan emits no values suffix (measured in us-east-1, #722).
extenddb_core::expression::validate_expression_param_usage(
input.expression_attribute_names.as_ref(),
has_proj_expr || has_filter_expr,
input.expression_attribute_values.as_ref(),
has_filter_expr,
&[ExpressionKind::Filter],
&[],
)?;

// ConditionalOperator requires a ScanFilter with two or more conditions.
Expand Down
8 changes: 4 additions & 4 deletions tests/test_expression_param_usage.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

Amazon DynamoDB rejects a request that provides ExpressionAttributeNames or
ExpressionAttributeValues when there is no expression parameter that could
reference them. The names message is always suffix-free; the values message
names the null value-capable expression parameter(s) for that API.
reference them. The names message is always suffix-free. On Query and Scan
the values message is suffix-free as well: it ends after "expressions".

Dual-target against Amazon DynamoDB and extenddb.
"""
Expand Down Expand Up @@ -82,7 +82,7 @@ def test_scan_values_no_expression(self, dynamodb_client, hash_table):
TableName=hash_table,
ExpressionAttributeValues={":v": {"S": "x"}},
),
f"{VALUES_PREFIX}: FilterExpression is null",
VALUES_PREFIX,
)

def test_delete_item_names_no_expression(self, dynamodb_client, hash_table):
Expand Down Expand Up @@ -162,7 +162,7 @@ def test_query_names_no_expression(self, dynamodb_client, hash_table):
)

def test_query_values_no_expression(self, dynamodb_client, hash_table):
# Query emits no values suffix, unlike Scan/Delete/Update.
# Query emits no values suffix, as Scan does.
_expect_validation(
lambda: dynamodb_client.query(
TableName=hash_table,
Expand Down
Loading