Repository navigation
Conversation
`#a` (NIP-01 address) was post-filtered after SQL LIMIT, so a selective
read such as `{kinds:[7], "#a":["30175:<pubkey>:<d>"]}` scanned the newest
rows community-wide and could return too few matches, or none, and COUNT
could not take its exact fast path.
`EventQuery.a_tags` mirrors `e_tags`: an exact positional tag match with
JSONB containment as the GIN prefilter (`idx_events_tags_gin`, no schema
change), the MATERIALIZED CTE fence, no recent-first split, and an empty
set matches nothing, as the post-filter does. `filter_to_query_params`
fills it for every filter and `filter_fully_pushable` treats `#a` as
pushed. `per_channel_scope` now excludes every fenced read through the
shared `reference_tag_fence` helper, so `#a` with a multi-value `#h`
cannot nest the fence around the per-channel lateral.
Co-authored-by: Son of Anton <8e0ef2ab02d69a7ac089ef5eca90d1a3fbbdc546f6322dc34d0c4f3deecea7f4@buzz.block.builderlab.xyz>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Jemiah Westerman <jemiah@squareup.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The relay applied
#a(NIP-01 address) filters only after the SQLLIMIT. A selective read like{kinds:[7], "#a":["30175:<pubkey>:<d>"], limit:n}fetched the newest kind:7 rows across the whole community and then dropped the ones that didn't match. When older matches existed, it could return fewer thannof them, or none. COUNT also could not take its exact fast path. Clients therefore cannot count reactions to an addressable event by address, which is the identity that persists when the event is edited.What changed:
EventQuery.a_tags(buzz-db) works likee_tags. It is an exact positional tag match (tag->>0 = 'a' AND tag->>1 = ANY(..)) with JSONB@>as the prefilter on the existing GIN indexidx_events_tags_gin.#e, so the planner cannot walkcreated_atbackward looking for a rare match.count_events_sql.filter_to_query_paramsfillsa_tagsfor every filter, andfilter_fully_pushabletreats#aas pushed. REQ, COUNT and the HTTP bridge/queryand/countall go through these two functions.per_channel_scopenow skips per-channel reads for every fenced query, through a sharedreference_tag_fencehelper. Before this, it excluded#ereads explicitly, and#awith a multi-value#hwould have wrapped the fence around the per-channel lateral, which is invalid SQL.Not included:
#kand other low-cardinality tags. Postgres's estimate for JSONB@>assumes any match is rare, so pushing a common value could switch to a slower plan. They remain post-filters.Related issue
None found.
Testing
req.rsunit test:#amaps toa_tags(including empty and absent) and is fully pushable;#a+#kis not.#aread is fenced, COUNT applies the match, an#aread is never split into recent and older passes, and#amakes a read ineligible for per-channel scope. An empty#ais answered without a database read.#acase added topushed_down_tag_filters_reject_positional_decoys, covering query and COUNT.handlers/tag_pushdown_postgres_tests.rs:#amatch ahead of a full page of newer reactions to another address. COUNT is exact, and an empty#acounts 0. This test fails whena_tagsis removed fromfilter_to_query_params.#a+ a multi-value#h. This test fails, withCLOSED database error, without theper_channel_scopefix.REQ {kinds:[7], #a:[needle], limit:2}returned exactly the two needle reactions, newest first. COUNT returned 2 for the needle, 6 for the hay and 0 for an empty#a.#a+#ewithlimit:1returned the newest needle reaction.🤖 Generated with Claude Code