Issue
The @index directive in schema.gql doesn't support PostgreSQL operator classes (e.g. gin_trgm_ops). For fuzzy-search use cases requiring pg_trgm trigram indexes, the only path today is to create them directly in Postgres via raw SQL (CREATE INDEX foo ON tbl USING gin (col gin_trgm_ops)).
Because those indexes aren't expressible in schema.gql, every subsequent firebase deploy --only dataconnect proposes DROP INDEX foo as a "destructive change" and aborts.
Reproduction
- In Postgres:
CREATE EXTENSION pg_trgm; CREATE INDEX my_trgm_idx ON paper USING gin (title gin_trgm_ops);
- Add nothing related to the index in
schema.gql.
- Run
firebase deploy --only dataconnect --force.
- Observe:
⚠ dataconnect: PostgreSQL schema is incompatible with the SQL Connect Schema.
Those SQL statements will migrate it to be compatible:
/** Destructive: drop index "my_trgm_idx" from table: "paper" */
DROP INDEX "public"."my_trgm_idx"
Error: Command aborted. Your database schema is incompatible with your SQL Connect schema.
Why schemaValidation: COMPATIBLE doesn't help
The docs at https://firebase.google.com/docs/sql-connect/manage-schemas-and-connectors explicitly list DROP SCHEMA / DROP TABLE / DROP COLUMN as the operations COMPATIBLE protects. DROP INDEX is not in that list, and verified empirically: with schemaValidation: COMPATIBLE set and --force passed, the deploy still aborts on index-drop proposals.
Use case
Trigram indexes are how mature platforms (Algolia, Typesense internally, Elasticsearch with the wildcard field type) deliver typo-tolerance / fuzzy search on text columns. There's no SQL Connect-native alternative — @searchable is FTS-only (no edit-distance), and Native SQL (Preview) addresses query side, not schema.
Prior art
Prisma had the same issue: prisma/prisma#7515. Their resolution allowed @@index([col(ops: raw("gin_trgm_ops"))], type: Gin) in the Prisma schema, which made migrate aware of the index without it being the literal one it manages.
Proposed solutions (any of these would work)
- Extend
@index to accept an ops argument: @index(type: GIN, ops: "gin_trgm_ops"). Mirrors Prisma's resolution exactly.
- A
@preserveIndex(name: String) directive at the @table level — declares "an index of this name exists, please don't touch it".
- A
dataconnect/sql/ migration directory where arbitrary SQL DDL lives alongside the GraphQL schema. Schema-diff would mark anything created via these files as managed.
Option 1 is closest to existing primitives and would be the smallest API surface change.
Current workaround (not great)
Patching the deploy workflow to grep stdout for Destructive: drop index .*_trgm_idx and bypass the abort if those are the only destructive proposals. Brittle (depends on CLI output wording) but it's the only path that doesn't silently break the indexes.
Environment
firebase-tools 15.8.0
- Cloud SQL Postgres 16
dataconnect.yaml with schemaValidation: "COMPATIBLE" set correctly at the postgresql level
Issue
The
@indexdirective inschema.gqldoesn't support PostgreSQL operator classes (e.g.gin_trgm_ops). For fuzzy-search use cases requiringpg_trgmtrigram indexes, the only path today is to create them directly in Postgres via raw SQL (CREATE INDEX foo ON tbl USING gin (col gin_trgm_ops)).Because those indexes aren't expressible in
schema.gql, every subsequentfirebase deploy --only dataconnectproposesDROP INDEX fooas a "destructive change" and aborts.Reproduction
CREATE EXTENSION pg_trgm; CREATE INDEX my_trgm_idx ON paper USING gin (title gin_trgm_ops);schema.gql.firebase deploy --only dataconnect --force.Why
schemaValidation: COMPATIBLEdoesn't helpThe docs at https://firebase.google.com/docs/sql-connect/manage-schemas-and-connectors explicitly list
DROP SCHEMA / DROP TABLE / DROP COLUMNas the operations COMPATIBLE protects.DROP INDEXis not in that list, and verified empirically: withschemaValidation: COMPATIBLEset and--forcepassed, the deploy still aborts on index-drop proposals.Use case
Trigram indexes are how mature platforms (Algolia, Typesense internally, Elasticsearch with the
wildcardfield type) deliver typo-tolerance / fuzzy search on text columns. There's no SQL Connect-native alternative —@searchableis FTS-only (no edit-distance), and Native SQL (Preview) addresses query side, not schema.Prior art
Prisma had the same issue: prisma/prisma#7515. Their resolution allowed
@@index([col(ops: raw("gin_trgm_ops"))], type: Gin)in the Prisma schema, which made migrate aware of the index without it being the literal one it manages.Proposed solutions (any of these would work)
@indexto accept anopsargument:@index(type: GIN, ops: "gin_trgm_ops"). Mirrors Prisma's resolution exactly.@preserveIndex(name: String)directive at the@tablelevel — declares "an index of this name exists, please don't touch it".dataconnect/sql/migration directory where arbitrary SQL DDL lives alongside the GraphQL schema. Schema-diff would mark anything created via these files as managed.Option 1 is closest to existing primitives and would be the smallest API surface change.
Current workaround (not great)
Patching the deploy workflow to grep stdout for
Destructive: drop index .*_trgm_idxand bypass the abort if those are the only destructive proposals. Brittle (depends on CLI output wording) but it's the only path that doesn't silently break the indexes.Environment
firebase-tools15.8.0dataconnect.yamlwithschemaValidation: "COMPATIBLE"set correctly at thepostgresqllevel