Skip to content

fix(dynamodb): honor legacy QueryFilter parameter#1

Merged
brandon-rhombus merged 1 commit into
mainfrom
brandon/dynamodb-legacy-queryfilter
May 6, 2026
Merged

fix(dynamodb): honor legacy QueryFilter parameter#1
brandon-rhombus merged 1 commit into
mainfrom
brandon/dynamodb-legacy-queryfilter

Conversation

@brandon-rhombus
Copy link
Copy Markdown

@brandon-rhombus brandon-rhombus commented May 6, 2026

Summary

Fixes a silent bug where Query requests carrying the legacy QueryFilter parameter (rather than FilterExpression) returned unfiltered results.

Repro

curl -sk -X POST http://localhost:4566/ \
  -H "X-Amz-Target: DynamoDB_20120810.Query" \
  -H "Content-Type: application/x-amz-json-1.0" \
  -d '{
    "TableName": "Devices",
    "KeyConditions": {"orgUuid": {"AttributeValueList": [{"S": "..."}], "ComparisonOperator": "EQ"}},
    "QueryFilter": {"type": {"AttributeValueList": [{"S": "AUDIO_GATEWAY"}], "ComparisonOperator": "EQ"}}
  }'

Before: returns rows of every type for that org. After: returns only AUDIO_GATEWAY rows.

Why this matters

The AWS Java SDK v1 Document API still emits QueryFilter when callers use QuerySpec.withQueryFilters(...). A lot of existing Java code does — including older Rhombus services. Without honoring QueryFilter, type-discriminated reads against polymorphic tables (e.g. "fetch only AUDIO_GATEWAY rows" from a Devices table that mixes camera/audio-gateway/door rows) returned every row, and the caller then blew up casting CameraType to AudioGatewayType.

What changed

Scan already supports the legacy ScanFilter parameter (same wire format) in handleScan / scan(...). This PR adds the symmetric plumbing for Query:

  • DynamoDbJsonHandler.handleQuery reads QueryFilter from the request and passes it through.
  • DynamoDbService.query accepts a new JsonNode queryFilter parameter and applies it post-FilterExpression via matchesScanFilter — the wire format is identical to ScanFilter.
  • Three older query(...) overloads pass null for the new parameter to preserve existing call sites.

Test plan

  • Verified manually by hitting the local emulator with the curl above before/after — before: 2 rows; after: 1 row (only the type that matches the filter)
  • Existing scan tests should be unaffected (no scan code paths changed)
  • Existing query tests with FilterExpression should be unaffected (new branch only fires when QueryFilter is present, applied after FilterExpression)

🤖 Generated with Claude Code


Note

Medium Risk
Changes Query result filtering semantics when legacy QueryFilter is present, which can alter returned items for some callers. Scope is limited and backwards-compatible for existing call sites that don’t send QueryFilter.

Overview
Fixes DynamoDB emulator Query handling to honor the legacy QueryFilter request parameter (emitted by AWS SDK v1 Document API), preventing silently unfiltered query results.

DynamoDbJsonHandler.handleQuery now parses and forwards QueryFilter, and DynamoDbService.query adds a new overload that applies the filter after any FilterExpression using the existing matchesScanFilter logic; existing query(...) overloads pass null to preserve current behavior.

Reviewed by Cursor Bugbot for commit e4a49ad. Bugbot is set up for automated code reviews on this repo. Configure here.

The Query handler reads only FilterExpression — it silently dropped
the legacy QueryFilter parameter, returning unfiltered results. The
AWS Java SDK v1 Document API still emits QueryFilter when callers use
QuerySpec.withQueryFilters(...), and a fair amount of existing Java
code still does. Without honoring it, type-discriminated reads
(e.g. "fetch only AUDIO_GATEWAY rows" against a polymorphic device
table) returned all rows, then blew up downstream when callers cast
to the wrong concrete type.

ScanFilter (the Scan-side equivalent with the same wire format) was
already supported in handleScan/scan(...). This change mirrors that
plumbing for Query: parse QueryFilter in the JSON handler, thread it
through to DynamoDbService.query, and apply it post-FilterExpression
via matchesScanFilter (the wire format is identical).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@brandon-rhombus brandon-rhombus merged commit accc24d into main May 6, 2026
11 checks passed
@brandon-rhombus brandon-rhombus deleted the brandon/dynamodb-legacy-queryfilter branch May 6, 2026 01:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant