feat: generalize accounts prefiltering logic to any filter shape#1207
feat: generalize accounts prefiltering logic to any filter shape#1207Azorlogh wants to merge 13 commits intorelease/v2.2from
Conversation
- Introduced a more efficient method for filtering accounts based on address segments by using INNER JOIN instead of LATERAL JOIN. - Enhanced the query logic to support multiple OR conditions for partial address filters. - Added comprehensive tests for various scenarios involving partial address filters, including PIT and OOT conditions.
- Updated the query in resource_volumes.go to include the 'moves' table alias, resolving issues with missing aliases in specific query scenarios. - Added a test case to validate the fix, ensuring proper functionality when filtering using PIT and metadata without a partial address filter.
- Updated the volume query logic in resource_aggregated_balances.go to ensure the 'moves' table alias is correctly applied when filtering using PIT and metadata without a partial address filter. - Added a new test case in balances_test.go to validate the fix and ensure proper functionality in the specified scenario.
- Updated the query optimization in resource_aggregated_balances.go and resource_volumes.go to handle cases where partial address filters are combined with metadata filters, ensuring accurate results without excluding relevant accounts. - Added new test cases in balances_test.go and volumes_test.go to validate the functionality of the updated query logic, specifically for scenarios involving $or conditions with partial addresses and metadata.
- Updated the query logic in resource_aggregated_balances.go and resource_volumes.go to optimize filtering with single partial address conditions, ensuring accurate results when combined with other filters. - Added new test cases in balances_test.go and volumes_test.go to validate the functionality of the updated query logic, specifically for scenarios involving $or conditions with partial addresses and balance filters.
- Enhanced the handling of partial address filtering in resource_aggregated_balances.go and resource_volumes.go to ensure accurate results when combined with complex query operators. - Updated the test cases in balances_test.go to reflect changes in expected results for address filtering scenarios. - Introduced a new utility function to analyze query complexity, ensuring optimizations are applied safely without excluding relevant accounts.
- Modified test cases in balances_test.go and volumes_test.go to reflect changes in address filtering, ensuring accurate expectations for partial address queries. - Enhanced utility functions in utils.go to clarify the semantics of address patterns, improving the handling of segment counts for filtering logic.
… edge cases - Introduced new test cases in volumes_test.go to validate the handling of special characters and long patterns in account addresses. - Added scenarios for UTF-8 characters, patterns with wildcards, and edge cases to ensure accurate filtering and matching behavior. - Enhanced tests for complex query combinations, including $or and $and conditions, to verify expected results across various address formats.
…fixes - Introduced a new test case in volumes_test.go to validate the behavior of $or queries when combining partial and exact address prefixes. - Ensured that the tests cover scenarios with both matching and non-matching exact addresses, confirming correct volume retrieval. - Enhanced parallel execution of tests for improved performance and reliability.
WalkthroughAdds a Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
internal/storage/ledger/utils.go (1)
26-53: Add nil guard and safe type assertion to prevent runtime panics.
filterInvolvedAccountscallsbuilder.Build()unconditionally and usesvalue.(string)without type checking. Throughout the codebase (resource.go, legacy/balances.go, legacy/volumes.go, legacy/logs.go), nil guards precede.Build()calls. Additionally, defensive type assertions are safer than direct casting.♻️ Proposed fix
func filterInvolvedAccounts(builder query.Builder, addressColumnName string) (string, []any, error) { + if builder == nil { + return "true", nil, nil + } return builder.Build(query.ContextFn(func(property, operator string, value any) (string, []any, error) { if property == "address" || property == "account" { - return filterAccountAddress(value.(string), addressColumnName), nil, nil + s, ok := value.(string) + if !ok { + return "", nil, fmt.Errorf("expected string for %s filter", property) + } + return filterAccountAddress(s, addressColumnName), nil, nil } else { return "true", nil, nil } })) }
🤖 Fix all issues with AI agents
In `@internal/storage/ledger/resource_aggregated_balances.go`:
- Around line 91-118: The optimized path building the select (inside the
useAddressOptimization branch creating ret via store.newScopedSelect()) applies
only the PIT filter (query.PIT) but omits the OOT filter (query.OOT); update
that branch to also apply the OOT constraint by adding a Where(...) using the
same date column variable (dateFilterColumn) and query.OOT when query.OOT is set
(similar to how resource_volumes.go handles both PIT and OOT), so ret includes
both Where("moves."+dateFilterColumn+" <= ?", query.PIT) and the appropriate OOT
Where clause (e.g., Where("moves."+dateFilterColumn+" >= ?", query.OOT) or the
correct operator used elsewhere) when needed.
- Around line 105-116: The metadata lateral join block guarded by
query.useFilter("metadata") (the subQuery built via store.newScopedSelect(),
DistinctOn("accounts_address"), ColumnExpr("first_value(metadata) ... as
metadata"), and the Join(`left join lateral (?) accounts_metadata on true`) plus
Column("metadata")) is dead because useAddressOptimization is defined as
needAddressSegments && !query.useFilter("metadata"), so when this optimization
path runs query.useFilter("metadata") is always false; remove this unreachable
metadata join and Column("metadata") addition from the optimized branch (i.e.,
delete the entire if query.useFilter("metadata") { ... } block inside the
useAddressOptimization path) to eliminate dead code.
- Around line 50-53: The skipFilter in
aggregatedBalancesResourceRepositoryHandler currently only checks
query.UsePIT(), causing the PIT-only optimization to miss OOT queries; update
aggregatedBalancesResourceRepositoryHandler.skipFilter (method on type
aggregatedBalancesResourceRepositoryHandler taking
repositoryHandlerBuildContext[ledgercontroller.GetAggregatedVolumesOptions]) to
mirror volumesResourceHandler.skipFilter by using query.UsePIT() ||
query.UseOOT() (i.e., change the first condition to include UseOOT) while
keeping the existing needAddressSegments and !query.useFilter("metadata") checks
so buildDataset optimization applies for both PIT and OOT.
In `@internal/storage/ledger/resource_volumes.go`:
- Around line 144-154: The metadata lateral join block guarded by
query.useFilter("metadata") inside resource_volumes.go is dead because the
surrounding useAddressOptimization path already enforces
!query.useFilter("metadata"); remove the entire metadata-handling block (the if
query.useFilter("metadata") { ... } that builds subQuery and appends the lateral
join to selectVolumes) to eliminate unreachable code and avoid confusion; ensure
no other references to the removed subQuery or accounts_metadata join remain in
the same function.
- Around line 187-197: The metadata lateral subquery in resource_volumes.go (the
block that runs when query.useFilter("metadata") and builds subQuery via
store.newScopedSelect() with DistinctOn/ModelTableExpr/ColumnExpr and is joined
into selectVolumes) lacks point-in-time filtering; update that subQuery to
include a Where("date <= ?", query.PIT) condition in addition to the existing
Where("accounts_metadata.accounts_address = moves.accounts_address") so the
lateral join only returns metadata as of the requested PIT. Also apply the same
fix to the optimized-path metadata handling block that builds/joins metadata
(the other code path that constructs a metadata subquery or array_agg and
attaches "(array_agg(metadata))[1] as metadata") to ensure consistent PIT/OOT
behavior.
🧹 Nitpick comments (1)
internal/storage/ledger/volumes_test.go (1)
1035-1055: Verify filter field name consistency.This test uses
"address"as the filter field name, while other tests use"account". Both should work since"account"is defined as an alias for"address"involumesResourceHandler.filters(), but consider using consistent field names across tests for clarity.
based on #1206
Makes the logic work for any filter, simplifying it & giving us more choice for when to enable/disable it