feat: scope trgm operators to tables with intentional search (Option C)#841
Merged
pyramation merged 5 commits intomainfrom Mar 17, 2026
Merged
feat: scope trgm operators to tables with intentional search (Option C)#841pyramation merged 5 commits intomainfrom
pyramation merged 5 commits intomainfrom
Conversation
- Change createTrgmOperatorFactories() to target 'StringTrgm' type instead of global 'String', so trgm operators register on StringTrgmFilter rather than the shared StringFilter used by every string column everywhere. - Register StringTrgmFilter type in unified search plugin init hook with pgConnectionFilterOperators scope so standard operators auto-propagate. - In GraphQLInputObjectType_fields hook, swap StringFilter to StringTrgmFilter for string attribute fields on tables that qualify for trgm (via the existing supplementary adapter gating logic). - Add @trgmSearch smart tag support: tables or columns tagged with @trgmSearch will activate supplementary adapters (including trgm) even without tsvector or BM25 intentional search infrastructure.
Contributor
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
… without intentional search)
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
Previously,
createTrgmOperatorFactories()registeredsimilarToandwordSimilarToon the global'String'type, which meant these trgm operators appeared on every string field in every table — regardless of whether the table had any search infrastructure.This PR implements per-table scoping (Option C from research) by introducing a
StringTrgmFiltertype variant:operator-factories.ts: ChangedtypeNamesfrom'String'to'StringTrgm'so trgm operators register onStringTrgmFilterinstead of the sharedStringFilter.plugin.ts(init hook): RegistersStringTrgmFilteras a new input object type withpgConnectionFilterOperatorsscope. The connection filter operators plugin auto-propagates all standard string operators (equalTo, startsWith, etc.) to it, plus the custom trgm operators get added via the factory.plugin.ts(GraphQLInputObjectType_fields hook): For tables wheregetAdapterColumns()returns trgm columns, swaps string attribute field types fromStringFilter→StringTrgmFilter. Non-qualifying tables keep plainStringFilter.plugin.ts(getAdapterColumns): Added@trgmSearchsmart tag support — tables or columns tagged with@trgmSearchactivate supplementary adapters even without tsvector/BM25 infrastructure.Result:
filter: { name: { similarTo: { value: "jon" } } }only appears on tables with intentional search (or@trgmSearchtag). The unified search plugin's per-table features (trgmName, fullTextSearch, score fields, orderBy) continue working as before.Snapshot updates
Both test snapshot files were updated to reflect the schema change:
StringFilterno longer containssimilarTo/wordSimilarTooperatorsTrgmSearchInputtype (and its dependencyFloatscalar in the introspection snapshot) are no longer registered in schemas without intentional search infrastructureReview & Testing Checklist for Human
similarTo/wordSimilarToappear on qualifying tables: The test databases don't have tsvector/BM25 columns, so CI only validates the removal path. The positive path (operators appearing on a qualifying table'sStringTrgmFilter) is untested by CI. Must be verified manually against a database with a tsvector column.field.type === StringFilterType) relies on GraphQL type object identity. IffieldWithHookswraps or clones the type object, the comparison would silently fail and trgm operators would disappear from ALL tables (including qualifying ones). This needs a live test with a table that has tsvector + text columns.StringTrgmFiltergets the full set of standard operators: It's registered withpgCodecs: [textCodec](justTYPES.text), whileStringFilterhas all string codecs (text, varchar, bpchar, name, char, citext). Confirm thatConnectionFilterOperatorsPlugingenerates identical standard operators on both types.@trgmSearchsmart tag path: AddCOMMENT ON TABLE foo IS E'@trgmSearch';on a table without tsvector/BM25 and verify trgm operators appear on its string fields.Object.assign({}, field, ...)shallow clone preserves Graphile field metadata: IffieldWithHooksattaches non-enumerable properties, the cloned field may lose important internal state (apply functions, scope data, etc.).Recommended test plan: Start the GraphQL server against a database with at least one table that has a tsvector column and one that doesn't. Use GraphiQL to introspect both table filters and verify
similarTo/wordSimilarToappear only on the qualifying table's string fields.Notes
mainand not introduced by this PR.as anycasts for smart tag checking and scope registration are consistent with existing patterns in this file, but worth noting.Link to Devin session: https://app.devin.ai/sessions/08765fef6135466bb5403f799e933fbe
Requested by: @pyramation