From 89ba2ed65b1d43ee7d5716e1940ebbba7fbbf5f5 Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 18 Sep 2026 14:29:09 +0200 Subject: [PATCH 01/36] test(postgres): cover target-owned built-in query operations Red tests for the move of `ilike` into `@internal/target-postgres` and the three new full-text search operations. The adapter tests assert its runtime descriptor and descriptor meta no longer carry a query-operation surface. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../postgres/test/query-operations.test.ts | 119 ++++++++++++++++++ .../postgres/test/descriptor-meta.test.ts | 13 ++ 2 files changed, 132 insertions(+) create mode 100644 packages/3-targets/3-targets/postgres/test/query-operations.test.ts diff --git a/packages/3-targets/3-targets/postgres/test/query-operations.test.ts b/packages/3-targets/3-targets/postgres/test/query-operations.test.ts new file mode 100644 index 000000000000..11869ee7f6ee --- /dev/null +++ b/packages/3-targets/3-targets/postgres/test/query-operations.test.ts @@ -0,0 +1,119 @@ +import { createSqlOperationRegistry } from '@internal/sql-operations'; +import { LiteralExpr, OperationExpr, ParamRef } from '@internal/sql-relational-core/ast'; +import { describe, expect, it } from 'vitest'; +import postgresTargetDescriptor from '../src/exports/runtime'; + +const TEXT_COLUMN = ParamRef.of('body', { codec: { codecId: 'pg/text@1' } }); + +function operations() { + return postgresTargetDescriptor.queryOperations?.() ?? {}; +} + +function findOperation(method: string) { + const op = operations()[method]; + if (!op) throw new Error(`${method} not found`); + return op; +} + +function buildOpAst(method: string, ...args: unknown[]): OperationExpr { + const expr = findOperation(method).impl(...(args as never[])) as unknown as { + buildAst(): OperationExpr; + }; + return expr.buildAst(); +} + +describe('postgres target query operations', () => { + it('ilike lowers to the infix ILIKE template', () => { + const ast = buildOpAst('ilike', TEXT_COLUMN, '%launch%'); + + expect(ast).toBeInstanceOf(OperationExpr); + expect(ast.lowering).toEqual({ + targetFamily: 'sql', + strategy: 'infix', + template: '{{self}} ILIKE {{arg0}}', + }); + expect(ast.returns).toEqual({ codecId: 'pg/bool@1', nullable: false }); + }); + + const fullTextOps: ReadonlyArray = [ + [ + 'fullTextMatches', + 'pg/bool@1', + 'to_tsvector({{arg1}}, {{self}}) @@ websearch_to_tsquery({{arg1}}, {{arg0}})', + ], + [ + 'fullTextRank', + 'pg/float4@1', + 'ts_rank(to_tsvector({{arg1}}, {{self}}), websearch_to_tsquery({{arg1}}, {{arg0}}))', + ], + [ + 'fullTextHeadline', + 'pg/text@1', + 'ts_headline({{arg1}}, {{self}}, websearch_to_tsquery({{arg1}}, {{arg0}}))', + ], + ]; + + describe.each(fullTextOps)('%s', (method, returnCodecId, template) => { + it('builds an OperationExpr with the expected lowering and return codec', () => { + const ast = buildOpAst(method, TEXT_COLUMN, 'prisma'); + + expect(ast).toBeInstanceOf(OperationExpr); + expect(ast.lowering).toEqual({ targetFamily: 'sql', strategy: 'function', template }); + expect(ast.returns).toEqual({ codecId: returnCodecId, nullable: false }); + }); + + it('binds the query as a pg/text@1 parameter', () => { + const queryArg = buildOpAst(method, TEXT_COLUMN, 'prisma').args[0]; + + expect(queryArg).toBeInstanceOf(ParamRef); + expect((queryArg as ParamRef).value).toBe('prisma'); + expect((queryArg as ParamRef).codec?.codecId).toBe('pg/text@1'); + }); + + it('embeds the language as a literal, defaulting to english', () => { + const withDefault = buildOpAst(method, TEXT_COLUMN, 'prisma').args[1]; + const withGerman = buildOpAst(method, TEXT_COLUMN, 'prisma', 'german').args[1]; + + expect(withDefault).toBeInstanceOf(LiteralExpr); + expect(withDefault.kind).toBe('literal'); + expect((withDefault as LiteralExpr).value).toBe('english'); + expect((withGerman as LiteralExpr).value).toBe('german'); + }); + + it('rejects a language Postgres has no configuration for', () => { + expect(() => buildOpAst(method, TEXT_COLUMN, 'prisma', 'klingon')).toThrow(/klingon/); + expect(() => buildOpAst(method, TEXT_COLUMN, 'prisma', 'klingon')).toThrow( + expect.objectContaining({ code: 'RUNTIME.ARGUMENT_INVALID' }), + ); + }); + + it('dispatches on the textual trait', () => { + expect(findOperation(method).self).toEqual({ traits: ['textual'] }); + }); + }); + + it('ilike dispatches on the textual trait', () => { + expect(findOperation('ilike').self).toEqual({ traits: ['textual'] }); + }); + + it('registers every operation in a SQL operation registry', () => { + const registry = createSqlOperationRegistry(); + for (const [name, op] of Object.entries(operations())) { + registry.register(name, op); + } + + const entries = registry.entries(); + for (const method of ['ilike', 'fullTextMatches', 'fullTextRank', 'fullTextHeadline']) { + expect(entries[method]).toBeDefined(); + } + }); + + it('the runtime target descriptor contributes exactly these four operations', () => { + expect(Object.keys(operations()).sort()).toEqual([ + 'fullTextHeadline', + 'fullTextMatches', + 'fullTextRank', + 'ilike', + ]); + }); +}); diff --git a/packages/3-targets/6-adapters/postgres/test/descriptor-meta.test.ts b/packages/3-targets/6-adapters/postgres/test/descriptor-meta.test.ts index 9187702b7ba0..0777e0688613 100644 --- a/packages/3-targets/6-adapters/postgres/test/descriptor-meta.test.ts +++ b/packages/3-targets/6-adapters/postgres/test/descriptor-meta.test.ts @@ -1,6 +1,7 @@ import { describe, expect, it } from 'vitest'; import { postgresNativeAuthoringTypes } from '../src/core/control-mutation-defaults'; import { postgresAdapterDescriptorMeta } from '../src/core/descriptor-meta'; +import postgresRuntimeAdapterDescriptor from '../src/exports/runtime'; const storage = postgresAdapterDescriptorMeta.types.storage; @@ -253,3 +254,15 @@ describe('precision bounds agree between authoring and expansion', () => { }, ); }); + +describe('postgres adapter query operations', () => { + // Postgres built-in operations moved to @internal/target-postgres; the + // adapter contributes none, so a stale slot here would register them twice. + it('the runtime descriptor contributes no query operations', () => { + expect(postgresRuntimeAdapterDescriptor.queryOperations).toBeUndefined(); + }); + + it('the descriptor meta declares no query-operation type import', () => { + expect(postgresAdapterDescriptorMeta.types).not.toHaveProperty('queryOperationTypes'); + }); +}); From 92b11673add471f81d16c1787ac58538783c24fe Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 18 Sep 2026 14:33:59 +0200 Subject: [PATCH 02/36] feat(postgres): move built-in query operations into the target pack `@internal/target-postgres` now owns Postgres query vocabulary. `ilike` moves here unchanged, and three full-text search operations join it: `fullTextMatches`, `fullTextRank` and `fullTextHeadline`, each lowering to `websearch_to_tsquery` with the language as an inline literal checked against the configurations a stock PostgreSQL server ships with. `@internal/adapter-postgres` loses its operation surface entirely: the types file, the `./operation-types` export, the tsdown entry, the `queryOperations` slot on its runtime descriptor and its `types.queryOperationTypes` import spec. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../3-targets/3-targets/postgres/package.json | 1 + .../postgres/src/core/descriptor-meta.ts | 9 ++ .../3-targets/postgres/src/core/errors.ts | 1 + .../postgres/src/core/query-operations.ts | 131 ++++++++++++++++++ .../postgres/src/exports/operation-types.ts | 1 + .../3-targets/postgres/src/exports/runtime.ts | 4 + .../postgres/src/types/operation-types.ts | 54 ++++++++ .../postgres/test/query-operations.test.ts | 11 +- .../3-targets/postgres/tsdown.config.ts | 1 + .../6-adapters/postgres/package.json | 1 - .../postgres/src/core/descriptor-meta.ts | 36 ----- .../postgres/src/exports/operation-types.ts | 1 - .../postgres/src/exports/runtime.ts | 3 +- .../postgres/src/types/operation-types.ts | 21 --- .../6-adapters/postgres/tsdown.config.ts | 1 - 15 files changed, 212 insertions(+), 64 deletions(-) create mode 100644 packages/3-targets/3-targets/postgres/src/core/query-operations.ts create mode 100644 packages/3-targets/3-targets/postgres/src/exports/operation-types.ts create mode 100644 packages/3-targets/3-targets/postgres/src/types/operation-types.ts delete mode 100644 packages/3-targets/6-adapters/postgres/src/exports/operation-types.ts delete mode 100644 packages/3-targets/6-adapters/postgres/src/types/operation-types.ts diff --git a/packages/3-targets/3-targets/postgres/package.json b/packages/3-targets/3-targets/postgres/package.json index 50dfc37d680c..aaa27364462c 100644 --- a/packages/3-targets/3-targets/postgres/package.json +++ b/packages/3-targets/3-targets/postgres/package.json @@ -77,6 +77,7 @@ "./migration": "./dist/migration.mjs", "./native-type-normalizer": "./dist/native-type-normalizer.mjs", "./op-factory-call": "./dist/op-factory-call.mjs", + "./operation-types": "./dist/operation-types.mjs", "./pack": "./dist/pack.mjs", "./planner": "./dist/planner.mjs", "./planner-ddl-builders": "./dist/planner-ddl-builders.mjs", diff --git a/packages/3-targets/3-targets/postgres/src/core/descriptor-meta.ts b/packages/3-targets/3-targets/postgres/src/core/descriptor-meta.ts index 6bb88039954d..59aad0031456 100644 --- a/packages/3-targets/3-targets/postgres/src/core/descriptor-meta.ts +++ b/packages/3-targets/3-targets/postgres/src/core/descriptor-meta.ts @@ -30,6 +30,15 @@ const postgresTargetDescriptorMetaBase = { renderCheckExpressions: postgresRenderCheckExpressions, lowerEntityHandles: postgresLowerEntityHandles, }, + types: { + queryOperationTypes: { + import: { + package: '@internal/target-postgres/operation-types', + named: 'QueryOperationTypes', + alias: 'PgTargetQueryOps', + }, + }, + }, } as const; export const postgresTargetDescriptorMeta: typeof postgresTargetDescriptorMetaBase & { diff --git a/packages/3-targets/3-targets/postgres/src/core/errors.ts b/packages/3-targets/3-targets/postgres/src/core/errors.ts index f3853d77bc99..4293967263f5 100644 --- a/packages/3-targets/3-targets/postgres/src/core/errors.ts +++ b/packages/3-targets/3-targets/postgres/src/core/errors.ts @@ -18,6 +18,7 @@ export type PostgresTargetErrorCode = | 'MIGRATION.CONTRACT_SPACE_VIOLATION' | 'MIGRATION.POSTGRES_CONTROL_STACK_MISSING' | 'MIGRATION.TARGET_MISMATCH' + | 'RUNTIME.ARGUMENT_INVALID' | 'RUNTIME.DECODE_FAILED' | 'RUNTIME.ENCODE_FAILED' | 'RUNTIME.TEMPORAL_UNAVAILABLE' diff --git a/packages/3-targets/3-targets/postgres/src/core/query-operations.ts b/packages/3-targets/3-targets/postgres/src/core/query-operations.ts new file mode 100644 index 000000000000..85a2f11c9b8a --- /dev/null +++ b/packages/3-targets/3-targets/postgres/src/core/query-operations.ts @@ -0,0 +1,131 @@ +import { LiteralExpr } from '@internal/sql-relational-core/ast'; +import { buildOperation, toExpr } from '@internal/sql-relational-core/expression'; +import type { QueryOperationTypes } from '../types/operation-types'; +import { PG_BOOL_CODEC_ID, PG_FLOAT4_CODEC_ID, PG_TEXT_CODEC_ID } from './codec-ids'; +import { postgresError } from './errors'; + +type CodecTypesBase = Record; + +const TEXT_REF = { codecId: PG_TEXT_CODEC_ID } as const; + +/** + * The text-search configurations a stock PostgreSQL server ships with. The + * language reaches SQL as an inline literal rather than a bound parameter, so + * only names on this list may be used. + */ +export const POSTGRES_TEXT_SEARCH_LANGUAGES = [ + 'simple', + 'arabic', + 'armenian', + 'basque', + 'catalan', + 'danish', + 'dutch', + 'english', + 'finnish', + 'french', + 'german', + 'greek', + 'hindi', + 'hungarian', + 'indonesian', + 'irish', + 'italian', + 'lithuanian', + 'nepali', + 'norwegian', + 'portuguese', + 'romanian', + 'russian', + 'serbian', + 'spanish', + 'swedish', + 'tamil', + 'turkish', + 'yiddish', +] as const; + +export type FullTextSearchLanguage = (typeof POSTGRES_TEXT_SEARCH_LANGUAGES)[number]; + +export const DEFAULT_FULL_TEXT_SEARCH_LANGUAGE: FullTextSearchLanguage = 'english'; + +function languageLiteral(method: string, language: string): LiteralExpr { + if (!(POSTGRES_TEXT_SEARCH_LANGUAGES as readonly string[]).includes(language)) { + throw postgresError( + 'RUNTIME.ARGUMENT_INVALID', + `${method}: '${language}' is not a PostgreSQL text-search configuration Prisma recognizes.`, + { + why: 'The language is written into the SQL as an inline literal, not a bound parameter, so it is checked against the configurations a stock PostgreSQL server ships with.', + fix: `Pass one of: ${POSTGRES_TEXT_SEARCH_LANGUAGES.join(', ')}.`, + meta: { helper: method, argument: 'language', received: language }, + }, + ); + } + return LiteralExpr.of(language); +} + +export function postgresQueryOperations(): QueryOperationTypes { + return { + ilike: { + self: { traits: ['textual'] }, + impl: (self, pattern) => + buildOperation({ + method: 'ilike', + args: [toExpr(self), toExpr(pattern, TEXT_REF)], + returns: { codecId: PG_BOOL_CODEC_ID, nullable: false }, + lowering: { targetFamily: 'sql', strategy: 'infix', template: '{{self}} ILIKE {{arg0}}' }, + }), + }, + fullTextMatches: { + self: { traits: ['textual'] }, + impl: (self, query, language = DEFAULT_FULL_TEXT_SEARCH_LANGUAGE) => + buildOperation({ + method: 'fullTextMatches', + args: [ + toExpr(self), + toExpr(query, TEXT_REF), + languageLiteral('fullTextMatches', language), + ], + returns: { codecId: PG_BOOL_CODEC_ID, nullable: false }, + lowering: { + targetFamily: 'sql', + strategy: 'function', + template: 'to_tsvector({{arg1}}, {{self}}) @@ websearch_to_tsquery({{arg1}}, {{arg0}})', + }, + }), + }, + fullTextRank: { + self: { traits: ['textual'] }, + impl: (self, query, language = DEFAULT_FULL_TEXT_SEARCH_LANGUAGE) => + buildOperation({ + method: 'fullTextRank', + args: [toExpr(self), toExpr(query, TEXT_REF), languageLiteral('fullTextRank', language)], + returns: { codecId: PG_FLOAT4_CODEC_ID, nullable: false }, + lowering: { + targetFamily: 'sql', + strategy: 'function', + template: + 'ts_rank(to_tsvector({{arg1}}, {{self}}), websearch_to_tsquery({{arg1}}, {{arg0}}))', + }, + }), + }, + fullTextHeadline: { + self: { traits: ['textual'] }, + impl: (self, query, language = DEFAULT_FULL_TEXT_SEARCH_LANGUAGE) => + buildOperation({ + method: 'fullTextHeadline', + args: [ + toExpr(self), + toExpr(query, TEXT_REF), + languageLiteral('fullTextHeadline', language), + ], + returns: { codecId: PG_TEXT_CODEC_ID, nullable: false }, + lowering: { + targetFamily: 'sql', + strategy: 'function', + template: 'ts_headline({{arg1}}, {{self}}, websearch_to_tsquery({{arg1}}, {{arg0}}))', + }, + }), + }, + }; +} diff --git a/packages/3-targets/3-targets/postgres/src/exports/operation-types.ts b/packages/3-targets/3-targets/postgres/src/exports/operation-types.ts new file mode 100644 index 000000000000..1f13606f5910 --- /dev/null +++ b/packages/3-targets/3-targets/postgres/src/exports/operation-types.ts @@ -0,0 +1 @@ +export type { FullTextSearchLanguage, QueryOperationTypes } from '../types/operation-types'; diff --git a/packages/3-targets/3-targets/postgres/src/exports/runtime.ts b/packages/3-targets/3-targets/postgres/src/exports/runtime.ts index 0ca48451d50d..4f46aa791bdf 100644 --- a/packages/3-targets/3-targets/postgres/src/exports/runtime.ts +++ b/packages/3-targets/3-targets/postgres/src/exports/runtime.ts @@ -3,8 +3,10 @@ import type { RuntimeTargetDescriptor, RuntimeTargetInstance, } from '@internal/framework-components/execution'; +import type { SqlOperationDescriptors } from '@internal/sql-operations'; import { postgresTargetDescriptorMetaRuntime } from '../core/descriptor-meta-runtime'; import { decodePostgresListText } from '../core/list-decoder'; +import { postgresQueryOperations } from '../core/query-operations'; export { INSTANT_NOW_GENERATOR_ID, instantNow } from '../core/instant-now-generator'; export { decodePostgresListText } from '../core/list-decoder'; @@ -35,10 +37,12 @@ const postgresRuntimeTargetDescriptor: RuntimeTargetDescriptor< > & { readonly codecs: () => readonly AnyCodecDescriptor[]; readonly listDecoder: () => PostgresListDecoder; + readonly queryOperations: () => SqlOperationDescriptors; } = { ...postgresTargetDescriptorMetaRuntime, codecs: () => [], listDecoder: () => decodePostgresListText, + queryOperations: () => postgresQueryOperations(), create(): PostgresRuntimeTargetInstance { return { familyId: 'sql', diff --git a/packages/3-targets/3-targets/postgres/src/types/operation-types.ts b/packages/3-targets/3-targets/postgres/src/types/operation-types.ts new file mode 100644 index 000000000000..c800d3ade2d4 --- /dev/null +++ b/packages/3-targets/3-targets/postgres/src/types/operation-types.ts @@ -0,0 +1,54 @@ +import type { SqlQueryOperationTypes } from '@internal/sql-contract/types'; +import type { + CodecExpression, + Expression, + TraitExpression, +} from '@internal/sql-relational-core/expression'; +import type { FullTextSearchLanguage } from '../core/query-operations'; + +type CodecTypesBase = Record; + +type TextualSelfSpec = { readonly traits: readonly ['textual'] }; + +type TextualSelf = TraitExpression; + +type TextArgument = CodecExpression<'pg/text@1', false, CT>; + +export type { FullTextSearchLanguage }; + +export type QueryOperationTypes = SqlQueryOperationTypes< + CT, + { + readonly ilike: { + readonly self: TextualSelfSpec; + readonly impl: ( + self: TextualSelf, + pattern: TextArgument, + ) => Expression<{ codecId: 'pg/bool@1'; nullable: false }>; + }; + readonly fullTextMatches: { + readonly self: TextualSelfSpec; + readonly impl: ( + self: TextualSelf, + query: TextArgument, + language?: FullTextSearchLanguage, + ) => Expression<{ codecId: 'pg/bool@1'; nullable: false }>; + }; + readonly fullTextRank: { + readonly self: TextualSelfSpec; + readonly impl: ( + self: TextualSelf, + query: TextArgument, + language?: FullTextSearchLanguage, + ) => Expression<{ codecId: 'pg/float4@1'; nullable: false }>; + }; + readonly fullTextHeadline: { + readonly self: TextualSelfSpec; + readonly impl: ( + self: TextualSelf, + query: TextArgument, + language?: FullTextSearchLanguage, + ) => Expression<{ codecId: 'pg/text@1'; nullable: false }>; + }; + } +>; diff --git a/packages/3-targets/3-targets/postgres/test/query-operations.test.ts b/packages/3-targets/3-targets/postgres/test/query-operations.test.ts index 11869ee7f6ee..0976aa25cebe 100644 --- a/packages/3-targets/3-targets/postgres/test/query-operations.test.ts +++ b/packages/3-targets/3-targets/postgres/test/query-operations.test.ts @@ -3,7 +3,14 @@ import { LiteralExpr, OperationExpr, ParamRef } from '@internal/sql-relational-c import { describe, expect, it } from 'vitest'; import postgresTargetDescriptor from '../src/exports/runtime'; -const TEXT_COLUMN = ParamRef.of('body', { codec: { codecId: 'pg/text@1' } }); +const TEXT_COLUMN_AST = ParamRef.of('body', { codec: { codecId: 'pg/text@1' } }); + +// Stands in for a contract-bound text column: the operations take an +// Expression on `self` and read its AST, not a bare AST node. +const TEXT_COLUMN = { + returnType: { codecId: 'pg/text@1', nullable: false }, + buildAst: () => TEXT_COLUMN_AST, +}; function operations() { return postgresTargetDescriptor.queryOperations?.() ?? {}; @@ -74,8 +81,8 @@ describe('postgres target query operations', () => { const withDefault = buildOpAst(method, TEXT_COLUMN, 'prisma').args[1]; const withGerman = buildOpAst(method, TEXT_COLUMN, 'prisma', 'german').args[1]; + expect(withDefault?.kind).toBe('literal'); expect(withDefault).toBeInstanceOf(LiteralExpr); - expect(withDefault.kind).toBe('literal'); expect((withDefault as LiteralExpr).value).toBe('english'); expect((withGerman as LiteralExpr).value).toBe('german'); }); diff --git a/packages/3-targets/3-targets/postgres/tsdown.config.ts b/packages/3-targets/3-targets/postgres/tsdown.config.ts index 6d7b4478e39a..5393314bd0d1 100644 --- a/packages/3-targets/3-targets/postgres/tsdown.config.ts +++ b/packages/3-targets/3-targets/postgres/tsdown.config.ts @@ -18,6 +18,7 @@ export default defineConfig({ 'src/exports/migration.ts', 'src/exports/native-type-normalizer.ts', 'src/exports/op-factory-call.ts', + 'src/exports/operation-types.ts', 'src/exports/pack.ts', 'src/exports/planner-ddl-builders.ts', 'src/exports/planner-identity-values.ts', diff --git a/packages/3-targets/6-adapters/postgres/package.json b/packages/3-targets/6-adapters/postgres/package.json index a67681e94109..a2ae469b0b47 100644 --- a/packages/3-targets/6-adapters/postgres/package.json +++ b/packages/3-targets/6-adapters/postgres/package.json @@ -64,7 +64,6 @@ "./adapter": "./dist/adapter.mjs", "./column-types": "./dist/column-types.mjs", "./control": "./dist/control.mjs", - "./operation-types": "./dist/operation-types.mjs", "./runtime": "./dist/runtime.mjs", "./sql-renderer": "./dist/sql-renderer.mjs", "./types": "./dist/types.mjs", diff --git a/packages/3-targets/6-adapters/postgres/src/core/descriptor-meta.ts b/packages/3-targets/6-adapters/postgres/src/core/descriptor-meta.ts index 13a7b842a219..860b9cbcd05f 100644 --- a/packages/3-targets/6-adapters/postgres/src/core/descriptor-meta.ts +++ b/packages/3-targets/6-adapters/postgres/src/core/descriptor-meta.ts @@ -1,11 +1,4 @@ import type { CodecControlHooks, ExpandNativeTypeInput } from '@internal/family-sql/control'; -import { - buildOperation, - type CodecExpression, - type Expression, - type TraitExpression, - toExpr, -} from '@internal/sql-relational-core/expression'; import { postgresAggregateDescriptors } from '@internal/target-postgres/aggregates'; import { PG_BIT_CODEC_ID, @@ -45,7 +38,6 @@ import { SQL_VARCHAR_CODEC_ID, } from '@internal/target-postgres/codec-ids'; import { postgresCodecRegistry } from '@internal/target-postgres/codecs'; -import type { QueryOperationTypes } from '../types/operation-types'; import { adapterError } from './adapter-errors'; // ============================================================================ Helper functions for reducing boilerplate ============================================================================ @@ -149,27 +141,6 @@ const identityHooks: CodecControlHooks = { expandNativeType: ({ nativeType }) => // ============================================================================ Descriptor metadata ============================================================================ -type CodecTypesBase = Record; - -export function postgresQueryOperations(): QueryOperationTypes { - return { - ilike: { - self: { traits: ['textual'] }, - impl: ( - self: TraitExpression, - pattern: CodecExpression<'pg/text@1', false, CT>, - ): Expression<{ codecId: 'pg/bool@1'; nullable: false }> => { - return buildOperation({ - method: 'ilike', - args: [toExpr(self), toExpr(pattern, { codecId: PG_TEXT_CODEC_ID })], - returns: { codecId: PG_BOOL_CODEC_ID, nullable: false }, - lowering: { targetFamily: 'sql', strategy: 'infix', template: '{{self}} ILIKE {{arg0}}' }, - }); - }, - }, - }; -} - export const postgresAdapterDescriptorMeta = { kind: 'adapter', familyId: 'sql', @@ -349,12 +320,5 @@ export const postgresAdapterDescriptorMeta = { { typeId: PG_UUID_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'uuid' }, { typeId: PG_INET_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'inet' }, ], - queryOperationTypes: { - import: { - package: '@internal/adapter-postgres/operation-types', - named: 'QueryOperationTypes', - alias: 'PgAdapterQueryOps', - }, - }, }, } as const; diff --git a/packages/3-targets/6-adapters/postgres/src/exports/operation-types.ts b/packages/3-targets/6-adapters/postgres/src/exports/operation-types.ts deleted file mode 100644 index 38dc6e72298f..000000000000 --- a/packages/3-targets/6-adapters/postgres/src/exports/operation-types.ts +++ /dev/null @@ -1 +0,0 @@ -export type { QueryOperationTypes } from '../types/operation-types'; diff --git a/packages/3-targets/6-adapters/postgres/src/exports/runtime.ts b/packages/3-targets/6-adapters/postgres/src/exports/runtime.ts index 7d71fe06c110..8ac5cf67d1e0 100644 --- a/packages/3-targets/6-adapters/postgres/src/exports/runtime.ts +++ b/packages/3-targets/6-adapters/postgres/src/exports/runtime.ts @@ -14,7 +14,7 @@ import { } from '@internal/target-postgres/runtime'; import { createPostgresAdapterWithCodecRegistry, postgresRawCodecInferer } from '../core/adapter'; import { assemblePostgresCodecRegistry } from '../core/codec-lookup'; -import { postgresAdapterDescriptorMeta, postgresQueryOperations } from '../core/descriptor-meta'; +import { postgresAdapterDescriptorMeta } from '../core/descriptor-meta'; import type { PostgresContract, PostgresLoweredStatement } from '../core/types'; export interface SqlRuntimeAdapter @@ -49,7 +49,6 @@ const postgresRuntimeAdapterDescriptor: SqlRuntimeAdapterDescriptor<'postgres', { ...postgresAdapterDescriptorMeta, codecs: () => Array.from(postgresCodecRegistry.values()), - queryOperations: () => postgresQueryOperations(), mutationDefaultGenerators: createPostgresMutationDefaultGenerators, rawCodecInferer: postgresRawCodecInferer, create(stack): SqlRuntimeAdapter { diff --git a/packages/3-targets/6-adapters/postgres/src/types/operation-types.ts b/packages/3-targets/6-adapters/postgres/src/types/operation-types.ts deleted file mode 100644 index 8e6eb72e26ea..000000000000 --- a/packages/3-targets/6-adapters/postgres/src/types/operation-types.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { SqlQueryOperationTypes } from '@internal/sql-contract/types'; -import type { - CodecExpression, - Expression, - TraitExpression, -} from '@internal/sql-relational-core/expression'; - -type CodecTypesBase = Record; - -export type QueryOperationTypes = SqlQueryOperationTypes< - CT, - { - readonly ilike: { - readonly self: { readonly traits: readonly ['textual'] }; - readonly impl: ( - self: TraitExpression, - pattern: CodecExpression<'pg/text@1', false, CT>, - ) => Expression<{ codecId: 'pg/bool@1'; nullable: false }>; - }; - } ->; diff --git a/packages/3-targets/6-adapters/postgres/tsdown.config.ts b/packages/3-targets/6-adapters/postgres/tsdown.config.ts index 141e70a95f7c..01100c99e576 100644 --- a/packages/3-targets/6-adapters/postgres/tsdown.config.ts +++ b/packages/3-targets/6-adapters/postgres/tsdown.config.ts @@ -6,7 +6,6 @@ export default defineConfig({ 'src/exports/types.ts', 'src/exports/column-types.ts', 'src/exports/control.ts', - 'src/exports/operation-types.ts', 'src/exports/runtime.ts', 'src/exports/sql-renderer.ts', ], From 0ef894ad6f7076f9215d142680056c3bee1cfc03 Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 18 Sep 2026 14:35:36 +0200 Subject: [PATCH 03/36] docs(adr): record target-owned built-in query operations as ADR 253 ADRs 203 and 206 each gain one sentence pointing at it, since both describe built-in operations as coming from adapters and extensions. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/architecture docs/ADR-INDEX.md | 1 + ...03 - Trait-targeted operation arguments.md | 2 +- ...06 - Operations as TypeScript functions.md | 4 +- ... Target-owned built-in query operations.md | 74 +++++++++++++++++++ 4 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 docs/architecture docs/adrs/ADR 253 - Target-owned built-in query operations.md diff --git a/docs/architecture docs/ADR-INDEX.md b/docs/architecture docs/ADR-INDEX.md index 5ed3adab52fd..4a099dcbab9b 100644 --- a/docs/architecture docs/ADR-INDEX.md +++ b/docs/architecture docs/ADR-INDEX.md @@ -75,6 +75,7 @@ This document provides a comprehensive index of all Architectural Decision Recor | 203 | Trait-targeted operation arguments | Extends operation argument specs with `traits` to accept any codec carrying the required capability, alongside exact `codecId` targeting | [ADR 203 - Trait-targeted operation arguments.md](adrs/ADR%20203%20-%20Trait-targeted%20operation%20arguments.md) | | 204 | Single-tier runtime | Collapses `runtime-executor` into `framework-components`; family runtimes (`@internal/sql-runtime`, `@internal/mongo-runtime`) extend `RuntimeCore` directly via the `/runtime` subpath. Partially supersedes ADR 140's "Runtime Separation" two-tier model. | [ADR 204 - Single-tier runtime.md](adrs/ADR%20204%20-%20Single-tier%20runtime.md) | | 206 | Operations as TypeScript functions | Operations are authored as real TS functions — signature is the type surface, body builds the AST — with a minimal `self` dispatch hint for ORM column-helper reachability | [ADR 206 - Operations as TypeScript functions.md](adrs/ADR%20206%20-%20Operations%20as%20TypeScript%20functions.md) | +| 253 | Target-owned built-in query operations | Moves a target's built-in query operations out of its adapter and into the target pack; Postgres gains `fullTextMatches`, `fullTextRank` and `fullTextHeadline` over `websearch_to_tsquery` with an allowlisted language literal | [ADR 253 - Target-owned built-in query operations.md](adrs/ADR%20253%20-%20Target-owned%20built-in%20query%20operations.md) | | 210 | Prepared Statements: Author Surface and Driver SPI | Adds `runtime.prepare(declaration, callback)` (re-exposed on each DB facade as `db.prepare(...)`) and prepared execution through the existing `query()` driver SPI; lazy driver-allocated opaque handle, no global cache, cache lifetime bounded by user reference and connection. Family-level: per-driver caching strategies are out of scope here. | [ADR 210 - Prepared Statements - Author Surface and Driver SPI.md](adrs/ADR%20210%20-%20Prepared%20Statements%20-%20Author%20Surface%20and%20Driver%20SPI.md) | | 215 | Runtime middleware lifecycle: `beforeExecute` fires before `encodeParams` | Reorders the SQL family runtime so `beforeExecute` fires between `lowerToDraft` and `encodeDraftParams`, with a pre-encode `paramsMutator` over user-domain values. Extracts `runBeforeExecuteChain` from `runWithMiddleware`; `intercept` always observes a post-`beforeExecute` plan. SPI shape unchanged. | [ADR 215 - Runtime middleware lifecycle beforeExecute before encodeParams.md](adrs/ADR%20215%20-%20Runtime%20middleware%20lifecycle%20beforeExecute%20before%20encodeParams.md) | | 220 | Plan execution identity for middleware correlation | Adds `planExecutionId: string` to `RuntimeMiddlewareContext`, minted by the runtime via `crypto.randomUUID()` at the start of every runtime operation (`query`, prepared statement `query`, or `execute`). Per-operation identity (not per-plan), shared across all hooks within one operation, distinct across two operations of the same plan. Lives on the per-operation context, not on `PlanMeta`. Distinct from ADR 013's content-based `planId` and ADR 160's `groupingKey`. | [ADR 220 - Plan execution identity for middleware correlation.md](adrs/ADR%20220%20-%20Plan%20execution%20identity%20for%20middleware%20correlation.md) | diff --git a/docs/architecture docs/adrs/ADR 203 - Trait-targeted operation arguments.md b/docs/architecture docs/adrs/ADR 203 - Trait-targeted operation arguments.md index 66c68fcd87f2..ab4bcfcbc16a 100644 --- a/docs/architecture docs/adrs/ADR 203 - Trait-targeted operation arguments.md +++ b/docs/architecture docs/adrs/ADR 203 - Trait-targeted operation arguments.md @@ -2,7 +2,7 @@ ## Context -Adapters and extensions register query operations (e.g., `ilike`, `cosineDistance`) that attach to fields of a given shape. Until now an operation declared its `self` argument as a specific `codecId` — `pgvector/vector@1` for `cosineDistance`, for example. The type and runtime machinery then surfaced that operation on every field whose codec matched that ID. +Adapters and extensions register query operations (e.g., `ilike`, `cosineDistance`) that attach to fields of a given shape. (Since [ADR 253](ADR%20253%20-%20Target-owned%20built-in%20query%20operations.md), a target registers its built-in operations too — `ilike` is contributed by the Postgres target, not its adapter.) Until now an operation declared its `self` argument as a specific `codecId` — `pgvector/vector@1` for `cosineDistance`, for example. The type and runtime machinery then surfaced that operation on every field whose codec matched that ID. Codec-ID targeting works when an operation is tied to one concrete codec. It breaks down when an operation is defined by a *capability* that multiple codecs share: diff --git a/docs/architecture docs/adrs/ADR 206 - Operations as TypeScript functions.md b/docs/architecture docs/adrs/ADR 206 - Operations as TypeScript functions.md index fc0b944d02f3..1f1aad8e8fd7 100644 --- a/docs/architecture docs/adrs/ADR 206 - Operations as TypeScript functions.md +++ b/docs/architecture docs/adrs/ADR 206 - Operations as TypeScript functions.md @@ -2,7 +2,7 @@ ## Context -Operations contributed by adapters and extensions — `ilike`, `cosineDistance`, and any future operator — are described to the framework by a declarative record: an argument list in which each argument targets a codec by identity or by trait, a return codec, and a lowering spec. The framework reads that record, derives call signatures for the SQL builder's `fns` surface and the ORM column helper, and wraps user-supplied values as parameter references using the codec identity on each argument position. +Operations contributed by targets, adapters and extensions — `ilike`, `cosineDistance`, and any future operator — are described to the framework by a declarative record: an argument list in which each argument targets a codec by identity or by trait, a return codec, and a lowering spec. The framework reads that record, derives call signatures for the SQL builder's `fns` surface and the ORM column helper, and wraps user-supplied values as parameter references using the codec identity on each argument position. The shape of that record is a closed structure. It can say "this argument accepts any expression of codec X" or "of any codec with traits T", and nothing else. It cannot express a generic tying two argument codecs together, a non-database TypeScript type such as a numeric dimension or an option bag, a conditional return codec that depends on the argument codec, or a method overload. Every operation is forced into the single shape that the records can describe. Extensions that want more do not have a way to ask for it. @@ -37,7 +37,7 @@ The distinction between predicate operations (return a boolean, composable insid ## Interaction with other subsystems - **Operation arguments.** [ADR 203](ADR%20203%20-%20Trait-targeted%20operation%20arguments.md) introduced codec-identity and trait-set targeting for argument specs. The primitive survives — the self hint uses the same vocabulary — but it now applies only to the ORM column-helper dispatch. The SQL builder no longer reads argument specs; it calls the authored function directly. -- **Adapter SPI.** [ADR 016](ADR%20016%20-%20Adapter%20SPI%20for%20Lowering.md) described how adapters contribute lowering. The adapter runtime descriptor's `queryOperations` slot now yields a factory rather than a const array. The contract-assembly layer calls the factory with the contract's codec-types map. +- **Adapter SPI.** [ADR 016](ADR%20016%20-%20Adapter%20SPI%20for%20Lowering.md) described how adapters contribute lowering. The adapter runtime descriptor's `queryOperations` slot now yields a factory rather than a const array. The contract-assembly layer calls the factory with the contract's codec-types map. [ADR 253](ADR%20253%20-%20Target-owned%20built-in%20query%20operations.md) then moved a target's built-in operations off the adapter and onto the target descriptor's identical slot. - **Codec registry.** [ADR 030](ADR%20030%20-%20Result%20decoding%20%26%20codecs%20registry.md) defines codec metadata including traits. The ORM column helper continues to read traits from the registry to expand trait-targeted self hints. Codec-types flow from the same registry into the contract and onward into each operation factory. - **Extension compatibility.** [ADR 017](ADR%20017%20-%20Extension%20Compatibility%20Policy.md) is honoured: old declarative operation records are not retained, so the decision is a breaking change for extensions that ship their own operation contributions. The breakage is local — each extension rewrites its operation contribution at the factory boundary, without changes elsewhere in the authoring surface. diff --git a/docs/architecture docs/adrs/ADR 253 - Target-owned built-in query operations.md b/docs/architecture docs/adrs/ADR 253 - Target-owned built-in query operations.md new file mode 100644 index 000000000000..e552b813f57c --- /dev/null +++ b/docs/architecture docs/adrs/ADR 253 - Target-owned built-in query operations.md @@ -0,0 +1,74 @@ +# ADR 253 — Target-owned built-in query operations + +**Status:** Accepted + +**Related:** [ADR 005 — Thin core, fat targets](ADR%20005%20-%20Thin%20Core%20Fat%20Targets.md) draws the line between what a target knows and what an adapter does. [ADR 016 — Adapter SPI for Lowering](ADR%20016%20-%20Adapter%20SPI%20for%20Lowering.md) makes the adapter responsible for turning an AST into a statement. [ADR 206 — Operations as TypeScript functions](ADR%20206%20-%20Operations%20as%20TypeScript%20functions.md) defines how an operation is authored. [ADR 251 — Target-owned Postgres list framing](ADR%20251%20-%20Target-owned%20Postgres%20list%20framing.md) is the precedent for moving Postgres semantics out of the adapter. + +--- + +## Context + +Postgres has always shipped one built-in query operation, `ilike`, and it lived in `@internal/adapter-postgres`. The adapter was the only Postgres component with a `queryOperations` slot at the time, so that is where it went. + +That placement says the wrong thing about ownership. `ILIKE` is not a lowering decision. It is part of the Postgres query language, known before anything is executed and true no matter which driver or adapter carries the statement to the server. The adapter's job, per ADR 016, is to render an AST and bind its parameters; deciding that Postgres spells case-insensitive matching `ILIKE` is the target's job, per ADR 005. + +The placement also leaks into generated code. Every emitted Postgres `contract.d.ts` named `@internal/adapter-postgres/operation-types` in an import, so an application's contract types depended on the adapter package for vocabulary the target defines. + +Adding full-text search made the mismatch concrete. `to_tsvector`, `websearch_to_tsquery`, `ts_rank` and `ts_headline` are Postgres functions with Postgres semantics — including the set of text-search configurations a server ships with. None of that is adapter knowledge. + +## Decision + +Built-in query operations for a target live in the target package. For Postgres that is `@internal/target-postgres`, which now contributes `ilike`, `fullTextMatches`, `fullTextRank` and `fullTextHeadline`. `@internal/adapter-postgres` contributes no query operations at all; its `operation-types` export and the `queryOperations` slot on its runtime descriptor are removed rather than kept as forwarding shims. + +Nothing in the framework had to change to allow this. `SqlStaticContributions.queryOperations` is already optional on every SQL component, `createSqlExecutionStack` already iterates the target alongside the adapter and the extensions, and `extractQueryOperationTypeImports` already reads `types.queryOperationTypes` from every descriptor in the stack. The target simply fills slots it had left empty. + +Extensions are unaffected. An extension pack still contributes its own operations the same way; the change is only about where a *target's built-in* vocabulary lives. Adapters keep the ability to contribute operations — a genuinely adapter-specific operation is still legal — but Postgres no longer has one. + +The three full-text operations follow ADR 206: each is a TypeScript function whose signature is its type-level surface. They dispatch on `self: { traits: ['textual'] }`, so they appear on any textual column, exactly as `ilike` does. The search string is bound as a `pg/text@1` parameter. The language is a second, optional argument defaulting to `'english'`, and it is written into the SQL as an inline literal rather than a parameter, because Postgres will not accept a parameter in the configuration position of `to_tsvector`. An inline literal has to be trustworthy, so the language is checked against the configurations a stock PostgreSQL server ships with, and anything else throws `RUNTIME.ARGUMENT_INVALID` before a statement is built. + +`websearch_to_tsquery` is the only query parser used. It accepts the syntax an application's users already type — quoted phrases, `-word` to exclude, `or` between terms — and it does not raise a syntax error on arbitrary input, which `to_tsquery` does. + +## Consequences + +Emitted Postgres `contract.d.ts` files change: they import `QueryOperationTypes` from `@internal/target-postgres/operation-types` under the alias `PgTargetQueryOps` instead of from the adapter under `PgAdapterQueryOps`. `contract.json` does not change, and no contract hash moves. An application regenerates its contract types and keeps working. + +An extension or application that imported `@internal/adapter-postgres/operation-types` directly must import `@internal/target-postgres/operation-types` instead. There is no compatibility re-export, per `no-backward-compatibility.mdc`. + +Full-text search needs no new codec, no capability key and no extension. `tsvector` and `tsquery` never leave the server — they are constructed and consumed inside a single expression — so nothing has to cross the wire in a shape the codec registry does not already know. + +Performance is the application's responsibility, because the operation does not create indexes. `fullTextMatches` renders `to_tsvector('', "")`, so a GIN index that is to answer the predicate must declare exactly that expression: + +```prisma +@@index(expression: "to_tsvector('english', \"text\")", type: "gin", name: "message_text_search") +``` + +An index whose expression differs — a different language, or a `tsvector` column maintained by a trigger — will not be used. + +The set of accepted languages is a hand-maintained list. A server with a custom text-search configuration installed cannot name it. That is the price of keeping the language out of the parameter list; widening it later means deciding how Prisma learns what a given server has configured, which is a question this decision does not answer. + +## Implementation anchors + +- The operations and the language list: [`query-operations.ts`](../../../packages/3-targets/3-targets/postgres/src/core/query-operations.ts). +- Their type-level surface, re-exported as the package's `./operation-types` entry: [`operation-types.ts`](../../../packages/3-targets/3-targets/postgres/src/types/operation-types.ts). +- The runtime target descriptor that contributes them: [`runtime.ts`](../../../packages/3-targets/3-targets/postgres/src/exports/runtime.ts). +- The import spec the emitter writes into `contract.d.ts`: [`descriptor-meta.ts`](../../../packages/3-targets/3-targets/postgres/src/core/descriptor-meta.ts). +- The contributor loop that registers every component's operations: [`sql-context.ts`](../../../packages/2-sql/5-runtime/src/sql-context.ts). +- The control-plane collection of type imports: [`control-stack.ts`](../../../packages/1-framework/1-core/framework-components/src/control/control-stack.ts). + +## Alternatives considered + +### Leave the operations in the adapter and add full-text search there + +Rejected. It keeps `ILIKE` and `to_tsvector` — plain Postgres language — inside the component whose stated job is rendering and transport, and it keeps every generated contract depending on the adapter package for vocabulary the target defines. ADR 251 already moved Postgres list semantics out of the adapter for the same reason. + +### Ship full-text search as an extension pack + +Rejected. An extension exists for things a server may or may not have: `pgvector`, `postgis`, ParadeDB's `bm25`. Full-text search is in core PostgreSQL and has been for many releases. Requiring an install step for it would misrepresent what an application has to do. + +### Accept any string as the language + +Rejected. The language is interpolated into the SQL rather than bound, so an unchecked string is a SQL-injection hole on any path where the value is not a compile-time constant. The allowlist is the smallest thing that makes the inline literal safe. + +### Use `to_tsquery` or `plainto_tsquery` + +Rejected. `to_tsquery` raises a syntax error on ordinary user input, which turns a search box into a source of failed queries. `plainto_tsquery` is safe but throws away the operators users expect — quoted phrases and negation. `websearch_to_tsquery` is forgiving and supports both. From 559c835aa8f2825d65bde056e65e485cfa379673 Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 18 Sep 2026 14:43:56 +0200 Subject: [PATCH 04/36] refactor(publish-surface): point query-operation type imports at the target The Postgres facade now republishes `@internal/target-postgres/operation-types` as `@prisma/orm-postgres/target/operation-types`, which is the subpath emitted `contract.d.ts` files name after D1 moved the operations into the target pack. The adapter subpath disappears from both shell manifests, which the shell build regenerates. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- packages/0-config/tsdown/shell-testkit.ts | 2 +- packages/0-shared/publish-surface/src/shells.ts | 1 + .../publish-surface/test/consumer-surface.test.ts | 2 +- .../publish-surface/test/import-roots.test.ts | 4 ++-- .../3-tooling/emitter/test/import-roots.test.ts | 8 ++++---- .../scripts/strip-pgvector-fixture.mjs | 3 +-- packages/9-public/@prisma/orm-postgres/package.json | 2 +- .../@prisma/orm-target-postgres/package.json | 2 +- ... => emitter.target-query-operation-types.test.ts} | 12 ++++++------ 9 files changed, 18 insertions(+), 18 deletions(-) rename test/integration/test/{emitter.adapter-query-operation-types.test.ts => emitter.target-query-operation-types.test.ts} (79%) diff --git a/packages/0-config/tsdown/shell-testkit.ts b/packages/0-config/tsdown/shell-testkit.ts index caf1ba4acb1c..5ee17901e729 100644 --- a/packages/0-config/tsdown/shell-testkit.ts +++ b/packages/0-config/tsdown/shell-testkit.ts @@ -326,7 +326,6 @@ function shellMapModules(installedPackageDir: string): ReadonlySet { export const knownInternalNamesInDist: readonly string[] = [ '@internal/*', '@internal/adapter-mongo/codec-types', - '@internal/adapter-postgres/operation-types', '@internal/adapter-sqlite/codec-types', '@internal/cli', '@internal/cli-telemetry', @@ -379,6 +378,7 @@ export const knownInternalNamesInDist: readonly string[] = [ '@internal/target-postgres/codec-types', '@internal/target-postgres/codecs', '@internal/target-postgres/errors', + '@internal/target-postgres/operation-types', '@internal/target-sqlite', '@internal/target-sqlite/errors', '@internal/utils', diff --git a/packages/0-shared/publish-surface/src/shells.ts b/packages/0-shared/publish-surface/src/shells.ts index bc5e3330605e..eba28a3f7f00 100644 --- a/packages/0-shared/publish-surface/src/shells.ts +++ b/packages/0-shared/publish-surface/src/shells.ts @@ -640,6 +640,7 @@ export const publicShells: ReadonlyMap = new Map< 'migration', 'native-type-normalizer', 'op-factory-call', + 'operation-types', 'pack', 'planner', 'planner-ddl-builders', diff --git a/packages/0-shared/publish-surface/test/consumer-surface.test.ts b/packages/0-shared/publish-surface/test/consumer-surface.test.ts index d31f064bea4e..d510f2a14f34 100644 --- a/packages/0-shared/publish-surface/test/consumer-surface.test.ts +++ b/packages/0-shared/publish-surface/test/consumer-surface.test.ts @@ -106,9 +106,9 @@ describe('the published surface against the applications that will consume it', '@internal/framework-components/control', '@internal/sql-contract/types', '@internal/mongo-contract', - '@internal/adapter-postgres/operation-types', '@internal/adapter-mongo/codec-types', '@internal/target-postgres/codec-types', + '@internal/target-postgres/operation-types', '@internal/postgres/migration', '@internal/sqlite/migration', '@internal/target-mongo/migration', diff --git a/packages/0-shared/publish-surface/test/import-roots.test.ts b/packages/0-shared/publish-surface/test/import-roots.test.ts index 74ed3964dcaa..a6cb8c574ea8 100644 --- a/packages/0-shared/publish-surface/test/import-roots.test.ts +++ b/packages/0-shared/publish-surface/test/import-roots.test.ts @@ -49,8 +49,8 @@ describe('resolveImportSpecifier', () => { '@prisma/orm-postgres/target/codec-types', ); expect( - resolveImportSpecifier('@internal/adapter-postgres/operation-types', postgresFacade), - ).toBe('@prisma/orm-postgres/adapter/operation-types'); + resolveImportSpecifier('@internal/target-postgres/operation-types', postgresFacade), + ).toBe('@prisma/orm-postgres/target/operation-types'); }); it('resolves the facade package itself to the facade shell', () => { diff --git a/packages/2-sql/3-tooling/emitter/test/import-roots.test.ts b/packages/2-sql/3-tooling/emitter/test/import-roots.test.ts index a732daf6e0f1..b475b666df6f 100644 --- a/packages/2-sql/3-tooling/emitter/test/import-roots.test.ts +++ b/packages/2-sql/3-tooling/emitter/test/import-roots.test.ts @@ -35,7 +35,7 @@ const codecTypeImports: TypesImportSpec[] = [ ]; const queryOperationTypeImports: TypesImportSpec[] = [ { - package: '@internal/adapter-postgres/operation-types', + package: '@internal/target-postgres/operation-types', named: 'QueryOperationTypes', alias: 'PgQueryOps', }, @@ -82,21 +82,21 @@ function emit(root: ImportRoot): string { describe('emitted contract types under each import root', () => { it('names workspace packages under the internal root', () => { expect(importedSpecifiers(emit(internalImportRoot)).sort()).toEqual([ - '@internal/adapter-postgres/operation-types', '@internal/contract/types', '@internal/extension-pgvector/codec-types', '@internal/sql-contract/types', '@internal/target-postgres/codec-types', + '@internal/target-postgres/operation-types', ]); }); it('names the facade and the extension pack under the facade root', () => { expect(importedSpecifiers(emit(postgresFacade)).sort()).toEqual([ '@prisma/orm-extension-pgvector/codec-types', - '@prisma/orm-postgres/adapter/operation-types', '@prisma/orm-postgres/contract/types', '@prisma/orm-postgres/family-contract/types', '@prisma/orm-postgres/target/codec-types', + '@prisma/orm-postgres/target/operation-types', ]); }); @@ -105,8 +105,8 @@ describe('emitted contract types under each import root', () => { '@prisma/orm-extension-pgvector/codec-types', '@prisma/orm-family-sql/contract/types', '@prisma/orm-framework/contract/types', - '@prisma/orm-target-postgres/adapter/operation-types', '@prisma/orm-target-postgres/target/codec-types', + '@prisma/orm-target-postgres/target/operation-types', ]); }); diff --git a/packages/3-extensions/sql-orm-client/scripts/strip-pgvector-fixture.mjs b/packages/3-extensions/sql-orm-client/scripts/strip-pgvector-fixture.mjs index bdfb1e5ab6bd..d225da4da819 100644 --- a/packages/3-extensions/sql-orm-client/scripts/strip-pgvector-fixture.mjs +++ b/packages/3-extensions/sql-orm-client/scripts/strip-pgvector-fixture.mjs @@ -33,10 +33,9 @@ const source = readFileSync(target, 'utf8'); * be. That is not something this script should care about. */ const importBlock = - /import type \{ QueryOperationTypes as PgAdapterQueryOps \} from '@internal\/adapter-postgres\/operation-types';\nimport type \{[\s\S]*?\} from '@internal\/extension-pgvector\/codec-types';\nimport type \{ QueryOperationTypes as PgVectorQueryOperationTypes \} from '@internal\/extension-pgvector\/operation-types';/; + /import type \{[^}]*\} from '@internal\/extension-pgvector\/codec-types';\nimport type \{ QueryOperationTypes as PgVectorQueryOperationTypes \} from '@internal\/extension-pgvector\/operation-types';/; const replacement = [ - "import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types';", '// pgvector types replaced with local aliases (see note above)', 'type PgVectorTypes = object;', 'type Vector<_N extends number> = number[];', diff --git a/packages/9-public/@prisma/orm-postgres/package.json b/packages/9-public/@prisma/orm-postgres/package.json index 556191a119fc..06dd5dc0e0a6 100644 --- a/packages/9-public/@prisma/orm-postgres/package.json +++ b/packages/9-public/@prisma/orm-postgres/package.json @@ -48,7 +48,6 @@ "./adapter/adapter": "./dist/adapter__adapter.mjs", "./adapter/column-types": "./dist/adapter__column-types.mjs", "./adapter/control": "./dist/adapter__control.mjs", - "./adapter/operation-types": "./dist/adapter__operation-types.mjs", "./adapter/runtime": "./dist/adapter__runtime.mjs", "./adapter/sql-renderer": "./dist/adapter__sql-renderer.mjs", "./adapter/types": "./dist/adapter__types.mjs", @@ -150,6 +149,7 @@ "./target/migration": "./dist/target__migration.mjs", "./target/native-type-normalizer": "./dist/target__native-type-normalizer.mjs", "./target/op-factory-call": "./dist/target__op-factory-call.mjs", + "./target/operation-types": "./dist/target__operation-types.mjs", "./target/pack": "./dist/target__pack.mjs", "./target/planner": "./dist/target__planner.mjs", "./target/planner-ddl-builders": "./dist/target__planner-ddl-builders.mjs", diff --git a/packages/9-public/@prisma/orm-target-postgres/package.json b/packages/9-public/@prisma/orm-target-postgres/package.json index 95901c653bdc..aca796ac2f29 100644 --- a/packages/9-public/@prisma/orm-target-postgres/package.json +++ b/packages/9-public/@prisma/orm-target-postgres/package.json @@ -50,7 +50,6 @@ "./adapter/adapter": "./dist/adapter__adapter.mjs", "./adapter/column-types": "./dist/adapter__column-types.mjs", "./adapter/control": "./dist/adapter__control.mjs", - "./adapter/operation-types": "./dist/adapter__operation-types.mjs", "./adapter/runtime": "./dist/adapter__runtime.mjs", "./adapter/sql-renderer": "./dist/adapter__sql-renderer.mjs", "./adapter/types": "./dist/adapter__types.mjs", @@ -74,6 +73,7 @@ "./target/migration": "./dist/target__migration.mjs", "./target/native-type-normalizer": "./dist/target__native-type-normalizer.mjs", "./target/op-factory-call": "./dist/target__op-factory-call.mjs", + "./target/operation-types": "./dist/target__operation-types.mjs", "./target/pack": "./dist/target__pack.mjs", "./target/planner": "./dist/target__planner.mjs", "./target/planner-ddl-builders": "./dist/target__planner-ddl-builders.mjs", diff --git a/test/integration/test/emitter.adapter-query-operation-types.test.ts b/test/integration/test/emitter.target-query-operation-types.test.ts similarity index 79% rename from test/integration/test/emitter.adapter-query-operation-types.test.ts rename to test/integration/test/emitter.target-query-operation-types.test.ts index 2f0d87291988..54ecfb5af123 100644 --- a/test/integration/test/emitter.adapter-query-operation-types.test.ts +++ b/test/integration/test/emitter.target-query-operation-types.test.ts @@ -1,16 +1,16 @@ -import postgresAdapter from '@internal/adapter-postgres/control'; import type { Contract } from '@internal/contract/types'; import { generateContractDts } from '@internal/emitter'; import { extractQueryOperationTypeImports } from '@internal/framework-components/control'; import { UNBOUND_NAMESPACE_ID } from '@internal/framework-components/ir'; import type { SqlStorage } from '@internal/sql-contract/types'; import { sqlEmission } from '@internal/sql-contract-emitter'; +import postgresTarget from '@internal/target-postgres/control'; import { postgresCreateNamespace } from '@internal/target-postgres/types'; import { applicationDomainOf } from '@repo/test-utils'; import { describe, expect, it } from 'vitest'; -describe('emitter + postgres adapter descriptor', () => { - it('surfaces adapter-declared queryOperationTypes.import in generated contract.d.ts', () => { +describe('emitter + postgres target descriptor', () => { + it('surfaces target-declared queryOperationTypes.import in generated contract.d.ts', () => { const ir: Contract = { target: 'postgres', targetFamily: 'sql', @@ -30,7 +30,7 @@ describe('emitter + postgres adapter descriptor', () => { profileHash: 'profile:test' as never, meta: {}, }; - const queryOperationTypeImports = extractQueryOperationTypeImports([postgresAdapter]); + const queryOperationTypeImports = extractQueryOperationTypeImports([postgresTarget]); const types = generateContractDts( ir, @@ -41,8 +41,8 @@ describe('emitter + postgres adapter descriptor', () => { ); expect(types).toContain( - "import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'", + "import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'", ); - expect(types).toContain('export type QueryOperationTypes = PgAdapterQueryOps'); + expect(types).toContain('export type QueryOperationTypes = PgTargetQueryOps'); }); }); From b4034545c476695197ffab24773ea2e8867411a9 Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 18 Sep 2026 14:47:41 +0200 Subject: [PATCH 05/36] chore(fixtures): regenerate emitted contract types for the target operations `pnpm fixtures:emit` output only. Every emitted Postgres `contract.d.ts` now imports `QueryOperationTypes` from the target as `PgTargetQueryOps`; nothing else in these files moved. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- apps/telemetry-backend/src/prisma/contract.d.ts | 4 ++-- examples/bundle-size/src/postgres/generated/contract.d.ts | 4 ++-- examples/multi-extension-monorepo/app/src/contract.d.ts | 4 ++-- .../contract.d.ts | 4 ++-- .../multi-extension-monorepo/packages/audit/src/contract.d.ts | 4 ++-- .../contract.d.ts | 4 ++-- .../packages/feature-flags/src/contract.d.ts | 4 ++-- examples/paradedb-demo/src/prisma/contract.d.ts | 4 ++-- examples/prisma-8-cloudflare-worker/src/prisma/contract.d.ts | 4 ++-- .../contract.d.ts | 4 ++-- .../contract.d.ts | 4 ++-- .../contract.d.ts | 4 ++-- examples/prisma-8-demo/src/prisma/contract.d.ts | 4 ++-- .../contract.d.ts | 4 ++-- examples/prisma-8-postgis-demo/src/prisma/contract.d.ts | 4 ++-- examples/prisma7-adoption/generated/prisma8/contract.d.ts | 4 ++-- examples/react-router-demo/src/prisma/contract.d.ts | 4 ++-- examples/supabase/src/contract.d.ts | 4 ++-- .../4-lanes/sql-builder/test/fixtures/generated/contract.d.ts | 4 ++-- .../contract.d.ts | 4 ++-- packages/3-extensions/paradedb/src/contract.d.ts | 4 ++-- .../contract.d.ts | 4 ++-- packages/3-extensions/pgvector/src/contract.d.ts | 4 ++-- .../contract.d.ts | 4 ++-- packages/3-extensions/postgis/src/contract.d.ts | 4 ++-- .../postgres/test/fixtures/generated/contract.d.ts | 4 ++-- .../sql-orm-client/test/fixtures/generated/contract.d.ts | 4 ++-- .../test/fixtures/junction-namespaces/generated/contract.d.ts | 4 ++-- packages/3-extensions/supabase/src/contract/contract.d.ts | 4 ++-- .../supabase/test/fixtures/example-app/contract.d.ts | 4 ++-- .../supabase/test/fixtures/no-policy/contract.d.ts | 4 ++-- .../supabase/test/fixtures/renamed-policy/contract.d.ts | 4 ++-- test/e2e/framework/test/fixtures/generated/contract.d.ts | 4 ++-- .../test/enum-order-by/_fixture/generated/contract.d.ts | 4 ++-- test/integration/test/fixtures/contract.d.ts | 4 ++-- .../namespaced-accessors/fixtures/generated/contract.d.ts | 4 ++-- .../aggregation/avg/_fixture/decimal/generated/contract.d.ts | 4 ++-- .../aggregation/avg/_fixture/numeric/generated/contract.d.ts | 4 ++-- .../aggregation/count/_fixture/generated/contract.d.ts | 4 ++-- .../group_by/_fixture/main/generated/contract.d.ts | 4 ++-- .../_fixture/regression-21789/generated/contract.d.ts | 4 ++-- .../group_by_having/_fixture/common/generated/contract.d.ts | 4 ++-- .../group_by_having/_fixture/decimal/generated/contract.d.ts | 4 ++-- .../_fixture/compound/generated/contract.d.ts | 4 ++-- .../many_count_relation/_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/nested/generated/contract.d.ts | 4 ++-- .../many_count_relation/_fixture/self/generated/contract.d.ts | 4 ++-- .../aggregation/max/_fixture/common/generated/contract.d.ts | 4 ++-- .../aggregation/max/_fixture/decimal/generated/contract.d.ts | 4 ++-- .../aggregation/min/_fixture/common/generated/contract.d.ts | 4 ++-- .../aggregation/min/_fixture/decimal/generated/contract.d.ts | 4 ++-- .../aggregation/sum/_fixture/decimal/generated/contract.d.ts | 4 ++-- .../aggregation/sum/_fixture/numeric/generated/contract.d.ts | 4 ++-- .../uniq-count-relation/_fixture/base/generated/contract.d.ts | 4 ++-- .../_fixture/nested/generated/contract.d.ts | 4 ++-- .../data_types/bigint/_fixture/generated/contract.d.ts | 4 ++-- .../queries/data_types/bool/_fixture/generated/contract.d.ts | 4 ++-- .../bytes/_fixture/relations/generated/contract.d.ts | 4 ++-- .../data_types/bytes/_fixture/scalars/generated/contract.d.ts | 4 ++-- .../data_types/datetime/_fixture/generated/contract.d.ts | 4 ++-- .../data_types/decimal/_fixture/generated/contract.d.ts | 4 ++-- .../enum_type/_fixture/postgres/generated/contract.d.ts | 4 ++-- .../queries/data_types/float/_fixture/generated/contract.d.ts | 4 ++-- .../queries/data_types/int/_fixture/generated/contract.d.ts | 4 ++-- .../data_types/json/_fixture/scalar/generated/contract.d.ts | 4 ++-- .../native/postgres/_fixture/other/generated/contract.d.ts | 4 ++-- .../native/postgres/_fixture/string/generated/contract.d.ts | 4 ++-- .../data_types/string/_fixture/generated/contract.d.ts | 4 ++-- .../through_relation/_fixture/common/generated/contract.d.ts | 4 ++-- .../through_relation/_fixture/decimal/generated/contract.d.ts | 4 ++-- .../through_relation/_fixture/enum/generated/contract.d.ts | 4 ++-- .../through_relation/_fixture/json/generated/contract.d.ts | 4 ++-- .../through_relation/_fixture/lists/generated/contract.d.ts | 4 ++-- .../engines/queries/distinct/_fixture/generated/contract.d.ts | 4 ++-- .../filters/bigint_filter/_fixture/generated/contract.d.ts | 4 ++-- .../filters/bytes_filter/_fixture/generated/contract.d.ts | 4 ++-- .../filters/decimal_filter/_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/decimal-list/generated/contract.d.ts | 4 ++-- .../field_reference/_fixture/enum/generated/contract.d.ts | 4 ++-- .../field_reference/_fixture/list/generated/contract.d.ts | 4 ++-- .../field_reference/_fixture/mixed/generated/contract.d.ts | 4 ++-- .../bigint_filter/_fixture/generated/contract.d.ts | 4 ++-- .../bytes_filter/_fixture/generated/contract.d.ts | 4 ++-- .../datetime_filter/_fixture/generated/contract.d.ts | 4 ++-- .../decimal_filter/_fixture/generated/contract.d.ts | 4 ++-- .../failure/_fixture/common/generated/contract.d.ts | 4 ++-- .../failure/_fixture/default/generated/contract.d.ts | 4 ++-- .../failure/_fixture/list/generated/contract.d.ts | 4 ++-- .../float_filter/_fixture/generated/contract.d.ts | 4 ++-- .../having_filter/_fixture/generated/contract.d.ts | 4 ++-- .../int_filter/_fixture/generated/contract.d.ts | 4 ++-- .../json_filter/_fixture/generated/contract.d.ts | 4 ++-- .../json_filter/_fixture/list/generated/contract.d.ts | 4 ++-- .../relation_filter/_fixture/complex/generated/contract.d.ts | 4 ++-- .../_fixture/one-to-many/generated/contract.d.ts | 4 ++-- .../_fixture/one-to-one-list/generated/contract.d.ts | 4 ++-- .../_fixture/one-to-one/generated/contract.d.ts | 4 ++-- .../string_filter/_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/compound-one-to-many/generated/contract.d.ts | 4 ++-- .../_fixture/many-to-many/generated/contract.d.ts | 4 ++-- .../_fixture/one-to-many/generated/contract.d.ts | 4 ++-- .../queries/filters/filters/_fixture/generated/contract.d.ts | 4 ++-- .../filters/json/_fixture/optional/generated/contract.d.ts | 4 ++-- .../list_filters/_fixture/base/generated/contract.d.ts | 4 ++-- .../list_filters/_fixture/decimal/generated/contract.d.ts | 4 ++-- .../list_filters/_fixture/json/generated/contract.d.ts | 4 ++-- .../many_relation/_fixture/25103/generated/contract.d.ts | 4 ++-- .../many_relation/_fixture/l2-to-one/generated/contract.d.ts | 4 ++-- .../one2one_regression/_fixture/generated/contract.d.ts | 4 ++-- .../one_relation/_fixture/21356/generated/contract.d.ts | 4 ++-- .../one_relation/_fixture/21366/generated/contract.d.ts | 4 ++-- .../batching-bigint/_fixture/generated/contract.d.ts | 4 ++-- .../batching-bytes/_fixture/generated/contract.d.ts | 4 ++-- .../functional/blog-update/_fixture/generated/contract.d.ts | 4 ++-- .../functional/bytes-upsert/_fixture/generated/contract.d.ts | 4 ++-- .../chunking-query/_fixture/generated/contract.d.ts | 4 ++-- .../create-default-date/_fixture/generated/contract.d.ts | 4 ++-- .../functional/decimal-list/_fixture/generated/contract.d.ts | 4 ++-- .../decimal-precision/_fixture/generated/contract.d.ts | 4 ++-- .../decimal-scalar/_fixture/generated/contract.d.ts | 4 ++-- .../default-selection/_fixture/generated/contract.d.ts | 4 ++-- .../functional/distinct/_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../functional/enum-array/_fixture/generated/contract.d.ts | 4 ++-- .../extended-where/_fixture/generated/contract.d.ts | 4 ++-- .../filter-count-relations/_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../handle-int-overflow/_fixture/generated/contract.d.ts | 4 ++-- .../interactive-transactions/_fixture/generated/contract.d.ts | 4 ++-- .../functional/issues-11974/_fixture/generated/contract.d.ts | 4 ++-- .../functional/issues-12378/_fixture/generated/contract.d.ts | 4 ++-- .../functional/issues-12557/_fixture/generated/contract.d.ts | 4 ++-- .../functional/issues-12572/_fixture/generated/contract.d.ts | 4 ++-- .../functional/issues-14271/_fixture/generated/contract.d.ts | 4 ++-- .../issues-14954-date-batch/_fixture/generated/contract.d.ts | 4 ++-- .../functional/issues-15044/_fixture/generated/contract.d.ts | 4 ++-- .../issues-16535-select-enum/_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../functional/issues-23902/_fixture/generated/contract.d.ts | 4 ++-- .../functional/issues-25404/_fixture/generated/contract.d.ts | 4 ++-- .../issues-27455-bytes-id/_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../functional/issues-4004/_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../functional/json-fields/_fixture/generated/contract.d.ts | 4 ++-- .../functional/large-floats/_fixture/generated/contract.d.ts | 4 ++-- .../legacy-aggregations/_fixture/generated/contract.d.ts | 4 ++-- .../functional/legacy-json/_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../functional/methods-count/_fixture/generated/contract.d.ts | 4 ++-- .../methods-createMany/_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../methods-findFirstOrThrow/_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../methods-upsert-simple/_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/different-names/generated/contract.d.ts | 4 ++-- .../_fixture/identical-names/generated/contract.d.ts | 4 ++-- .../multi-schema/_fixture/no-map/generated/contract.d.ts | 4 ++-- .../multiple-types/_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/generated/contract.d.ts | 4 ++-- .../_fixture/cascade-map/generated/contract.d.ts | 4 ++-- .../_fixture/cascade-plain/generated/contract.d.ts | 4 ++-- .../_fixture/noaction-map/generated/contract.d.ts | 4 ++-- .../_fixture/noaction-plain/generated/contract.d.ts | 4 ++-- .../_fixture/restrict-map/generated/contract.d.ts | 4 ++-- .../_fixture/restrict-plain/generated/contract.d.ts | 4 ++-- .../_fixture/setnull-map/generated/contract.d.ts | 4 ++-- .../_fixture/setnull-plain/generated/contract.d.ts | 4 ++-- .../_fixture/cascade-map/generated/contract.d.ts | 4 ++-- .../_fixture/cascade-plain/generated/contract.d.ts | 4 ++-- .../_fixture/noaction-map/generated/contract.d.ts | 4 ++-- .../_fixture/noaction-plain/generated/contract.d.ts | 4 ++-- .../_fixture/restrict-map/generated/contract.d.ts | 4 ++-- .../_fixture/restrict-plain/generated/contract.d.ts | 4 ++-- .../_fixture/setnull-map/generated/contract.d.ts | 4 ++-- .../_fixture/setnull-plain/generated/contract.d.ts | 4 ++-- .../_fixture/cascade-nomap/generated/contract.d.ts | 4 ++-- .../_fixture/default-nomap/generated/contract.d.ts | 4 ++-- .../_fixture/noaction-nomap/generated/contract.d.ts | 4 ++-- .../_fixture/restrict-nomap/generated/contract.d.ts | 4 ++-- .../sql-builder/fixtures/generated-no-pgvector/contract.d.ts | 4 ++-- .../test/sql-builder/fixtures/generated/contract.d.ts | 4 ++-- .../fixtures/execution-defaulted-tags/generated/contract.d.ts | 4 ++-- .../test/sql-orm-client/fixtures/generated/contract.d.ts | 4 ++-- .../fixtures/integer-representation/generated/contract.d.ts | 4 ++-- .../fixtures/junction-namespaces/generated/contract.d.ts | 4 ++-- .../sql-orm-client/fixtures/mn-psl/generated/contract.d.ts | 4 ++-- .../fixtures/non-identifier-names/generated/contract.d.ts | 4 ++-- .../fixtures/polymorphism/generated/contract.d.ts | 4 ++-- .../fixtures/scalar-lists/generated/contract.d.ts | 4 ++-- .../fixtures/self-relations/generated/contract.d.ts | 4 ++-- .../_fixture-timestamp/generated/contract.d.ts | 4 ++-- .../test/temporal-defaults/_fixture/generated/contract.d.ts | 4 ++-- 224 files changed, 448 insertions(+), 448 deletions(-) diff --git a/apps/telemetry-backend/src/prisma/contract.d.ts b/apps/telemetry-backend/src/prisma/contract.d.ts index b82c6f42ecc7..90ca3987d575 100644 --- a/apps/telemetry-backend/src/prisma/contract.d.ts +++ b/apps/telemetry-backend/src/prisma/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma/orm-postgres/adapter/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@prisma/orm-postgres/target/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgres/target/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/examples/bundle-size/src/postgres/generated/contract.d.ts b/examples/bundle-size/src/postgres/generated/contract.d.ts index d27f8ee558bf..4c0774b31ddf 100644 --- a/examples/bundle-size/src/postgres/generated/contract.d.ts +++ b/examples/bundle-size/src/postgres/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma/orm-postgres/adapter/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@prisma/orm-postgres/target/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgres/target/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/examples/multi-extension-monorepo/app/src/contract.d.ts b/examples/multi-extension-monorepo/app/src/contract.d.ts index 4997c92ba569..bced6117f7b0 100644 --- a/examples/multi-extension-monorepo/app/src/contract.d.ts +++ b/examples/multi-extension-monorepo/app/src/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma/orm-postgres/adapter/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@prisma/orm-postgres/target/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgres/target/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/examples/multi-extension-monorepo/packages/audit/migrations/snapshots/d009a7c12d910e42e7319f0e56ef3113548bd5d3262f06759caf861afd4468f5/contract.d.ts b/examples/multi-extension-monorepo/packages/audit/migrations/snapshots/d009a7c12d910e42e7319f0e56ef3113548bd5d3262f06759caf861afd4468f5/contract.d.ts index 4474d5abd52f..f01801d78952 100644 --- a/examples/multi-extension-monorepo/packages/audit/migrations/snapshots/d009a7c12d910e42e7319f0e56ef3113548bd5d3262f06759caf861afd4468f5/contract.d.ts +++ b/examples/multi-extension-monorepo/packages/audit/migrations/snapshots/d009a7c12d910e42e7319f0e56ef3113548bd5d3262f06759caf861afd4468f5/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma/orm-postgres/adapter/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@prisma/orm-postgres/target/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgres/target/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/examples/multi-extension-monorepo/packages/audit/src/contract.d.ts b/examples/multi-extension-monorepo/packages/audit/src/contract.d.ts index 4474d5abd52f..f01801d78952 100644 --- a/examples/multi-extension-monorepo/packages/audit/src/contract.d.ts +++ b/examples/multi-extension-monorepo/packages/audit/src/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma/orm-postgres/adapter/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@prisma/orm-postgres/target/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgres/target/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/examples/multi-extension-monorepo/packages/feature-flags/migrations/snapshots/7d110d82b575662c90102339516066ae91f9633527a9fa7c2f2769b714234a98/contract.d.ts b/examples/multi-extension-monorepo/packages/feature-flags/migrations/snapshots/7d110d82b575662c90102339516066ae91f9633527a9fa7c2f2769b714234a98/contract.d.ts index affc9467b130..e094cba0bef8 100644 --- a/examples/multi-extension-monorepo/packages/feature-flags/migrations/snapshots/7d110d82b575662c90102339516066ae91f9633527a9fa7c2f2769b714234a98/contract.d.ts +++ b/examples/multi-extension-monorepo/packages/feature-flags/migrations/snapshots/7d110d82b575662c90102339516066ae91f9633527a9fa7c2f2769b714234a98/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma/orm-postgres/adapter/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@prisma/orm-postgres/target/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgres/target/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/examples/multi-extension-monorepo/packages/feature-flags/src/contract.d.ts b/examples/multi-extension-monorepo/packages/feature-flags/src/contract.d.ts index affc9467b130..e094cba0bef8 100644 --- a/examples/multi-extension-monorepo/packages/feature-flags/src/contract.d.ts +++ b/examples/multi-extension-monorepo/packages/feature-flags/src/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma/orm-postgres/adapter/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@prisma/orm-postgres/target/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgres/target/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/examples/paradedb-demo/src/prisma/contract.d.ts b/examples/paradedb-demo/src/prisma/contract.d.ts index d4544d9b7bd1..33bdbef7ef34 100644 --- a/examples/paradedb-demo/src/prisma/contract.d.ts +++ b/examples/paradedb-demo/src/prisma/contract.d.ts @@ -2,7 +2,6 @@ // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit import type { QueryOperationTypes as ParadeDbQueryOperationTypes } from '@prisma/orm-extension-paradedb/operation-types'; -import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma/orm-postgres/adapter/operation-types'; import type { Bit, Char, @@ -20,6 +19,7 @@ import type { VarBit, Varchar, } from '@prisma/orm-postgres/target/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgres/target/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps & +export type QueryOperationTypes = PgTargetQueryOps & ParadeDbQueryOperationTypes; export type AggregateTypes = { readonly avg: { diff --git a/examples/prisma-8-cloudflare-worker/src/prisma/contract.d.ts b/examples/prisma-8-cloudflare-worker/src/prisma/contract.d.ts index 195e13936210..1f920bb15f5b 100644 --- a/examples/prisma-8-cloudflare-worker/src/prisma/contract.d.ts +++ b/examples/prisma-8-cloudflare-worker/src/prisma/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma/orm-postgres/adapter/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@prisma/orm-postgres/target/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgres/target/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/examples/prisma-8-demo/migrations/snapshots/62d81d607d929760f7d740b45bb97acc1dba361363c4851b19ee5a1cb4fecbe3/contract.d.ts b/examples/prisma-8-demo/migrations/snapshots/62d81d607d929760f7d740b45bb97acc1dba361363c4851b19ee5a1cb4fecbe3/contract.d.ts index 15aaf8074fa0..ad10d0fe0a18 100644 --- a/examples/prisma-8-demo/migrations/snapshots/62d81d607d929760f7d740b45bb97acc1dba361363c4851b19ee5a1cb4fecbe3/contract.d.ts +++ b/examples/prisma-8-demo/migrations/snapshots/62d81d607d929760f7d740b45bb97acc1dba361363c4851b19ee5a1cb4fecbe3/contract.d.ts @@ -6,7 +6,6 @@ import type { Vector, } from '@prisma/orm-extension-pgvector/codec-types'; import type { QueryOperationTypes as PgVectorQueryOperationTypes } from '@prisma/orm-extension-pgvector/operation-types'; -import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma/orm-postgres/adapter/operation-types'; import type { Bit, Char, @@ -24,6 +23,7 @@ import type { VarBit, Varchar, } from '@prisma/orm-postgres/target/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgres/target/operation-types'; import type { ContractWithTypeMaps, @@ -47,7 +47,7 @@ export type ProfileHash = export type CodecTypes = PgTypes & PgVectorTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps & +export type QueryOperationTypes = PgTargetQueryOps & PgVectorQueryOperationTypes; export type AggregateTypes = { readonly avg: { diff --git a/examples/prisma-8-demo/migrations/snapshots/8abaa3b97115767c5fee67bcd90de0cec3ac1f14a59875c2f5d22887ba435f89/contract.d.ts b/examples/prisma-8-demo/migrations/snapshots/8abaa3b97115767c5fee67bcd90de0cec3ac1f14a59875c2f5d22887ba435f89/contract.d.ts index cb1eb3c463a7..96764e403785 100644 --- a/examples/prisma-8-demo/migrations/snapshots/8abaa3b97115767c5fee67bcd90de0cec3ac1f14a59875c2f5d22887ba435f89/contract.d.ts +++ b/examples/prisma-8-demo/migrations/snapshots/8abaa3b97115767c5fee67bcd90de0cec3ac1f14a59875c2f5d22887ba435f89/contract.d.ts @@ -6,7 +6,6 @@ import type { Vector, } from '@prisma/orm-extension-pgvector/codec-types'; import type { QueryOperationTypes as PgVectorQueryOperationTypes } from '@prisma/orm-extension-pgvector/operation-types'; -import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma/orm-postgres/adapter/operation-types'; import type { Bit, Char, @@ -24,6 +23,7 @@ import type { VarBit, Varchar, } from '@prisma/orm-postgres/target/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgres/target/operation-types'; import type { ContractWithTypeMaps, @@ -47,7 +47,7 @@ export type ProfileHash = export type CodecTypes = PgTypes & PgVectorTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps & +export type QueryOperationTypes = PgTargetQueryOps & PgVectorQueryOperationTypes; export type AggregateTypes = { readonly avg: { diff --git a/examples/prisma-8-demo/migrations/snapshots/f62a4154d0b48cb144ca4f74667fc6922e770f81edd5517393285fb92d07dddc/contract.d.ts b/examples/prisma-8-demo/migrations/snapshots/f62a4154d0b48cb144ca4f74667fc6922e770f81edd5517393285fb92d07dddc/contract.d.ts index 36e7341dacd5..8df66c0c73b8 100644 --- a/examples/prisma-8-demo/migrations/snapshots/f62a4154d0b48cb144ca4f74667fc6922e770f81edd5517393285fb92d07dddc/contract.d.ts +++ b/examples/prisma-8-demo/migrations/snapshots/f62a4154d0b48cb144ca4f74667fc6922e770f81edd5517393285fb92d07dddc/contract.d.ts @@ -6,7 +6,6 @@ import type { Vector, } from '@prisma/orm-extension-pgvector/codec-types'; import type { QueryOperationTypes as PgVectorQueryOperationTypes } from '@prisma/orm-extension-pgvector/operation-types'; -import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma/orm-postgres/adapter/operation-types'; import type { Bit, Char, @@ -24,6 +23,7 @@ import type { VarBit, Varchar, } from '@prisma/orm-postgres/target/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgres/target/operation-types'; import type { ContractWithTypeMaps, @@ -47,7 +47,7 @@ export type ProfileHash = export type CodecTypes = PgTypes & PgVectorTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps & +export type QueryOperationTypes = PgTargetQueryOps & PgVectorQueryOperationTypes; export type AggregateTypes = { readonly avg: { diff --git a/examples/prisma-8-demo/src/prisma/contract.d.ts b/examples/prisma-8-demo/src/prisma/contract.d.ts index 15aaf8074fa0..ad10d0fe0a18 100644 --- a/examples/prisma-8-demo/src/prisma/contract.d.ts +++ b/examples/prisma-8-demo/src/prisma/contract.d.ts @@ -6,7 +6,6 @@ import type { Vector, } from '@prisma/orm-extension-pgvector/codec-types'; import type { QueryOperationTypes as PgVectorQueryOperationTypes } from '@prisma/orm-extension-pgvector/operation-types'; -import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma/orm-postgres/adapter/operation-types'; import type { Bit, Char, @@ -24,6 +23,7 @@ import type { VarBit, Varchar, } from '@prisma/orm-postgres/target/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgres/target/operation-types'; import type { ContractWithTypeMaps, @@ -47,7 +47,7 @@ export type ProfileHash = export type CodecTypes = PgTypes & PgVectorTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps & +export type QueryOperationTypes = PgTargetQueryOps & PgVectorQueryOperationTypes; export type AggregateTypes = { readonly avg: { diff --git a/examples/prisma-8-postgis-demo/migrations/snapshots/22e2633fb68e81380243a7fb492d650f4b45dcf990f2a3a146744fe8e2277423/contract.d.ts b/examples/prisma-8-postgis-demo/migrations/snapshots/22e2633fb68e81380243a7fb492d650f4b45dcf990f2a3a146744fe8e2277423/contract.d.ts index 40fa43970440..1fc8c853a82c 100644 --- a/examples/prisma-8-postgis-demo/migrations/snapshots/22e2633fb68e81380243a7fb492d650f4b45dcf990f2a3a146744fe8e2277423/contract.d.ts +++ b/examples/prisma-8-postgis-demo/migrations/snapshots/22e2633fb68e81380243a7fb492d650f4b45dcf990f2a3a146744fe8e2277423/contract.d.ts @@ -6,7 +6,6 @@ import type { Geometry, } from '@prisma/orm-extension-postgis/codec-types'; import type { QueryOperationTypes as PostgisQueryOperationTypes } from '@prisma/orm-extension-postgis/operation-types'; -import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma/orm-postgres/adapter/operation-types'; import type { Bit, Char, @@ -24,6 +23,7 @@ import type { VarBit, Varchar, } from '@prisma/orm-postgres/target/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgres/target/operation-types'; import type { ContractWithTypeMaps, @@ -47,7 +47,7 @@ export type ProfileHash = export type CodecTypes = PgTypes & PostgisTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps & +export type QueryOperationTypes = PgTargetQueryOps & PostgisQueryOperationTypes; export type AggregateTypes = { readonly avg: { diff --git a/examples/prisma-8-postgis-demo/src/prisma/contract.d.ts b/examples/prisma-8-postgis-demo/src/prisma/contract.d.ts index 40fa43970440..1fc8c853a82c 100644 --- a/examples/prisma-8-postgis-demo/src/prisma/contract.d.ts +++ b/examples/prisma-8-postgis-demo/src/prisma/contract.d.ts @@ -6,7 +6,6 @@ import type { Geometry, } from '@prisma/orm-extension-postgis/codec-types'; import type { QueryOperationTypes as PostgisQueryOperationTypes } from '@prisma/orm-extension-postgis/operation-types'; -import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma/orm-postgres/adapter/operation-types'; import type { Bit, Char, @@ -24,6 +23,7 @@ import type { VarBit, Varchar, } from '@prisma/orm-postgres/target/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgres/target/operation-types'; import type { ContractWithTypeMaps, @@ -47,7 +47,7 @@ export type ProfileHash = export type CodecTypes = PgTypes & PostgisTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps & +export type QueryOperationTypes = PgTargetQueryOps & PostgisQueryOperationTypes; export type AggregateTypes = { readonly avg: { diff --git a/examples/prisma7-adoption/generated/prisma8/contract.d.ts b/examples/prisma7-adoption/generated/prisma8/contract.d.ts index d5806b97d4a7..28e89daf962b 100644 --- a/examples/prisma7-adoption/generated/prisma8/contract.d.ts +++ b/examples/prisma7-adoption/generated/prisma8/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma/orm-postgres/adapter/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@prisma/orm-postgres/target/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgres/target/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/examples/react-router-demo/src/prisma/contract.d.ts b/examples/react-router-demo/src/prisma/contract.d.ts index a6730d611251..9ec8e5f1ee53 100644 --- a/examples/react-router-demo/src/prisma/contract.d.ts +++ b/examples/react-router-demo/src/prisma/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma/orm-postgres/adapter/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@prisma/orm-postgres/target/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgres/target/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/examples/supabase/src/contract.d.ts b/examples/supabase/src/contract.d.ts index f9dba0451467..03b62eb4cb70 100644 --- a/examples/supabase/src/contract.d.ts +++ b/examples/supabase/src/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma/orm-postgres/adapter/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@prisma/orm-postgres/target/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgres/target/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/packages/2-sql/4-lanes/sql-builder/test/fixtures/generated/contract.d.ts b/packages/2-sql/4-lanes/sql-builder/test/fixtures/generated/contract.d.ts index b778ac914982..d08b896a147a 100644 --- a/packages/2-sql/4-lanes/sql-builder/test/fixtures/generated/contract.d.ts +++ b/packages/2-sql/4-lanes/sql-builder/test/fixtures/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/packages/3-extensions/paradedb/migrations/snapshots/0c0734babd6eeb868fee1f281ca96963022475611560e9f170f465daa35f8599/contract.d.ts b/packages/3-extensions/paradedb/migrations/snapshots/0c0734babd6eeb868fee1f281ca96963022475611560e9f170f465daa35f8599/contract.d.ts index 83b6eb49e167..f159df324d8d 100644 --- a/packages/3-extensions/paradedb/migrations/snapshots/0c0734babd6eeb868fee1f281ca96963022475611560e9f170f465daa35f8599/contract.d.ts +++ b/packages/3-extensions/paradedb/migrations/snapshots/0c0734babd6eeb868fee1f281ca96963022475611560e9f170f465daa35f8599/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/packages/3-extensions/paradedb/src/contract.d.ts b/packages/3-extensions/paradedb/src/contract.d.ts index 83b6eb49e167..f159df324d8d 100644 --- a/packages/3-extensions/paradedb/src/contract.d.ts +++ b/packages/3-extensions/paradedb/src/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/packages/3-extensions/pgvector/migrations/snapshots/3d2c56a2944685bd21b05bc8a8d73164397df51c014201902932fbe7e80ff1b8/contract.d.ts b/packages/3-extensions/pgvector/migrations/snapshots/3d2c56a2944685bd21b05bc8a8d73164397df51c014201902932fbe7e80ff1b8/contract.d.ts index 5c115f5f4fc5..0b159f2ef01f 100644 --- a/packages/3-extensions/pgvector/migrations/snapshots/3d2c56a2944685bd21b05bc8a8d73164397df51c014201902932fbe7e80ff1b8/contract.d.ts +++ b/packages/3-extensions/pgvector/migrations/snapshots/3d2c56a2944685bd21b05bc8a8d73164397df51c014201902932fbe7e80ff1b8/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/packages/3-extensions/pgvector/src/contract.d.ts b/packages/3-extensions/pgvector/src/contract.d.ts index 5c115f5f4fc5..0b159f2ef01f 100644 --- a/packages/3-extensions/pgvector/src/contract.d.ts +++ b/packages/3-extensions/pgvector/src/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/packages/3-extensions/postgis/migrations/snapshots/7e98a4d9437e6be2f2fa7fca02fbc01c245586997a937f97cab60788612512e5/contract.d.ts b/packages/3-extensions/postgis/migrations/snapshots/7e98a4d9437e6be2f2fa7fca02fbc01c245586997a937f97cab60788612512e5/contract.d.ts index e1ddccf4fcb4..e668035166d1 100644 --- a/packages/3-extensions/postgis/migrations/snapshots/7e98a4d9437e6be2f2fa7fca02fbc01c245586997a937f97cab60788612512e5/contract.d.ts +++ b/packages/3-extensions/postgis/migrations/snapshots/7e98a4d9437e6be2f2fa7fca02fbc01c245586997a937f97cab60788612512e5/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/packages/3-extensions/postgis/src/contract.d.ts b/packages/3-extensions/postgis/src/contract.d.ts index e1ddccf4fcb4..e668035166d1 100644 --- a/packages/3-extensions/postgis/src/contract.d.ts +++ b/packages/3-extensions/postgis/src/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/packages/3-extensions/postgres/test/fixtures/generated/contract.d.ts b/packages/3-extensions/postgres/test/fixtures/generated/contract.d.ts index b778ac914982..d08b896a147a 100644 --- a/packages/3-extensions/postgres/test/fixtures/generated/contract.d.ts +++ b/packages/3-extensions/postgres/test/fixtures/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/packages/3-extensions/sql-orm-client/test/fixtures/generated/contract.d.ts b/packages/3-extensions/sql-orm-client/test/fixtures/generated/contract.d.ts index 4d40317a6ebc..971c669dab98 100644 --- a/packages/3-extensions/sql-orm-client/test/fixtures/generated/contract.d.ts +++ b/packages/3-extensions/sql-orm-client/test/fixtures/generated/contract.d.ts @@ -6,7 +6,6 @@ // in this package-level copy to avoid a circular Turbo build dependency. // (@internal/extension-pgvector → @internal/postgres → @internal/sql-orm-client) // The integration tests that exercise pgvector-specific operations live in test/integration/. -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; // pgvector types replaced with local aliases (see note above) type PgVectorTypes = object; type Vector<_N extends number> = number[]; @@ -28,6 +27,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -51,7 +51,7 @@ export type ProfileHash = export type CodecTypes = PgTypes & PgVectorTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps & +export type QueryOperationTypes = PgTargetQueryOps & PgVectorQueryOperationTypes; export type AggregateTypes = { readonly avg: { diff --git a/packages/3-extensions/sql-orm-client/test/fixtures/junction-namespaces/generated/contract.d.ts b/packages/3-extensions/sql-orm-client/test/fixtures/junction-namespaces/generated/contract.d.ts index 4fb985207f8f..2ce0337ee2fe 100644 --- a/packages/3-extensions/sql-orm-client/test/fixtures/junction-namespaces/generated/contract.d.ts +++ b/packages/3-extensions/sql-orm-client/test/fixtures/junction-namespaces/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/packages/3-extensions/supabase/src/contract/contract.d.ts b/packages/3-extensions/supabase/src/contract/contract.d.ts index cd06be3be270..e1b2a93c231f 100644 --- a/packages/3-extensions/supabase/src/contract/contract.d.ts +++ b/packages/3-extensions/supabase/src/contract/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/packages/3-extensions/supabase/test/fixtures/example-app/contract.d.ts b/packages/3-extensions/supabase/test/fixtures/example-app/contract.d.ts index b93bc69d068f..60fcc5d6710c 100644 --- a/packages/3-extensions/supabase/test/fixtures/example-app/contract.d.ts +++ b/packages/3-extensions/supabase/test/fixtures/example-app/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/packages/3-extensions/supabase/test/fixtures/no-policy/contract.d.ts b/packages/3-extensions/supabase/test/fixtures/no-policy/contract.d.ts index e9188bdbb34b..58d9e73bbdc7 100644 --- a/packages/3-extensions/supabase/test/fixtures/no-policy/contract.d.ts +++ b/packages/3-extensions/supabase/test/fixtures/no-policy/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/packages/3-extensions/supabase/test/fixtures/renamed-policy/contract.d.ts b/packages/3-extensions/supabase/test/fixtures/renamed-policy/contract.d.ts index e0305e8bd44c..f6ca9de4737d 100644 --- a/packages/3-extensions/supabase/test/fixtures/renamed-policy/contract.d.ts +++ b/packages/3-extensions/supabase/test/fixtures/renamed-policy/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/e2e/framework/test/fixtures/generated/contract.d.ts b/test/e2e/framework/test/fixtures/generated/contract.d.ts index 592c94c19924..b778f0e74f07 100644 --- a/test/e2e/framework/test/fixtures/generated/contract.d.ts +++ b/test/e2e/framework/test/fixtures/generated/contract.d.ts @@ -7,7 +7,6 @@ import type { Vector, } from '@prisma/orm-extension-pgvector/codec-types'; import type { QueryOperationTypes as PgVectorQueryOperationTypes } from '@prisma/orm-extension-pgvector/operation-types'; -import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma/orm-postgres/adapter/operation-types'; import type { Bit, Char, @@ -25,6 +24,7 @@ import type { VarBit, Varchar, } from '@prisma/orm-postgres/target/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgres/target/operation-types'; import type { ContractWithTypeMaps, @@ -48,7 +48,7 @@ export type ProfileHash = export type CodecTypes = PgTypes & ArktypeJsonTypes & PgVectorTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps & +export type QueryOperationTypes = PgTargetQueryOps & PgVectorQueryOperationTypes; export type AggregateTypes = { readonly avg: { diff --git a/test/integration/test/enum-order-by/_fixture/generated/contract.d.ts b/test/integration/test/enum-order-by/_fixture/generated/contract.d.ts index 97b40d8e3dcf..bce1ab97c969 100644 --- a/test/integration/test/enum-order-by/_fixture/generated/contract.d.ts +++ b/test/integration/test/enum-order-by/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/fixtures/contract.d.ts b/test/integration/test/fixtures/contract.d.ts index 65687956beb1..5888e6098523 100644 --- a/test/integration/test/fixtures/contract.d.ts +++ b/test/integration/test/fixtures/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/namespaced-accessors/fixtures/generated/contract.d.ts b/test/integration/test/namespaced-accessors/fixtures/generated/contract.d.ts index 96708948ae61..a6b12be1a6e2 100644 --- a/test/integration/test/namespaced-accessors/fixtures/generated/contract.d.ts +++ b/test/integration/test/namespaced-accessors/fixtures/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/aggregation/avg/_fixture/decimal/generated/contract.d.ts b/test/integration/test/ports/engines/queries/aggregation/avg/_fixture/decimal/generated/contract.d.ts index 8a7111e9d270..1469f5c5e7ea 100644 --- a/test/integration/test/ports/engines/queries/aggregation/avg/_fixture/decimal/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/aggregation/avg/_fixture/decimal/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/aggregation/avg/_fixture/numeric/generated/contract.d.ts b/test/integration/test/ports/engines/queries/aggregation/avg/_fixture/numeric/generated/contract.d.ts index 43167ca400df..489b044ca52a 100644 --- a/test/integration/test/ports/engines/queries/aggregation/avg/_fixture/numeric/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/aggregation/avg/_fixture/numeric/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/aggregation/count/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/aggregation/count/_fixture/generated/contract.d.ts index 235b170cea2d..86ff55673c76 100644 --- a/test/integration/test/ports/engines/queries/aggregation/count/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/aggregation/count/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/aggregation/group_by/_fixture/main/generated/contract.d.ts b/test/integration/test/ports/engines/queries/aggregation/group_by/_fixture/main/generated/contract.d.ts index f78673d0c737..f0f4ca65fcac 100644 --- a/test/integration/test/ports/engines/queries/aggregation/group_by/_fixture/main/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/aggregation/group_by/_fixture/main/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/aggregation/group_by/_fixture/regression-21789/generated/contract.d.ts b/test/integration/test/ports/engines/queries/aggregation/group_by/_fixture/regression-21789/generated/contract.d.ts index e908dbdb3e88..0bb6bfef5a79 100644 --- a/test/integration/test/ports/engines/queries/aggregation/group_by/_fixture/regression-21789/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/aggregation/group_by/_fixture/regression-21789/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/aggregation/group_by_having/_fixture/common/generated/contract.d.ts b/test/integration/test/ports/engines/queries/aggregation/group_by_having/_fixture/common/generated/contract.d.ts index 3382b5c63f12..68df0cd732ef 100644 --- a/test/integration/test/ports/engines/queries/aggregation/group_by_having/_fixture/common/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/aggregation/group_by_having/_fixture/common/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/aggregation/group_by_having/_fixture/decimal/generated/contract.d.ts b/test/integration/test/ports/engines/queries/aggregation/group_by_having/_fixture/decimal/generated/contract.d.ts index 236e30261fdc..16a34993362d 100644 --- a/test/integration/test/ports/engines/queries/aggregation/group_by_having/_fixture/decimal/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/aggregation/group_by_having/_fixture/decimal/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/aggregation/many_count_relation/_fixture/compound/generated/contract.d.ts b/test/integration/test/ports/engines/queries/aggregation/many_count_relation/_fixture/compound/generated/contract.d.ts index 72d926adb391..024e166565a1 100644 --- a/test/integration/test/ports/engines/queries/aggregation/many_count_relation/_fixture/compound/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/aggregation/many_count_relation/_fixture/compound/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/aggregation/many_count_relation/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/aggregation/many_count_relation/_fixture/generated/contract.d.ts index d23ba06b6bf5..3b667439c605 100644 --- a/test/integration/test/ports/engines/queries/aggregation/many_count_relation/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/aggregation/many_count_relation/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/aggregation/many_count_relation/_fixture/nested/generated/contract.d.ts b/test/integration/test/ports/engines/queries/aggregation/many_count_relation/_fixture/nested/generated/contract.d.ts index 7963a59299eb..c647fef65887 100644 --- a/test/integration/test/ports/engines/queries/aggregation/many_count_relation/_fixture/nested/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/aggregation/many_count_relation/_fixture/nested/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/aggregation/many_count_relation/_fixture/self/generated/contract.d.ts b/test/integration/test/ports/engines/queries/aggregation/many_count_relation/_fixture/self/generated/contract.d.ts index 00d0c246da34..f29c650a1cab 100644 --- a/test/integration/test/ports/engines/queries/aggregation/many_count_relation/_fixture/self/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/aggregation/many_count_relation/_fixture/self/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/aggregation/max/_fixture/common/generated/contract.d.ts b/test/integration/test/ports/engines/queries/aggregation/max/_fixture/common/generated/contract.d.ts index 89877289b1b7..7a768d5cf658 100644 --- a/test/integration/test/ports/engines/queries/aggregation/max/_fixture/common/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/aggregation/max/_fixture/common/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/aggregation/max/_fixture/decimal/generated/contract.d.ts b/test/integration/test/ports/engines/queries/aggregation/max/_fixture/decimal/generated/contract.d.ts index 8a7111e9d270..1469f5c5e7ea 100644 --- a/test/integration/test/ports/engines/queries/aggregation/max/_fixture/decimal/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/aggregation/max/_fixture/decimal/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/aggregation/min/_fixture/common/generated/contract.d.ts b/test/integration/test/ports/engines/queries/aggregation/min/_fixture/common/generated/contract.d.ts index 89877289b1b7..7a768d5cf658 100644 --- a/test/integration/test/ports/engines/queries/aggregation/min/_fixture/common/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/aggregation/min/_fixture/common/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/aggregation/min/_fixture/decimal/generated/contract.d.ts b/test/integration/test/ports/engines/queries/aggregation/min/_fixture/decimal/generated/contract.d.ts index 8a7111e9d270..1469f5c5e7ea 100644 --- a/test/integration/test/ports/engines/queries/aggregation/min/_fixture/decimal/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/aggregation/min/_fixture/decimal/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/aggregation/sum/_fixture/decimal/generated/contract.d.ts b/test/integration/test/ports/engines/queries/aggregation/sum/_fixture/decimal/generated/contract.d.ts index 8a7111e9d270..1469f5c5e7ea 100644 --- a/test/integration/test/ports/engines/queries/aggregation/sum/_fixture/decimal/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/aggregation/sum/_fixture/decimal/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/aggregation/sum/_fixture/numeric/generated/contract.d.ts b/test/integration/test/ports/engines/queries/aggregation/sum/_fixture/numeric/generated/contract.d.ts index 43167ca400df..489b044ca52a 100644 --- a/test/integration/test/ports/engines/queries/aggregation/sum/_fixture/numeric/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/aggregation/sum/_fixture/numeric/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/aggregation/uniq-count-relation/_fixture/base/generated/contract.d.ts b/test/integration/test/ports/engines/queries/aggregation/uniq-count-relation/_fixture/base/generated/contract.d.ts index d23ba06b6bf5..3b667439c605 100644 --- a/test/integration/test/ports/engines/queries/aggregation/uniq-count-relation/_fixture/base/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/aggregation/uniq-count-relation/_fixture/base/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/aggregation/uniq-count-relation/_fixture/nested/generated/contract.d.ts b/test/integration/test/ports/engines/queries/aggregation/uniq-count-relation/_fixture/nested/generated/contract.d.ts index 7963a59299eb..c647fef65887 100644 --- a/test/integration/test/ports/engines/queries/aggregation/uniq-count-relation/_fixture/nested/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/aggregation/uniq-count-relation/_fixture/nested/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/data_types/bigint/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/data_types/bigint/_fixture/generated/contract.d.ts index 235b170cea2d..86ff55673c76 100644 --- a/test/integration/test/ports/engines/queries/data_types/bigint/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/data_types/bigint/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/data_types/bool/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/data_types/bool/_fixture/generated/contract.d.ts index 235b170cea2d..86ff55673c76 100644 --- a/test/integration/test/ports/engines/queries/data_types/bool/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/data_types/bool/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/data_types/bytes/_fixture/relations/generated/contract.d.ts b/test/integration/test/ports/engines/queries/data_types/bytes/_fixture/relations/generated/contract.d.ts index e911d101e61a..efbb6048877b 100644 --- a/test/integration/test/ports/engines/queries/data_types/bytes/_fixture/relations/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/data_types/bytes/_fixture/relations/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/data_types/bytes/_fixture/scalars/generated/contract.d.ts b/test/integration/test/ports/engines/queries/data_types/bytes/_fixture/scalars/generated/contract.d.ts index 235b170cea2d..86ff55673c76 100644 --- a/test/integration/test/ports/engines/queries/data_types/bytes/_fixture/scalars/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/data_types/bytes/_fixture/scalars/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/data_types/datetime/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/data_types/datetime/_fixture/generated/contract.d.ts index 235b170cea2d..86ff55673c76 100644 --- a/test/integration/test/ports/engines/queries/data_types/datetime/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/data_types/datetime/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/data_types/decimal/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/data_types/decimal/_fixture/generated/contract.d.ts index e14ae64f35f5..df6c44b3898d 100644 --- a/test/integration/test/ports/engines/queries/data_types/decimal/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/data_types/decimal/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/data_types/enum_type/_fixture/postgres/generated/contract.d.ts b/test/integration/test/ports/engines/queries/data_types/enum_type/_fixture/postgres/generated/contract.d.ts index 3798c465dc56..1f6d6396dc13 100644 --- a/test/integration/test/ports/engines/queries/data_types/enum_type/_fixture/postgres/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/data_types/enum_type/_fixture/postgres/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/data_types/float/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/data_types/float/_fixture/generated/contract.d.ts index 235b170cea2d..86ff55673c76 100644 --- a/test/integration/test/ports/engines/queries/data_types/float/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/data_types/float/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/data_types/int/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/data_types/int/_fixture/generated/contract.d.ts index 235b170cea2d..86ff55673c76 100644 --- a/test/integration/test/ports/engines/queries/data_types/int/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/data_types/int/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/data_types/json/_fixture/scalar/generated/contract.d.ts b/test/integration/test/ports/engines/queries/data_types/json/_fixture/scalar/generated/contract.d.ts index 69189ca7ebf5..8d609d2a46eb 100644 --- a/test/integration/test/ports/engines/queries/data_types/json/_fixture/scalar/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/data_types/json/_fixture/scalar/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/data_types/native/postgres/_fixture/other/generated/contract.d.ts b/test/integration/test/ports/engines/queries/data_types/native/postgres/_fixture/other/generated/contract.d.ts index 1ce8ccb2c75a..c6456ded03a7 100644 --- a/test/integration/test/ports/engines/queries/data_types/native/postgres/_fixture/other/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/data_types/native/postgres/_fixture/other/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/data_types/native/postgres/_fixture/string/generated/contract.d.ts b/test/integration/test/ports/engines/queries/data_types/native/postgres/_fixture/string/generated/contract.d.ts index 3c1c633952ea..55cba01831d6 100644 --- a/test/integration/test/ports/engines/queries/data_types/native/postgres/_fixture/string/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/data_types/native/postgres/_fixture/string/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/data_types/string/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/data_types/string/_fixture/generated/contract.d.ts index 235b170cea2d..86ff55673c76 100644 --- a/test/integration/test/ports/engines/queries/data_types/string/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/data_types/string/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/data_types/through_relation/_fixture/common/generated/contract.d.ts b/test/integration/test/ports/engines/queries/data_types/through_relation/_fixture/common/generated/contract.d.ts index 4688c62a647f..73dda391d563 100644 --- a/test/integration/test/ports/engines/queries/data_types/through_relation/_fixture/common/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/data_types/through_relation/_fixture/common/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/data_types/through_relation/_fixture/decimal/generated/contract.d.ts b/test/integration/test/ports/engines/queries/data_types/through_relation/_fixture/decimal/generated/contract.d.ts index 21e4cc27ad80..ba15f311c99f 100644 --- a/test/integration/test/ports/engines/queries/data_types/through_relation/_fixture/decimal/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/data_types/through_relation/_fixture/decimal/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/data_types/through_relation/_fixture/enum/generated/contract.d.ts b/test/integration/test/ports/engines/queries/data_types/through_relation/_fixture/enum/generated/contract.d.ts index d973a9d788d1..408f51a7691f 100644 --- a/test/integration/test/ports/engines/queries/data_types/through_relation/_fixture/enum/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/data_types/through_relation/_fixture/enum/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/data_types/through_relation/_fixture/json/generated/contract.d.ts b/test/integration/test/ports/engines/queries/data_types/through_relation/_fixture/json/generated/contract.d.ts index 3f27da73107c..52ebe59950e8 100644 --- a/test/integration/test/ports/engines/queries/data_types/through_relation/_fixture/json/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/data_types/through_relation/_fixture/json/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/data_types/through_relation/_fixture/lists/generated/contract.d.ts b/test/integration/test/ports/engines/queries/data_types/through_relation/_fixture/lists/generated/contract.d.ts index f9ddb732e20f..54a401920947 100644 --- a/test/integration/test/ports/engines/queries/data_types/through_relation/_fixture/lists/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/data_types/through_relation/_fixture/lists/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/distinct/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/distinct/_fixture/generated/contract.d.ts index f7589db4c4f8..1a292a6e58a0 100644 --- a/test/integration/test/ports/engines/queries/distinct/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/distinct/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/bigint_filter/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/bigint_filter/_fixture/generated/contract.d.ts index 235b170cea2d..86ff55673c76 100644 --- a/test/integration/test/ports/engines/queries/filters/bigint_filter/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/bigint_filter/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/bytes_filter/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/bytes_filter/_fixture/generated/contract.d.ts index 235b170cea2d..86ff55673c76 100644 --- a/test/integration/test/ports/engines/queries/filters/bytes_filter/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/bytes_filter/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/decimal_filter/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/decimal_filter/_fixture/generated/contract.d.ts index a6ca7e0227b1..c304b07ca47e 100644 --- a/test/integration/test/ports/engines/queries/filters/decimal_filter/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/decimal_filter/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/field_reference/_fixture/decimal-list/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/field_reference/_fixture/decimal-list/generated/contract.d.ts index 7a295e9d639b..10bf4c1f589c 100644 --- a/test/integration/test/ports/engines/queries/filters/field_reference/_fixture/decimal-list/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/field_reference/_fixture/decimal-list/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/field_reference/_fixture/enum/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/field_reference/_fixture/enum/generated/contract.d.ts index c67f0e4e663a..5e2d425aab16 100644 --- a/test/integration/test/ports/engines/queries/filters/field_reference/_fixture/enum/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/field_reference/_fixture/enum/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/field_reference/_fixture/list/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/field_reference/_fixture/list/generated/contract.d.ts index 0a31d1b9295b..188ad3f50581 100644 --- a/test/integration/test/ports/engines/queries/filters/field_reference/_fixture/list/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/field_reference/_fixture/list/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/field_reference/_fixture/mixed/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/field_reference/_fixture/mixed/generated/contract.d.ts index 241cdfe3d578..fbaedb3bc78d 100644 --- a/test/integration/test/ports/engines/queries/filters/field_reference/_fixture/mixed/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/field_reference/_fixture/mixed/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/field_reference/bigint_filter/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/field_reference/bigint_filter/_fixture/generated/contract.d.ts index 3ee7eebf7d89..21650b0ca364 100644 --- a/test/integration/test/ports/engines/queries/filters/field_reference/bigint_filter/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/field_reference/bigint_filter/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/field_reference/bytes_filter/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/field_reference/bytes_filter/_fixture/generated/contract.d.ts index 3ee7eebf7d89..21650b0ca364 100644 --- a/test/integration/test/ports/engines/queries/filters/field_reference/bytes_filter/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/field_reference/bytes_filter/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/field_reference/datetime_filter/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/field_reference/datetime_filter/_fixture/generated/contract.d.ts index 3ee7eebf7d89..21650b0ca364 100644 --- a/test/integration/test/ports/engines/queries/filters/field_reference/datetime_filter/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/field_reference/datetime_filter/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/field_reference/decimal_filter/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/field_reference/decimal_filter/_fixture/generated/contract.d.ts index 3cd3b20c0344..9095c0f3b943 100644 --- a/test/integration/test/ports/engines/queries/filters/field_reference/decimal_filter/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/field_reference/decimal_filter/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/field_reference/failure/_fixture/common/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/field_reference/failure/_fixture/common/generated/contract.d.ts index 3ee7eebf7d89..21650b0ca364 100644 --- a/test/integration/test/ports/engines/queries/filters/field_reference/failure/_fixture/common/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/field_reference/failure/_fixture/common/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/field_reference/failure/_fixture/default/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/field_reference/failure/_fixture/default/generated/contract.d.ts index 2f3332b9d0af..dfb24524fafd 100644 --- a/test/integration/test/ports/engines/queries/filters/field_reference/failure/_fixture/default/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/field_reference/failure/_fixture/default/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/field_reference/failure/_fixture/list/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/field_reference/failure/_fixture/list/generated/contract.d.ts index f2920490df67..4cfb093ac9c8 100644 --- a/test/integration/test/ports/engines/queries/filters/field_reference/failure/_fixture/list/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/field_reference/failure/_fixture/list/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/field_reference/float_filter/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/field_reference/float_filter/_fixture/generated/contract.d.ts index 3ee7eebf7d89..21650b0ca364 100644 --- a/test/integration/test/ports/engines/queries/filters/field_reference/float_filter/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/field_reference/float_filter/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/field_reference/having_filter/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/field_reference/having_filter/_fixture/generated/contract.d.ts index 3ee7eebf7d89..21650b0ca364 100644 --- a/test/integration/test/ports/engines/queries/filters/field_reference/having_filter/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/field_reference/having_filter/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/field_reference/int_filter/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/field_reference/int_filter/_fixture/generated/contract.d.ts index 3ee7eebf7d89..21650b0ca364 100644 --- a/test/integration/test/ports/engines/queries/filters/field_reference/int_filter/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/field_reference/int_filter/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/field_reference/json_filter/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/field_reference/json_filter/_fixture/generated/contract.d.ts index 70a5020db9be..d2c1c07fe5e3 100644 --- a/test/integration/test/ports/engines/queries/filters/field_reference/json_filter/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/field_reference/json_filter/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/field_reference/json_filter/_fixture/list/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/field_reference/json_filter/_fixture/list/generated/contract.d.ts index 8e5a8d26953f..f95f2ee20982 100644 --- a/test/integration/test/ports/engines/queries/filters/field_reference/json_filter/_fixture/list/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/field_reference/json_filter/_fixture/list/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/field_reference/relation_filter/_fixture/complex/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/field_reference/relation_filter/_fixture/complex/generated/contract.d.ts index dc9f32ae3136..46300f483173 100644 --- a/test/integration/test/ports/engines/queries/filters/field_reference/relation_filter/_fixture/complex/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/field_reference/relation_filter/_fixture/complex/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/field_reference/relation_filter/_fixture/one-to-many/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/field_reference/relation_filter/_fixture/one-to-many/generated/contract.d.ts index ffddc1470ad3..0f34be9931dd 100644 --- a/test/integration/test/ports/engines/queries/filters/field_reference/relation_filter/_fixture/one-to-many/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/field_reference/relation_filter/_fixture/one-to-many/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/field_reference/relation_filter/_fixture/one-to-one-list/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/field_reference/relation_filter/_fixture/one-to-one-list/generated/contract.d.ts index 190834526276..447cc2a42838 100644 --- a/test/integration/test/ports/engines/queries/filters/field_reference/relation_filter/_fixture/one-to-one-list/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/field_reference/relation_filter/_fixture/one-to-one-list/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/field_reference/relation_filter/_fixture/one-to-one/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/field_reference/relation_filter/_fixture/one-to-one/generated/contract.d.ts index 8f6699d30b4e..f95e4532af6c 100644 --- a/test/integration/test/ports/engines/queries/filters/field_reference/relation_filter/_fixture/one-to-one/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/field_reference/relation_filter/_fixture/one-to-one/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/field_reference/string_filter/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/field_reference/string_filter/_fixture/generated/contract.d.ts index 3ee7eebf7d89..21650b0ca364 100644 --- a/test/integration/test/ports/engines/queries/filters/field_reference/string_filter/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/field_reference/string_filter/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/filter_regression/_fixture/compound-one-to-many/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/filter_regression/_fixture/compound-one-to-many/generated/contract.d.ts index f8e1bb987a2d..27ff03b4bd18 100644 --- a/test/integration/test/ports/engines/queries/filters/filter_regression/_fixture/compound-one-to-many/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/filter_regression/_fixture/compound-one-to-many/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/filter_regression/_fixture/many-to-many/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/filter_regression/_fixture/many-to-many/generated/contract.d.ts index 2422d7160109..f32d92446bb9 100644 --- a/test/integration/test/ports/engines/queries/filters/filter_regression/_fixture/many-to-many/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/filter_regression/_fixture/many-to-many/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/filter_regression/_fixture/one-to-many/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/filter_regression/_fixture/one-to-many/generated/contract.d.ts index 2888ffaede3b..eeeedb63a2e0 100644 --- a/test/integration/test/ports/engines/queries/filters/filter_regression/_fixture/one-to-many/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/filter_regression/_fixture/one-to-many/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/filters/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/filters/_fixture/generated/contract.d.ts index 1114e3076ddf..6c8da363c121 100644 --- a/test/integration/test/ports/engines/queries/filters/filters/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/filters/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/json/_fixture/optional/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/json/_fixture/optional/generated/contract.d.ts index 69189ca7ebf5..8d609d2a46eb 100644 --- a/test/integration/test/ports/engines/queries/filters/json/_fixture/optional/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/json/_fixture/optional/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/list_filters/_fixture/base/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/list_filters/_fixture/base/generated/contract.d.ts index 03843f38068d..562e32a5b058 100644 --- a/test/integration/test/ports/engines/queries/filters/list_filters/_fixture/base/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/list_filters/_fixture/base/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/list_filters/_fixture/decimal/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/list_filters/_fixture/decimal/generated/contract.d.ts index 558ed5897ab2..ad1f649d1348 100644 --- a/test/integration/test/ports/engines/queries/filters/list_filters/_fixture/decimal/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/list_filters/_fixture/decimal/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/list_filters/_fixture/json/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/list_filters/_fixture/json/generated/contract.d.ts index cd9633820060..139496ae9a7f 100644 --- a/test/integration/test/ports/engines/queries/filters/list_filters/_fixture/json/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/list_filters/_fixture/json/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/many_relation/_fixture/25103/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/many_relation/_fixture/25103/generated/contract.d.ts index c5aa164b85b0..9894135bf070 100644 --- a/test/integration/test/ports/engines/queries/filters/many_relation/_fixture/25103/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/many_relation/_fixture/25103/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/many_relation/_fixture/l2-to-one/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/many_relation/_fixture/l2-to-one/generated/contract.d.ts index e179d07de7ce..6551fb4ea64b 100644 --- a/test/integration/test/ports/engines/queries/filters/many_relation/_fixture/l2-to-one/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/many_relation/_fixture/l2-to-one/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/one2one_regression/_fixture/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/one2one_regression/_fixture/generated/contract.d.ts index d453fa84c0a9..af6ab2d77ab3 100644 --- a/test/integration/test/ports/engines/queries/filters/one2one_regression/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/one2one_regression/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/one_relation/_fixture/21356/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/one_relation/_fixture/21356/generated/contract.d.ts index db3539d9910c..cd52e7763b5e 100644 --- a/test/integration/test/ports/engines/queries/filters/one_relation/_fixture/21356/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/one_relation/_fixture/21356/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/engines/queries/filters/one_relation/_fixture/21366/generated/contract.d.ts b/test/integration/test/ports/engines/queries/filters/one_relation/_fixture/21366/generated/contract.d.ts index 36f4fa049ce2..a34a91741d30 100644 --- a/test/integration/test/ports/engines/queries/filters/one_relation/_fixture/21366/generated/contract.d.ts +++ b/test/integration/test/ports/engines/queries/filters/one_relation/_fixture/21366/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/batching-bigint/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/batching-bigint/_fixture/generated/contract.d.ts index 6ce0bf98e572..0502c9c501ba 100644 --- a/test/integration/test/ports/prisma/functional/batching-bigint/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/batching-bigint/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/batching-bytes/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/batching-bytes/_fixture/generated/contract.d.ts index 722237c84e3f..e3c35a6202e0 100644 --- a/test/integration/test/ports/prisma/functional/batching-bytes/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/batching-bytes/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/blog-update/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/blog-update/_fixture/generated/contract.d.ts index 19cb20e30c11..9fbd5a267d27 100644 --- a/test/integration/test/ports/prisma/functional/blog-update/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/blog-update/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/bytes-upsert/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/bytes-upsert/_fixture/generated/contract.d.ts index f1456f500f7a..f9c2512bee33 100644 --- a/test/integration/test/ports/prisma/functional/bytes-upsert/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/bytes-upsert/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/chunking-query/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/chunking-query/_fixture/generated/contract.d.ts index f360dabd23fc..41d4dcd84d53 100644 --- a/test/integration/test/ports/prisma/functional/chunking-query/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/chunking-query/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/create-default-date/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/create-default-date/_fixture/generated/contract.d.ts index f456707075cf..97ac50dc0d05 100644 --- a/test/integration/test/ports/prisma/functional/create-default-date/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/create-default-date/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/decimal-list/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/decimal-list/_fixture/generated/contract.d.ts index e6918fb838a5..5a464fa7f0cb 100644 --- a/test/integration/test/ports/prisma/functional/decimal-list/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/decimal-list/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/decimal-precision/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/decimal-precision/_fixture/generated/contract.d.ts index e28b55a1e8de..954c2d8f5cc4 100644 --- a/test/integration/test/ports/prisma/functional/decimal-precision/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/decimal-precision/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/decimal-scalar/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/decimal-scalar/_fixture/generated/contract.d.ts index e1b3476f1173..cc62c66ecf9c 100644 --- a/test/integration/test/ports/prisma/functional/decimal-scalar/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/decimal-scalar/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/default-selection/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/default-selection/_fixture/generated/contract.d.ts index 7375b75f4657..81bd18f90190 100644 --- a/test/integration/test/ports/prisma/functional/default-selection/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/default-selection/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/distinct/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/distinct/_fixture/generated/contract.d.ts index 7ce2b6a836a7..e83c3b30dd58 100644 --- a/test/integration/test/ports/prisma/functional/distinct/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/distinct/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/driver-adapters-error-forwarding/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/driver-adapters-error-forwarding/_fixture/generated/contract.d.ts index 30808b9bdcf0..a6eb4a4ba9f6 100644 --- a/test/integration/test/ports/prisma/functional/driver-adapters-error-forwarding/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/driver-adapters-error-forwarding/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/driver-adapters-team-orm-687-bytes/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/driver-adapters-team-orm-687-bytes/_fixture/generated/contract.d.ts index dc38c2392b7c..e2b848cbff06 100644 --- a/test/integration/test/ports/prisma/functional/driver-adapters-team-orm-687-bytes/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/driver-adapters-team-orm-687-bytes/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/driver-adapters-validate-active-provider/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/driver-adapters-validate-active-provider/_fixture/generated/contract.d.ts index 57a61d7bcd72..7aa355c87573 100644 --- a/test/integration/test/ports/prisma/functional/driver-adapters-validate-active-provider/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/driver-adapters-validate-active-provider/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/enum-array/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/enum-array/_fixture/generated/contract.d.ts index 305ad7852ca8..cd4740f709c5 100644 --- a/test/integration/test/ports/prisma/functional/enum-array/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/enum-array/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/extended-where/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/extended-where/_fixture/generated/contract.d.ts index 46cc330e1259..63699e9e7fd8 100644 --- a/test/integration/test/ports/prisma/functional/extended-where/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/extended-where/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/filter-count-relations/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/filter-count-relations/_fixture/generated/contract.d.ts index 21627ca2aa38..7aacc0ad34e5 100644 --- a/test/integration/test/ports/prisma/functional/filter-count-relations/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/filter-count-relations/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/find-unique-or-throw-batching/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/find-unique-or-throw-batching/_fixture/generated/contract.d.ts index 7644154c9ca3..733c185f5013 100644 --- a/test/integration/test/ports/prisma/functional/find-unique-or-throw-batching/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/find-unique-or-throw-batching/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/handle-int-overflow/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/handle-int-overflow/_fixture/generated/contract.d.ts index c98ab2e77d2d..e340e73b2c66 100644 --- a/test/integration/test/ports/prisma/functional/handle-int-overflow/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/handle-int-overflow/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/interactive-transactions/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/interactive-transactions/_fixture/generated/contract.d.ts index 4211db17012c..cf12fd1ccf99 100644 --- a/test/integration/test/ports/prisma/functional/interactive-transactions/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/interactive-transactions/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-11974/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-11974/_fixture/generated/contract.d.ts index 37fc9a76616a..97ceb62bce90 100644 --- a/test/integration/test/ports/prisma/functional/issues-11974/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-11974/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-12378/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-12378/_fixture/generated/contract.d.ts index b90ea232fcd0..b6c0135f82db 100644 --- a/test/integration/test/ports/prisma/functional/issues-12378/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-12378/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-12557/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-12557/_fixture/generated/contract.d.ts index 327adad04545..e267b9fbf53d 100644 --- a/test/integration/test/ports/prisma/functional/issues-12557/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-12557/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-12572/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-12572/_fixture/generated/contract.d.ts index 16d065527121..092ff0a41657 100644 --- a/test/integration/test/ports/prisma/functional/issues-12572/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-12572/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-14271/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-14271/_fixture/generated/contract.d.ts index 5bd11f9075b3..776d09c36693 100644 --- a/test/integration/test/ports/prisma/functional/issues-14271/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-14271/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-14954-date-batch/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-14954-date-batch/_fixture/generated/contract.d.ts index 2cc1d684028c..8cc1f039f7e5 100644 --- a/test/integration/test/ports/prisma/functional/issues-14954-date-batch/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-14954-date-batch/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-15044/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-15044/_fixture/generated/contract.d.ts index 59fab6cc491a..53fcbd1f40c4 100644 --- a/test/integration/test/ports/prisma/functional/issues-15044/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-15044/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-16535-select-enum/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-16535-select-enum/_fixture/generated/contract.d.ts index 4484a06ad9e5..b10034295419 100644 --- a/test/integration/test/ports/prisma/functional/issues-16535-select-enum/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-16535-select-enum/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-17005-args-type-conflict/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-17005-args-type-conflict/_fixture/generated/contract.d.ts index 529ba9b4c3b3..899ef36f3ea5 100644 --- a/test/integration/test/ports/prisma/functional/issues-17005-args-type-conflict/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-17005-args-type-conflict/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-17030-args-type-conflict/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-17030-args-type-conflict/_fixture/generated/contract.d.ts index 5f618d17417e..afcea3e8c0b9 100644 --- a/test/integration/test/ports/prisma/functional/issues-17030-args-type-conflict/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-17030-args-type-conflict/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-18970-invalid-date/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-18970-invalid-date/_fixture/generated/contract.d.ts index 950f64e6d3f7..2da935d47b37 100644 --- a/test/integration/test/ports/prisma/functional/issues-18970-invalid-date/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-18970-invalid-date/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-20261-group-by-shortcut/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-20261-group-by-shortcut/_fixture/generated/contract.d.ts index b1354cdfcc8f..fb1316ae6a87 100644 --- a/test/integration/test/ports/prisma/functional/issues-20261-group-by-shortcut/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-20261-group-by-shortcut/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-21352-id-does-not-exist/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-21352-id-does-not-exist/_fixture/generated/contract.d.ts index c0ead042cf2b..5434379f5365 100644 --- a/test/integration/test/ports/prisma/functional/issues-21352-id-does-not-exist/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-21352-id-does-not-exist/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-21454-type-in-json/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-21454-type-in-json/_fixture/generated/contract.d.ts index 53a418f2744b..a370f620a41f 100644 --- a/test/integration/test/ports/prisma/functional/issues-21454-type-in-json/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-21454-type-in-json/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-21631-batching-in-transaction/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-21631-batching-in-transaction/_fixture/generated/contract.d.ts index 30fb0c6eec54..173b7a596d8c 100644 --- a/test/integration/test/ports/prisma/functional/issues-21631-batching-in-transaction/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-21631-batching-in-transaction/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-22098-column-does-not-exist/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-22098-column-does-not-exist/_fixture/generated/contract.d.ts index 86881b4b8000..3843728413e4 100644 --- a/test/integration/test/ports/prisma/functional/issues-22098-column-does-not-exist/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-22098-column-does-not-exist/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-22610-parallel-batch/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-22610-parallel-batch/_fixture/generated/contract.d.ts index b08e3df1d6c1..fdab25752475 100644 --- a/test/integration/test/ports/prisma/functional/issues-22610-parallel-batch/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-22610-parallel-batch/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-23201-non-ascii-comments/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-23201-non-ascii-comments/_fixture/generated/contract.d.ts index ed6fb45414cc..bd02d0c85759 100644 --- a/test/integration/test/ports/prisma/functional/issues-23201-non-ascii-comments/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-23201-non-ascii-comments/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-23902/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-23902/_fixture/generated/contract.d.ts index 070c33800497..6fa153ed15b6 100644 --- a/test/integration/test/ports/prisma/functional/issues-23902/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-23902/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-25404/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-25404/_fixture/generated/contract.d.ts index 528e18e6743f..f5f43433daf3 100644 --- a/test/integration/test/ports/prisma/functional/issues-25404/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-25404/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-27455-bytes-id/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-27455-bytes-id/_fixture/generated/contract.d.ts index b480a5ce96be..ecce1b00f57c 100644 --- a/test/integration/test/ports/prisma/functional/issues-27455-bytes-id/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-27455-bytes-id/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-27511-include-enum-array/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-27511-include-enum-array/_fixture/generated/contract.d.ts index a0e42cb97b9c..1df3f2ead058 100644 --- a/test/integration/test/ports/prisma/functional/issues-27511-include-enum-array/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-27511-include-enum-array/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-28151-broken-nested-set/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-28151-broken-nested-set/_fixture/generated/contract.d.ts index 5e665b01e8c7..ae808e2b93b3 100644 --- a/test/integration/test/ports/prisma/functional/issues-28151-broken-nested-set/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-28151-broken-nested-set/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-28192-pg-historical-dates/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-28192-pg-historical-dates/_fixture/generated/contract.d.ts index da783eb0c472..0775abedf506 100644 --- a/test/integration/test/ports/prisma/functional/issues-28192-pg-historical-dates/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-28192-pg-historical-dates/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-28591-mapped-enums/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-28591-mapped-enums/_fixture/generated/contract.d.ts index e5985d989e3f..11e52f6ac811 100644 --- a/test/integration/test/ports/prisma/functional/issues-28591-mapped-enums/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-28591-mapped-enums/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-29010-bigint-precision-relation-joins/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-29010-bigint-precision-relation-joins/_fixture/generated/contract.d.ts index a3c22de0b9b9..1320be3309ed 100644 --- a/test/integration/test/ports/prisma/functional/issues-29010-bigint-precision-relation-joins/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-29010-bigint-precision-relation-joins/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-29174-jsonb-parameter-regression/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-29174-jsonb-parameter-regression/_fixture/generated/contract.d.ts index 13055c8029f2..c60df96502c9 100644 --- a/test/integration/test/ports/prisma/functional/issues-29174-jsonb-parameter-regression/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-29174-jsonb-parameter-regression/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-29176-cursor-parameter-regression/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-29176-cursor-parameter-regression/_fixture/generated/contract.d.ts index ad1a5e376443..45095ed7753a 100644 --- a/test/integration/test/ports/prisma/functional/issues-29176-cursor-parameter-regression/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-29176-cursor-parameter-regression/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-29254-query-plan-cache-mutation/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-29254-query-plan-cache-mutation/_fixture/generated/contract.d.ts index 2a2a8f62fcb0..b5ad822ee68e 100644 --- a/test/integration/test/ports/prisma/functional/issues-29254-query-plan-cache-mutation/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-29254-query-plan-cache-mutation/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-29267-uint8array-in-json/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-29267-uint8array-in-json/_fixture/generated/contract.d.ts index 883d3b4d9f57..9ed0088fa80c 100644 --- a/test/integration/test/ports/prisma/functional/issues-29267-uint8array-in-json/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-29267-uint8array-in-json/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-29309-datetime-cursor/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-29309-datetime-cursor/_fixture/generated/contract.d.ts index cd234e561790..288997fa17b1 100644 --- a/test/integration/test/ports/prisma/functional/issues-29309-datetime-cursor/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-29309-datetime-cursor/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-29331-query-plan-cache-bloat/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-29331-query-plan-cache-bloat/_fixture/generated/contract.d.ts index caf7a2c44533..36c0f238ddb9 100644 --- a/test/integration/test/ports/prisma/functional/issues-29331-query-plan-cache-bloat/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-29331-query-plan-cache-bloat/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-4004/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-4004/_fixture/generated/contract.d.ts index effc0e725a96..4f66bf07fbcf 100644 --- a/test/integration/test/ports/prisma/functional/issues-4004/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-4004/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-5952-decimal-batch/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-5952-decimal-batch/_fixture/generated/contract.d.ts index 46fe92e809d3..71aa0b53ce19 100644 --- a/test/integration/test/ports/prisma/functional/issues-5952-decimal-batch/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-5952-decimal-batch/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-TML-1664-invalid-enum-value-error/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-TML-1664-invalid-enum-value-error/_fixture/generated/contract.d.ts index c6e241e32a4b..eae2fadeeb85 100644 --- a/test/integration/test/ports/prisma/functional/issues-TML-1664-invalid-enum-value-error/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-TML-1664-invalid-enum-value-error/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-TML-1664-unknown-enum-value-read-error/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-TML-1664-unknown-enum-value-read-error/_fixture/generated/contract.d.ts index 3ed227116118..1cd4156e2777 100644 --- a/test/integration/test/ports/prisma/functional/issues-TML-1664-unknown-enum-value-read-error/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-TML-1664-unknown-enum-value-read-error/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/issues-unmapped-driver-error-user-facing/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/issues-unmapped-driver-error-user-facing/_fixture/generated/contract.d.ts index 5af09468cdc6..79cc33198df7 100644 --- a/test/integration/test/ports/prisma/functional/issues-unmapped-driver-error-user-facing/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/issues-unmapped-driver-error-user-facing/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/json-fields/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/json-fields/_fixture/generated/contract.d.ts index 1cb6cfbe1690..dfe4897e564f 100644 --- a/test/integration/test/ports/prisma/functional/json-fields/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/json-fields/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/large-floats/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/large-floats/_fixture/generated/contract.d.ts index bde264cf75a4..babaa5545f57 100644 --- a/test/integration/test/ports/prisma/functional/large-floats/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/large-floats/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/legacy-aggregations/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/legacy-aggregations/_fixture/generated/contract.d.ts index 1408ec3616ed..458c20a79f64 100644 --- a/test/integration/test/ports/prisma/functional/legacy-aggregations/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/legacy-aggregations/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/legacy-json/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/legacy-json/_fixture/generated/contract.d.ts index 31babd5e3885..8d788b46ba71 100644 --- a/test/integration/test/ports/prisma/functional/legacy-json/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/legacy-json/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/legacy-optional-relation-filters/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/legacy-optional-relation-filters/_fixture/generated/contract.d.ts index 7974d418c996..a848ef130b61 100644 --- a/test/integration/test/ports/prisma/functional/legacy-optional-relation-filters/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/legacy-optional-relation-filters/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/methods-count/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/methods-count/_fixture/generated/contract.d.ts index e9c36a18d2ff..4c9c5034667c 100644 --- a/test/integration/test/ports/prisma/functional/methods-count/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/methods-count/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/methods-createMany/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/methods-createMany/_fixture/generated/contract.d.ts index f8e0bb0aedce..36832ecba76c 100644 --- a/test/integration/test/ports/prisma/functional/methods-createMany/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/methods-createMany/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/methods-createManyAndReturn/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/methods-createManyAndReturn/_fixture/generated/contract.d.ts index f8e0bb0aedce..36832ecba76c 100644 --- a/test/integration/test/ports/prisma/functional/methods-createManyAndReturn/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/methods-createManyAndReturn/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/methods-findFirstOrThrow/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/methods-findFirstOrThrow/_fixture/generated/contract.d.ts index ae5419d52224..4bb3b1e10356 100644 --- a/test/integration/test/ports/prisma/functional/methods-findFirstOrThrow/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/methods-findFirstOrThrow/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/methods-findUniqueOrThrow/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/methods-findUniqueOrThrow/_fixture/generated/contract.d.ts index 448e6c77c0ef..014f5adad549 100644 --- a/test/integration/test/ports/prisma/functional/methods-findUniqueOrThrow/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/methods-findUniqueOrThrow/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/methods-updateManyAndReturn/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/methods-updateManyAndReturn/_fixture/generated/contract.d.ts index f8e0bb0aedce..36832ecba76c 100644 --- a/test/integration/test/ports/prisma/functional/methods-updateManyAndReturn/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/methods-updateManyAndReturn/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/methods-upsert-native-atomic/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/methods-upsert-native-atomic/_fixture/generated/contract.d.ts index bf6edd0ed9c7..0615c49bb267 100644 --- a/test/integration/test/ports/prisma/functional/methods-upsert-native-atomic/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/methods-upsert-native-atomic/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/methods-upsert-simple/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/methods-upsert-simple/_fixture/generated/contract.d.ts index d1c238c1128f..3ddd152f7177 100644 --- a/test/integration/test/ports/prisma/functional/methods-upsert-simple/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/methods-upsert-simple/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/mixed-string-uuid-datetime-list-inputs/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/mixed-string-uuid-datetime-list-inputs/_fixture/generated/contract.d.ts index dd7ac943c13d..4fb8ce137db0 100644 --- a/test/integration/test/ports/prisma/functional/mixed-string-uuid-datetime-list-inputs/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/mixed-string-uuid-datetime-list-inputs/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/multi-schema/_fixture/different-names/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/multi-schema/_fixture/different-names/generated/contract.d.ts index cdee836840af..737c9dbc60dc 100644 --- a/test/integration/test/ports/prisma/functional/multi-schema/_fixture/different-names/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/multi-schema/_fixture/different-names/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/multi-schema/_fixture/identical-names/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/multi-schema/_fixture/identical-names/generated/contract.d.ts index 898213b28802..0bfec11dc123 100644 --- a/test/integration/test/ports/prisma/functional/multi-schema/_fixture/identical-names/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/multi-schema/_fixture/identical-names/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/multi-schema/_fixture/no-map/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/multi-schema/_fixture/no-map/generated/contract.d.ts index e1433a494871..40077361098a 100644 --- a/test/integration/test/ports/prisma/functional/multi-schema/_fixture/no-map/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/multi-schema/_fixture/no-map/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/multiple-types/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/multiple-types/_fixture/generated/contract.d.ts index 3cd4788e4ad4..567eb912dac0 100644 --- a/test/integration/test/ports/prisma/functional/multiple-types/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/multiple-types/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/optimistic-concurrency-control/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/optimistic-concurrency-control/_fixture/generated/contract.d.ts index dd407651b692..d0f59318c140 100644 --- a/test/integration/test/ports/prisma/functional/optimistic-concurrency-control/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/optimistic-concurrency-control/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/referential-actions-set-default-1to1/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/referential-actions-set-default-1to1/_fixture/generated/contract.d.ts index a01a00e82104..c1288389d243 100644 --- a/test/integration/test/ports/prisma/functional/referential-actions-set-default-1to1/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/referential-actions-set-default-1to1/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/referential-actions-set-default-1ton/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/referential-actions-set-default-1ton/_fixture/generated/contract.d.ts index a01a00e82104..c1288389d243 100644 --- a/test/integration/test/ports/prisma/functional/referential-actions-set-default-1ton/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/referential-actions-set-default-1ton/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/relation-mode-17255-mixed-actions/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/relation-mode-17255-mixed-actions/_fixture/generated/contract.d.ts index 91d3bd762bce..ca4cce7b95f5 100644 --- a/test/integration/test/ports/prisma/functional/relation-mode-17255-mixed-actions/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/relation-mode-17255-mixed-actions/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/relation-mode-17255-same-actions/_fixture/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/relation-mode-17255-same-actions/_fixture/generated/contract.d.ts index b0d7e62a49f9..4d6b7d7ff483 100644 --- a/test/integration/test/ports/prisma/functional/relation-mode-17255-same-actions/_fixture/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/relation-mode-17255-same-actions/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/cascade-map/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/cascade-map/generated/contract.d.ts index b90d5cefe578..7601450ed2e6 100644 --- a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/cascade-map/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/cascade-map/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/cascade-plain/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/cascade-plain/generated/contract.d.ts index fba447be4251..3c6ea4d3b332 100644 --- a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/cascade-plain/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/cascade-plain/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/noaction-map/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/noaction-map/generated/contract.d.ts index c2cff47b28c2..5ab09e787c40 100644 --- a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/noaction-map/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/noaction-map/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/noaction-plain/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/noaction-plain/generated/contract.d.ts index a67b6cff0c14..33e0af81d675 100644 --- a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/noaction-plain/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/noaction-plain/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/restrict-map/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/restrict-map/generated/contract.d.ts index 94e3a3823f5b..81d8fb8a3c5e 100644 --- a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/restrict-map/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/restrict-map/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/restrict-plain/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/restrict-plain/generated/contract.d.ts index 5ed87ed7191b..8cab1ddc3d07 100644 --- a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/restrict-plain/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/restrict-plain/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/setnull-map/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/setnull-map/generated/contract.d.ts index 2097648c3fb3..20a8cb76ca6f 100644 --- a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/setnull-map/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/setnull-map/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/setnull-plain/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/setnull-plain/generated/contract.d.ts index 099caae3607d..a647c56cac03 100644 --- a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/setnull-plain/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-1/_fixture/setnull-plain/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/cascade-map/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/cascade-map/generated/contract.d.ts index 8e458f658f7a..0626d0b46a7b 100644 --- a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/cascade-map/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/cascade-map/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/cascade-plain/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/cascade-plain/generated/contract.d.ts index b24d542665c6..ff88c42ce651 100644 --- a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/cascade-plain/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/cascade-plain/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/noaction-map/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/noaction-map/generated/contract.d.ts index 823d652e6687..b01aa6eda6c8 100644 --- a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/noaction-map/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/noaction-map/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/noaction-plain/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/noaction-plain/generated/contract.d.ts index 841c08875311..c1339c056096 100644 --- a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/noaction-plain/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/noaction-plain/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/restrict-map/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/restrict-map/generated/contract.d.ts index 8d02e547499c..1832ce2fd345 100644 --- a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/restrict-map/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/restrict-map/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/restrict-plain/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/restrict-plain/generated/contract.d.ts index 63be9799393d..9cdbc015bd1c 100644 --- a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/restrict-plain/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/restrict-plain/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/setnull-map/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/setnull-map/generated/contract.d.ts index 9002e112e6c1..9dd53d47f9ea 100644 --- a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/setnull-map/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/setnull-map/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/setnull-plain/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/setnull-plain/generated/contract.d.ts index 3d89b9baefb5..f0eb902c3aad 100644 --- a/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/setnull-plain/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/relation-mode-gh-1-to-n/_fixture/setnull-plain/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/relation-mode-gh-m-to-n/_fixture/cascade-nomap/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/relation-mode-gh-m-to-n/_fixture/cascade-nomap/generated/contract.d.ts index 09a3d1bea5f8..d84b6b390d0b 100644 --- a/test/integration/test/ports/prisma/functional/relation-mode-gh-m-to-n/_fixture/cascade-nomap/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/relation-mode-gh-m-to-n/_fixture/cascade-nomap/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/relation-mode-gh-m-to-n/_fixture/default-nomap/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/relation-mode-gh-m-to-n/_fixture/default-nomap/generated/contract.d.ts index eb44ba9aaeda..608d502c5d4d 100644 --- a/test/integration/test/ports/prisma/functional/relation-mode-gh-m-to-n/_fixture/default-nomap/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/relation-mode-gh-m-to-n/_fixture/default-nomap/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/relation-mode-gh-m-to-n/_fixture/noaction-nomap/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/relation-mode-gh-m-to-n/_fixture/noaction-nomap/generated/contract.d.ts index eb44ba9aaeda..608d502c5d4d 100644 --- a/test/integration/test/ports/prisma/functional/relation-mode-gh-m-to-n/_fixture/noaction-nomap/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/relation-mode-gh-m-to-n/_fixture/noaction-nomap/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/ports/prisma/functional/relation-mode-gh-m-to-n/_fixture/restrict-nomap/generated/contract.d.ts b/test/integration/test/ports/prisma/functional/relation-mode-gh-m-to-n/_fixture/restrict-nomap/generated/contract.d.ts index f2205b3b101d..7229ab74b167 100644 --- a/test/integration/test/ports/prisma/functional/relation-mode-gh-m-to-n/_fixture/restrict-nomap/generated/contract.d.ts +++ b/test/integration/test/ports/prisma/functional/relation-mode-gh-m-to-n/_fixture/restrict-nomap/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/sql-builder/fixtures/generated-no-pgvector/contract.d.ts b/test/integration/test/sql-builder/fixtures/generated-no-pgvector/contract.d.ts index b778ac914982..d08b896a147a 100644 --- a/test/integration/test/sql-builder/fixtures/generated-no-pgvector/contract.d.ts +++ b/test/integration/test/sql-builder/fixtures/generated-no-pgvector/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/sql-builder/fixtures/generated/contract.d.ts b/test/integration/test/sql-builder/fixtures/generated/contract.d.ts index b089e4982b91..0fc1e5ff2b7d 100644 --- a/test/integration/test/sql-builder/fixtures/generated/contract.d.ts +++ b/test/integration/test/sql-builder/fixtures/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { CodecTypes as PgVectorTypes, Vector } from '@internal/extension-pgvector/codec-types'; import type { QueryOperationTypes as PgVectorQueryOperationTypes } from '@internal/extension-pgvector/operation-types'; import type { @@ -21,6 +20,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -44,7 +44,7 @@ export type ProfileHash = export type CodecTypes = PgTypes & PgVectorTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps & +export type QueryOperationTypes = PgTargetQueryOps & PgVectorQueryOperationTypes; export type AggregateTypes = { readonly avg: { diff --git a/test/integration/test/sql-orm-client/fixtures/execution-defaulted-tags/generated/contract.d.ts b/test/integration/test/sql-orm-client/fixtures/execution-defaulted-tags/generated/contract.d.ts index d4ceb38c5faa..d10d7b448c90 100644 --- a/test/integration/test/sql-orm-client/fixtures/execution-defaulted-tags/generated/contract.d.ts +++ b/test/integration/test/sql-orm-client/fixtures/execution-defaulted-tags/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/sql-orm-client/fixtures/generated/contract.d.ts b/test/integration/test/sql-orm-client/fixtures/generated/contract.d.ts index a4bf26601300..cee4ca50325c 100644 --- a/test/integration/test/sql-orm-client/fixtures/generated/contract.d.ts +++ b/test/integration/test/sql-orm-client/fixtures/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { CodecTypes as PgVectorTypes, Vector } from '@internal/extension-pgvector/codec-types'; import type { QueryOperationTypes as PgVectorQueryOperationTypes } from '@internal/extension-pgvector/operation-types'; import type { @@ -21,6 +20,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -44,7 +44,7 @@ export type ProfileHash = export type CodecTypes = PgTypes & PgVectorTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps & +export type QueryOperationTypes = PgTargetQueryOps & PgVectorQueryOperationTypes; export type AggregateTypes = { readonly avg: { diff --git a/test/integration/test/sql-orm-client/fixtures/integer-representation/generated/contract.d.ts b/test/integration/test/sql-orm-client/fixtures/integer-representation/generated/contract.d.ts index 4aff8d1742da..e2511480b814 100644 --- a/test/integration/test/sql-orm-client/fixtures/integer-representation/generated/contract.d.ts +++ b/test/integration/test/sql-orm-client/fixtures/integer-representation/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/sql-orm-client/fixtures/junction-namespaces/generated/contract.d.ts b/test/integration/test/sql-orm-client/fixtures/junction-namespaces/generated/contract.d.ts index 4fb985207f8f..2ce0337ee2fe 100644 --- a/test/integration/test/sql-orm-client/fixtures/junction-namespaces/generated/contract.d.ts +++ b/test/integration/test/sql-orm-client/fixtures/junction-namespaces/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/sql-orm-client/fixtures/mn-psl/generated/contract.d.ts b/test/integration/test/sql-orm-client/fixtures/mn-psl/generated/contract.d.ts index 3a0b37f0b552..e4c037423e7e 100644 --- a/test/integration/test/sql-orm-client/fixtures/mn-psl/generated/contract.d.ts +++ b/test/integration/test/sql-orm-client/fixtures/mn-psl/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/sql-orm-client/fixtures/non-identifier-names/generated/contract.d.ts b/test/integration/test/sql-orm-client/fixtures/non-identifier-names/generated/contract.d.ts index 4c58748911db..ddba74643089 100644 --- a/test/integration/test/sql-orm-client/fixtures/non-identifier-names/generated/contract.d.ts +++ b/test/integration/test/sql-orm-client/fixtures/non-identifier-names/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/sql-orm-client/fixtures/polymorphism/generated/contract.d.ts b/test/integration/test/sql-orm-client/fixtures/polymorphism/generated/contract.d.ts index bc07ece69efb..249a5d308ebb 100644 --- a/test/integration/test/sql-orm-client/fixtures/polymorphism/generated/contract.d.ts +++ b/test/integration/test/sql-orm-client/fixtures/polymorphism/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/sql-orm-client/fixtures/scalar-lists/generated/contract.d.ts b/test/integration/test/sql-orm-client/fixtures/scalar-lists/generated/contract.d.ts index aa7259ff0eae..20cf3190c8df 100644 --- a/test/integration/test/sql-orm-client/fixtures/scalar-lists/generated/contract.d.ts +++ b/test/integration/test/sql-orm-client/fixtures/scalar-lists/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/sql-orm-client/fixtures/self-relations/generated/contract.d.ts b/test/integration/test/sql-orm-client/fixtures/self-relations/generated/contract.d.ts index 76af669fb02e..29d418c6079a 100644 --- a/test/integration/test/sql-orm-client/fixtures/self-relations/generated/contract.d.ts +++ b/test/integration/test/sql-orm-client/fixtures/self-relations/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -41,7 +41,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/temporal-defaults/_fixture-timestamp/generated/contract.d.ts b/test/integration/test/temporal-defaults/_fixture-timestamp/generated/contract.d.ts index 935bbdb09043..da7b48511c99 100644 --- a/test/integration/test/temporal-defaults/_fixture-timestamp/generated/contract.d.ts +++ b/test/integration/test/temporal-defaults/_fixture-timestamp/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { diff --git a/test/integration/test/temporal-defaults/_fixture/generated/contract.d.ts b/test/integration/test/temporal-defaults/_fixture/generated/contract.d.ts index 796a4e707da4..0c5238a79d36 100644 --- a/test/integration/test/temporal-defaults/_fixture/generated/contract.d.ts +++ b/test/integration/test/temporal-defaults/_fixture/generated/contract.d.ts @@ -1,7 +1,6 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; import type { Bit, Char, @@ -19,6 +18,7 @@ import type { VarBit, Varchar, } from '@internal/target-postgres/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, @@ -42,7 +42,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { From 8887cbdb73c1812840293b05d7edf34ddc51c25e Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 18 Sep 2026 14:52:46 +0200 Subject: [PATCH 06/36] test(integration): exercise Postgres full-text search through the SQL builder Six comment rows differing by a word carry the cases: a word match, a quoted phrase that only matches when the words are adjacent, `-word` exclusion, `german` as the language, `fullTextRank` ordering the row with three occurrences first, and `fullTextHeadline` marking the matched word up. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../sql-builder/extension-functions.test.ts | 60 ++++++++++++++++++- test/integration/test/sql-builder/setup.ts | 8 ++- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/test/integration/test/sql-builder/extension-functions.test.ts b/test/integration/test/sql-builder/extension-functions.test.ts index 0f528001c485..7c6a1c7779b4 100644 --- a/test/integration/test/sql-builder/extension-functions.test.ts +++ b/test/integration/test/sql-builder/extension-functions.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from 'vitest'; import { setupIntegrationTest, timeouts } from './setup'; -describe('integration: ilike (adapter operation)', { timeout: timeouts.databaseOperation }, () => { +describe('integration: ilike (target operation)', { timeout: timeouts.databaseOperation }, () => { const { db, runtime } = setupIntegrationTest(); it('ilike filters case-insensitively in WHERE', async () => { @@ -83,3 +83,61 @@ describe('integration: extension functions', { timeout: timeouts.databaseOperati expect(rows.some((r) => r.id === 1)).toBe(true); }); }); + +describe('integration: full-text search', { timeout: timeouts.databaseOperation }, () => { + const { db, runtime } = setupIntegrationTest(); + + const idsMatching = async (query: string, language?: 'german') => { + const rows = await runtime().query( + db() + .public.comments.select('id') + .where((f, fns) => + language === undefined + ? fns.fullTextMatches(f.body, query) + : fns.fullTextMatches(f.body, query, language), + ) + .build(), + ); + return rows.map((row) => row.id).sort((a, b) => a - b); + }; + + it('fullTextMatches keeps rows containing the word and drops the rest', async () => { + expect(await idsMatching('alice')).toEqual([101, 102, 106]); + }); + + it('fullTextMatches on a quoted phrase requires the words to be adjacent', async () => { + expect(await idsMatching('"quick brown"')).toEqual([104]); + }); + + it('fullTextMatches excludes rows carrying a -prefixed word', async () => { + expect(await idsMatching('alice -manuscript')).toEqual([101, 102]); + }); + + it('fullTextMatches accepts a non-default language', async () => { + expect(await idsMatching('alice', 'german')).toEqual([101, 102, 106]); + }); + + it('fullTextRank ranks the row with more occurrences first', async () => { + const rows = await runtime().query( + db() + .public.comments.select('id') + .where((f, fns) => fns.fullTextMatches(f.body, 'alice')) + .orderBy((f, fns) => fns.fullTextRank(f.body, 'alice'), { direction: 'desc' }) + .build(), + ); + expect(rows.map((row) => row.id)[0]).toBe(102); + }); + + it('fullTextHeadline marks the matched word up', async () => { + const row = await runtime() + .query( + db() + .public.comments.select('id') + .select('snippet', (f, fns) => fns.fullTextHeadline(f.body, 'alice')) + .where((f, fns) => fns.eq(f.id, 101)) + .build(), + ) + .firstOrThrow(); + expect(row.snippet).toBe('alice wrote the report'); + }); +}); diff --git a/test/integration/test/sql-builder/setup.ts b/test/integration/test/sql-builder/setup.ts index 41502d840447..c56c17bf167e 100644 --- a/test/integration/test/sql-builder/setup.ts +++ b/test/integration/test/sql-builder/setup.ts @@ -89,7 +89,13 @@ export function setupIntegrationTest() { INSERT INTO comments (id, body, post_id) VALUES (1, 'Great post!', 1), (2, 'Nice work', 1), - (3, 'Interesting', 3) + (3, 'Interesting', 3), + (101, 'alice wrote the report', 1), + (102, 'alice met alice and alice again', 1), + (103, 'bob wrote the report', 1), + (104, 'the quick brown fox jumps', 1), + (105, 'a brown dog and a quick cat', 1), + (106, 'alice manuscript draft', 1) `); await c.query(` INSERT INTO profiles (id, user_id, bio) VALUES From 1e121a68d2222513f8314ae6fd9c5371cddf3279 Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 18 Sep 2026 14:54:42 +0200 Subject: [PATCH 07/36] test(integration): cover full-text search through the ORM and at the type level The ORM cases run `fullTextMatches` in `where` and `fullTextRank(...).desc()` in `orderBy` against a real database. The type-level cases pin each operation's return codec and check that the language argument accepts `german` and rejects a name Postgres does not ship. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../playground/extension-functions.test-d.ts | 43 +++++++++++++++ .../extension-operations.test-d.ts | 41 ++++++++++++++ .../extension-operations.test.ts | 53 +++++++++++++++++++ 3 files changed, 137 insertions(+) diff --git a/test/integration/test/sql-builder/playground/extension-functions.test-d.ts b/test/integration/test/sql-builder/playground/extension-functions.test-d.ts index 2a1a0f5fbd5f..53f9cc27f1c7 100644 --- a/test/integration/test/sql-builder/playground/extension-functions.test-d.ts +++ b/test/integration/test/sql-builder/playground/extension-functions.test-d.ts @@ -46,3 +46,46 @@ test('ilike returns boolean expression', () => { return result; }); }); + +test('fullTextMatches returns a non-nullable boolean expression', () => { + db.public.users.select('id').where((f, fns) => { + const result = fns.fullTextMatches(f.name, 'alice'); + expectTypeOf(result).toEqualTypeOf>(); + return result; + }); +}); + +test('fullTextRank returns a non-nullable float4 expression', () => { + const ranked = db.public.users + .select('id') + .select('rank', (f, fns) => { + const result = fns.fullTextRank(f.name, 'alice'); + expectTypeOf(result).toEqualTypeOf>(); + return result; + }) + .build(); + + expectTypeOf(ranked).toEqualTypeOf>(); +}); + +test('fullTextHeadline returns a non-nullable text expression', () => { + const headlined = db.public.users + .select('id') + .select('snippet', (f, fns) => { + const result = fns.fullTextHeadline(f.name, 'alice'); + expectTypeOf(result).toEqualTypeOf>(); + return result; + }) + .build(); + + expectTypeOf(headlined).toEqualTypeOf>(); +}); + +test('the language argument is one of the configurations Postgres ships with', () => { + db.public.users.select('id').where((f, fns) => fns.fullTextMatches(f.name, 'alice', 'german')); + + db.public.users + .select('id') + // @ts-expect-error 'klingon' is not a PostgreSQL text-search configuration + .where((f, fns) => fns.fullTextMatches(f.name, 'alice', 'klingon')); +}); diff --git a/test/integration/test/sql-orm-client/extension-operations.test-d.ts b/test/integration/test/sql-orm-client/extension-operations.test-d.ts index 7a79b6f6d4a5..ae3b83d25d23 100644 --- a/test/integration/test/sql-orm-client/extension-operations.test-d.ts +++ b/test/integration/test/sql-orm-client/extension-operations.test-d.ts @@ -143,3 +143,44 @@ describe('vector field itself: only equality trait', () => { expectTypeOf().not.toHaveProperty('asc'); }); }); + +describe('full-text search operations on text fields', () => { + test('text field exposes the full-text operations', () => { + expectTypeOf().toHaveProperty('fullTextMatches'); + expectTypeOf().toHaveProperty('fullTextRank'); + expectTypeOf().toHaveProperty('fullTextHeadline'); + }); + + test('numeric and vector fields do not', () => { + expectTypeOf().not.toHaveProperty('fullTextMatches'); + expectTypeOf().not.toHaveProperty('fullTextMatches'); + }); + + test('fullTextMatches returns a predicate expression', () => { + type Fn = PostAccessor['title']['fullTextMatches']; + expectTypeOf().toBeFunction(); + expectTypeOf>().toExtend< + import('@internal/sql-relational-core/ast').AnyExpression + >(); + }); + + test('fullTextRank returns numeric comparison methods, so it can order results', () => { + type RankResult = ReturnType; + expectTypeOf().toEqualTypeOf< + ComparisonMethods + >(); + expectTypeOf().toHaveProperty('desc'); + }); + + test('fullTextHeadline returns textual comparison methods', () => { + type HeadlineResult = ReturnType; + expectTypeOf().toHaveProperty('like'); + }); + + test('the language argument is one of the configurations Postgres ships with', () => { + const title = null as unknown as PostAccessor['title']; + title.fullTextMatches('alice', 'german'); + // @ts-expect-error 'klingon' is not a PostgreSQL text-search configuration + title.fullTextMatches('alice', 'klingon'); + }); +}); diff --git a/test/integration/test/sql-orm-client/extension-operations.test.ts b/test/integration/test/sql-orm-client/extension-operations.test.ts index 3eeefe0ae6d7..0fc6256c3c15 100644 --- a/test/integration/test/sql-orm-client/extension-operations.test.ts +++ b/test/integration/test/sql-orm-client/extension-operations.test.ts @@ -81,3 +81,56 @@ describe('integration/extension-operations', () => { timeouts.spinUpPpgDev, ); }); + +describe('integration/full-text-search operations', () => { + const seedSearchablePosts = async (runtime: Parameters[0]) => { + await seedUsers(runtime, [{ id: 1, name: 'Alice', email: 'alice@test.com' }]); + await seedPosts(runtime, [ + { id: 1, title: 'alice wrote the report', userId: 1, views: 10, embedding: null }, + { id: 2, title: 'alice met alice and alice again', userId: 1, views: 20, embedding: null }, + { id: 3, title: 'bob wrote the report', userId: 1, views: 30, embedding: null }, + ]); + }; + + it( + 'filters posts by fullTextMatches in where()', + async () => { + await withCollectionRuntime(async (runtime) => { + await seedSearchablePosts(runtime); + + const results = await createPostsCollection(runtime) + .select('id', 'title') + .where((p) => p.title.fullTextMatches('alice')) + .orderBy((p) => p.id.asc()) + .all(); + + expect(results).toEqual([ + { id: 1, title: 'alice wrote the report' }, + { id: 2, title: 'alice met alice and alice again' }, + ]); + }); + }, + timeouts.spinUpPpgDev, + ); + + it( + 'orders posts by fullTextRank in orderBy()', + async () => { + await withCollectionRuntime(async (runtime) => { + await seedSearchablePosts(runtime); + + const results = await createPostsCollection(runtime) + .select('id', 'title') + .where((p) => p.title.fullTextMatches('alice')) + .orderBy((p) => p.title.fullTextRank('alice').desc()) + .all(); + + expect(results).toEqual([ + { id: 2, title: 'alice met alice and alice again' }, + { id: 1, title: 'alice wrote the report' }, + ]); + }); + }, + timeouts.spinUpPpgDev, + ); +}); From bbda9989395e3fa82956047b4b79d12db65c3e69 Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 18 Sep 2026 14:57:25 +0200 Subject: [PATCH 08/36] test(postgres): prove the GIN to_tsvector index plans and renders The target test authors `@@index(expression: "to_tsvector('english', \"text\")", type: "gin")` in PSL and checks the planner emits one `PostgresCreateIndex` carrying the access method and the expression verbatim. The byte assertion lives beside the renderer in the adapter, where the rest of the index DDL rendering is asserted. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../full-text-index-planning.test.ts | 139 ++++++++++++++++++ .../migrations/index-ddl-rendering.test.ts | 13 ++ 2 files changed, 152 insertions(+) create mode 100644 packages/3-targets/3-targets/postgres/test/migrations/full-text-index-planning.test.ts diff --git a/packages/3-targets/3-targets/postgres/test/migrations/full-text-index-planning.test.ts b/packages/3-targets/3-targets/postgres/test/migrations/full-text-index-planning.test.ts new file mode 100644 index 000000000000..9e05e7218cbe --- /dev/null +++ b/packages/3-targets/3-targets/postgres/test/migrations/full-text-index-planning.test.ts @@ -0,0 +1,139 @@ +/** + * A GIN index over `to_tsvector(...)`, authored in PSL, reaches the planner as + * a `PostgresCreateIndex` carrying the access method and the expression + * verbatim. The SQL bytes are asserted beside the renderer in the adapter + * package. + */ +import type { Contract } from '@internal/contract/types'; +import type { ExecuteRequestLowerer } from '@internal/family-sql/control-adapter'; +import { + APP_SPACE_ID, + assembleAuthoringContributions, +} from '@internal/framework-components/control'; +import { buildSymbolTable } from '@internal/psl-parser'; +import { parse } from '@internal/psl-parser/syntax'; +import type { SqlStorage } from '@internal/sql-contract/types'; +import { interpretPslDocumentToSqlContract } from '@internal/sql-contract-psl'; +import { describe, expect, it } from 'vitest'; +import { + postgresAuthoringEntityTypes, + postgresAuthoringPslBlockDescriptors, +} from '../../src/core/authoring'; +import { PostgresCreateIndex } from '../../src/core/ddl/nodes'; +import { postgresTargetDescriptorMeta } from '../../src/core/descriptor-meta'; +import { createPostgresMigrationPlanner } from '../../src/core/migrations/planner'; +import { postgresCreateNamespace } from '../../src/core/postgres-schema'; +import { PostgresDatabaseSchemaNode } from '../../src/core/schema-ir/postgres-database-schema-node'; +import { PostgresNamespaceSchemaNode } from '../../src/core/schema-ir/postgres-namespace-schema-node'; +import { PostgresTableSchemaNode } from '../../src/core/schema-ir/postgres-table-schema-node'; + +const SCHEMA = ` +model Message { + id Int @id + text String + @@index(expression: "to_tsvector('english', \\"text\\")", type: "gin", name: "message_text_search") +} +`; + +const assembled = assembleAuthoringContributions([ + { + authoring: { + entityTypes: postgresAuthoringEntityTypes, + pslBlockDescriptors: postgresAuthoringPslBlockDescriptors, + type: { + Int: { kind: 'typeConstructor', output: { codecId: 'pg/int4@1', nativeType: 'int4' } }, + String: { kind: 'typeConstructor', output: { codecId: 'pg/text@1', nativeType: 'text' } }, + }, + }, + }, +]); + +function authoredContract(): Contract { + const { document, sourceFile } = parse(SCHEMA); + const { table: symbolTable } = buildSymbolTable({ + document, + sourceFile, + pslBlockDescriptors: assembled.pslBlockDescriptors, + }); + const result = interpretPslDocumentToSqlContract({ + symbolTable, + sourceFile, + sourceId: 'schema.prisma', + capabilities: {}, + target: postgresTargetDescriptorMeta, + scalarColumnDescriptors: new Map([ + ['Int', { codecId: 'pg/int4@1', nativeType: 'int4' }], + ['String', { codecId: 'pg/text@1', nativeType: 'text' }], + ]), + authoringContributions: assembled, + composedExtensionContracts: new Map(), + createNamespace: postgresCreateNamespace, + }); + expect(result.ok).toBe(true); + if (!result.ok) throw new Error('PSL interpretation failed'); + return result.value; +} + +/** The table exists with no indexes, so only the index is left to plan. */ +function liveSchemaWithoutTheIndex(): PostgresDatabaseSchemaNode { + return new PostgresDatabaseSchemaNode({ + namespaces: { + public: new PostgresNamespaceSchemaNode({ + schemaName: 'public', + tables: { + Message: new PostgresTableSchemaNode({ + name: 'Message', + columns: { + id: { name: 'id', nativeType: 'int4', nullable: false }, + text: { name: 'text', nativeType: 'text', nullable: false }, + }, + primaryKey: { columns: ['id'] }, + foreignKeys: [], + uniques: [], + indexes: [], + rlsEnabled: false, + }), + }, + }), + }, + roles: [], + existingSchemas: ['public'], + pgVersion: 'unknown', + }); +} + +async function plannedCreateIndexNodes(): Promise { + const lowered: unknown[] = []; + const lowerer: ExecuteRequestLowerer = { + lower: () => ({ sql: 'stub', params: [] }), + lowerToExecuteRequest: async (ast) => { + lowered.push(ast); + return { sql: 'stub', params: [] }; + }, + }; + const result = createPostgresMigrationPlanner(lowerer).plan({ + contract: authoredContract(), + schema: liveSchemaWithoutTheIndex(), + policy: { allowedOperationClasses: ['additive', 'widening', 'destructive'] }, + fromContract: null, + frameworkComponents: [], + spaceId: APP_SPACE_ID, + snapshotsImportPath: '../../snapshots', + }); + expect(result.kind).toBe('success'); + if (result.kind !== 'success') return []; + await Promise.all(result.plan.operations); + return lowered.filter((node) => node instanceof PostgresCreateIndex); +} + +describe('a GIN index over to_tsvector, authored in PSL', () => { + it('plans one CREATE INDEX carrying the access method and the expression verbatim', async () => { + const nodes = await plannedCreateIndexNodes(); + expect(nodes).toHaveLength(1); + const node = nodes[0]!; + expect(node.type).toBe('gin'); + expect(node.elements).toEqual({ expression: `to_tsvector('english', "text")` }); + expect(node.table).toBe('Message'); + expect(node.name.startsWith('message_text_search')).toBe(true); + }); +}); diff --git a/packages/3-targets/6-adapters/postgres/test/migrations/index-ddl-rendering.test.ts b/packages/3-targets/6-adapters/postgres/test/migrations/index-ddl-rendering.test.ts index 624ed946d2a7..10407eadf4f4 100644 --- a/packages/3-targets/6-adapters/postgres/test/migrations/index-ddl-rendering.test.ts +++ b/packages/3-targets/6-adapters/postgres/test/migrations/index-ddl-rendering.test.ts @@ -177,6 +177,19 @@ describe('CreateIndexCall DDL rendering', () => { ); }); + it('renders a GIN index over to_tsvector, the shape a full-text predicate needs', async () => { + const call = new CreateIndexCall( + 'public', + 'message', + 'message_text_search', + { expression: `to_tsvector('english', "text")` }, + { type: 'gin' }, + ); + expect(await executeSql(call)).toBe( + `CREATE INDEX "message_text_search" ON "public"."message" USING "gin" (to_tsvector('english', "text"))`, + ); + }); + it('combines unique, USING, expression, WITH, and WHERE in clause order', async () => { const call = new CreateIndexCall( 'public', From d8e90825c231760724b0e9305bef221db448ef4e Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 18 Sep 2026 14:58:54 +0200 Subject: [PATCH 09/36] fix(test): narrow the interpreted contract to SQL storage in the index planner test Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../test/migrations/full-text-index-planning.test.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/3-targets/3-targets/postgres/test/migrations/full-text-index-planning.test.ts b/packages/3-targets/3-targets/postgres/test/migrations/full-text-index-planning.test.ts index 9e05e7218cbe..f62543f8a0c7 100644 --- a/packages/3-targets/3-targets/postgres/test/migrations/full-text-index-planning.test.ts +++ b/packages/3-targets/3-targets/postgres/test/migrations/full-text-index-planning.test.ts @@ -14,6 +14,7 @@ import { buildSymbolTable } from '@internal/psl-parser'; import { parse } from '@internal/psl-parser/syntax'; import type { SqlStorage } from '@internal/sql-contract/types'; import { interpretPslDocumentToSqlContract } from '@internal/sql-contract-psl'; +import { blindCast } from '@internal/utils/casts'; import { describe, expect, it } from 'vitest'; import { postgresAuthoringEntityTypes, @@ -71,7 +72,10 @@ function authoredContract(): Contract { }); expect(result.ok).toBe(true); if (!result.ok) throw new Error('PSL interpretation failed'); - return result.value; + return blindCast< + Contract, + 'the interpreter returns the framework Contract supertype; a Postgres schema is SQL storage' + >(result.value); } /** The table exists with no indexes, so only the index is left to plan. */ From 1e7fc7c58c172ec7c32f189f53230586e1b1f705 Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 18 Sep 2026 15:05:47 +0200 Subject: [PATCH 10/36] chore(fixtures): point two hand-maintained contract fixtures at the target Neither file is covered by `pnpm fixtures:emit`, so both still named the deleted adapter subpath. Only the import line changes, to exactly what the emitter now writes; re-emitting either one would drag in unrelated drift that has accumulated since they were last refreshed. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../3-targets/postgres/test/fixtures/namespaced-contract.d.ts | 4 ++-- .../test/value-objects/fixtures/generated/sql-contract.d.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/3-targets/3-targets/postgres/test/fixtures/namespaced-contract.d.ts b/packages/3-targets/3-targets/postgres/test/fixtures/namespaced-contract.d.ts index 11c9f990daa7..ad37a849d445 100644 --- a/packages/3-targets/3-targets/postgres/test/fixtures/namespaced-contract.d.ts +++ b/packages/3-targets/3-targets/postgres/test/fixtures/namespaced-contract.d.ts @@ -1,7 +1,7 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { Bit, Char, @@ -37,7 +37,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; type DefaultLiteralValue = CodecId extends keyof CodecTypes ? CodecTypes[CodecId]['output'] : _Encoded; diff --git a/test/integration/test/value-objects/fixtures/generated/sql-contract.d.ts b/test/integration/test/value-objects/fixtures/generated/sql-contract.d.ts index e97c9dbaff35..859cc8a69779 100644 --- a/test/integration/test/value-objects/fixtures/generated/sql-contract.d.ts +++ b/test/integration/test/value-objects/fixtures/generated/sql-contract.d.ts @@ -1,7 +1,7 @@ // ⚠️ GENERATED FILE - DO NOT EDIT // This file is automatically generated by 'prisma contract emit'. // To regenerate, run: prisma contract emit -import type { QueryOperationTypes as PgAdapterQueryOps } from '@internal/adapter-postgres/operation-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { Bit, Char, @@ -37,7 +37,7 @@ export type ProfileHash = export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; type DefaultLiteralValue = CodecId extends keyof CodecTypes ? CodecTypes[CodecId]['output'] : _Encoded; From d33d2c464dd07fe04ba182afe640b2d058fed4b6 Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 18 Sep 2026 15:12:59 +0200 Subject: [PATCH 11/36] refactor(postgres): give the text-search language allowlist its own module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review rework. The allowlist, its derived type and the default now live in `core/text-search-languages.ts`, which both `core/query-operations.ts` and `types/operation-types.ts` import — no module cycle and no type re-export from outside `exports/`. A module-scope `ReadonlySet` replaces the bare `as readonly string[]` cast in the language check. `RUNTIME.ARGUMENT_INVALID` joins the error reference, a test pins the exact 29-name allowlist, and three comments hard-wrapped near 75 columns are reflowed to the formatter width. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/reference/error-reference.md | 4 ++ .../postgres/src/core/query-operations.ts | 48 +++---------------- .../src/core/text-search-languages.ts | 45 +++++++++++++++++ .../postgres/src/exports/operation-types.ts | 3 +- .../postgres/src/types/operation-types.ts | 4 +- .../postgres/test/query-operations.test.ts | 41 +++++++++++++++- .../postgres/test/descriptor-meta.test.ts | 4 +- 7 files changed, 99 insertions(+), 50 deletions(-) create mode 100644 packages/3-targets/3-targets/postgres/src/core/text-search-languages.ts diff --git a/docs/reference/error-reference.md b/docs/reference/error-reference.md index 7d0df3a2ff85..47859dae548b 100644 --- a/docs/reference/error-reference.md +++ b/docs/reference/error-reference.md @@ -723,6 +723,10 @@ Two trait-matching aggregate descriptors for one operation both claim a register A lane terminal (SQL DSL `.build()`, ORM collection terminal) received an annotation whose declared `applicableTo` set does not include the operation kind being built: the runtime check that backs up the type-level annotation validation when it is bypassed via casts or dynamic invocation. Payload: `namespace`, `terminalName`, `kind`, `applicableTo`. +### RUNTIME.ARGUMENT_INVALID + +A built-in Postgres query operation received an argument it cannot use. Today the only such argument is the `language` of `fullTextMatches`, `fullTextRank` and `fullTextHeadline`: the language is written into the SQL as an inline literal rather than a bound parameter, so it is checked against the text-search configurations a stock PostgreSQL server ships with and anything else is refused. Raised while the query is being built, before any SQL reaches the database. Payload: `helper`, `argument`, `received`. + ### RUNTIME.AST_INVALID A lowered SQL AST is structurally invalid: a subquery projecting other than one column, an INSERT with zero rows, a missing column value, an empty onConflict column list or do-update-set, an UPDATE with no SET assignments, an INSERT target table absent from contract storage, or an AST node constructed with invalid arguments (empty FunctionSource column aliases, a CaseExpr with no branches, a raw query declaring a `__proto__` result column, a name that cannot survive as a column, so alias it in SQL and declare the alias). Raised by the Postgres and SQLite SQL renderers and by AST node construction in relational-core. Payload: `node`, `table`, `column`; construction sites carry node-specific fields. diff --git a/packages/3-targets/3-targets/postgres/src/core/query-operations.ts b/packages/3-targets/3-targets/postgres/src/core/query-operations.ts index 85a2f11c9b8a..439aac7b6349 100644 --- a/packages/3-targets/3-targets/postgres/src/core/query-operations.ts +++ b/packages/3-targets/3-targets/postgres/src/core/query-operations.ts @@ -3,54 +3,18 @@ import { buildOperation, toExpr } from '@internal/sql-relational-core/expression import type { QueryOperationTypes } from '../types/operation-types'; import { PG_BOOL_CODEC_ID, PG_FLOAT4_CODEC_ID, PG_TEXT_CODEC_ID } from './codec-ids'; import { postgresError } from './errors'; +import { + DEFAULT_FULL_TEXT_SEARCH_LANGUAGE, + isFullTextSearchLanguage, + POSTGRES_TEXT_SEARCH_LANGUAGES, +} from './text-search-languages'; type CodecTypesBase = Record; const TEXT_REF = { codecId: PG_TEXT_CODEC_ID } as const; -/** - * The text-search configurations a stock PostgreSQL server ships with. The - * language reaches SQL as an inline literal rather than a bound parameter, so - * only names on this list may be used. - */ -export const POSTGRES_TEXT_SEARCH_LANGUAGES = [ - 'simple', - 'arabic', - 'armenian', - 'basque', - 'catalan', - 'danish', - 'dutch', - 'english', - 'finnish', - 'french', - 'german', - 'greek', - 'hindi', - 'hungarian', - 'indonesian', - 'irish', - 'italian', - 'lithuanian', - 'nepali', - 'norwegian', - 'portuguese', - 'romanian', - 'russian', - 'serbian', - 'spanish', - 'swedish', - 'tamil', - 'turkish', - 'yiddish', -] as const; - -export type FullTextSearchLanguage = (typeof POSTGRES_TEXT_SEARCH_LANGUAGES)[number]; - -export const DEFAULT_FULL_TEXT_SEARCH_LANGUAGE: FullTextSearchLanguage = 'english'; - function languageLiteral(method: string, language: string): LiteralExpr { - if (!(POSTGRES_TEXT_SEARCH_LANGUAGES as readonly string[]).includes(language)) { + if (!isFullTextSearchLanguage(language)) { throw postgresError( 'RUNTIME.ARGUMENT_INVALID', `${method}: '${language}' is not a PostgreSQL text-search configuration Prisma recognizes.`, diff --git a/packages/3-targets/3-targets/postgres/src/core/text-search-languages.ts b/packages/3-targets/3-targets/postgres/src/core/text-search-languages.ts new file mode 100644 index 000000000000..54641fff92b0 --- /dev/null +++ b/packages/3-targets/3-targets/postgres/src/core/text-search-languages.ts @@ -0,0 +1,45 @@ +/** + * The text-search configurations a stock PostgreSQL server ships with. The language reaches SQL as + * an inline literal rather than a bound parameter, so only names on this list may be used. + */ +export const POSTGRES_TEXT_SEARCH_LANGUAGES = [ + 'simple', + 'arabic', + 'armenian', + 'basque', + 'catalan', + 'danish', + 'dutch', + 'english', + 'finnish', + 'french', + 'german', + 'greek', + 'hindi', + 'hungarian', + 'indonesian', + 'irish', + 'italian', + 'lithuanian', + 'nepali', + 'norwegian', + 'portuguese', + 'romanian', + 'russian', + 'serbian', + 'spanish', + 'swedish', + 'tamil', + 'turkish', + 'yiddish', +] as const; + +export type FullTextSearchLanguage = (typeof POSTGRES_TEXT_SEARCH_LANGUAGES)[number]; + +export const DEFAULT_FULL_TEXT_SEARCH_LANGUAGE: FullTextSearchLanguage = 'english'; + +const KNOWN_LANGUAGES: ReadonlySet = new Set(POSTGRES_TEXT_SEARCH_LANGUAGES); + +export function isFullTextSearchLanguage(language: string): language is FullTextSearchLanguage { + return KNOWN_LANGUAGES.has(language); +} diff --git a/packages/3-targets/3-targets/postgres/src/exports/operation-types.ts b/packages/3-targets/3-targets/postgres/src/exports/operation-types.ts index 1f13606f5910..710188a5e585 100644 --- a/packages/3-targets/3-targets/postgres/src/exports/operation-types.ts +++ b/packages/3-targets/3-targets/postgres/src/exports/operation-types.ts @@ -1 +1,2 @@ -export type { FullTextSearchLanguage, QueryOperationTypes } from '../types/operation-types'; +export type { FullTextSearchLanguage } from '../core/text-search-languages'; +export type { QueryOperationTypes } from '../types/operation-types'; diff --git a/packages/3-targets/3-targets/postgres/src/types/operation-types.ts b/packages/3-targets/3-targets/postgres/src/types/operation-types.ts index c800d3ade2d4..5c9fe2e44492 100644 --- a/packages/3-targets/3-targets/postgres/src/types/operation-types.ts +++ b/packages/3-targets/3-targets/postgres/src/types/operation-types.ts @@ -4,7 +4,7 @@ import type { Expression, TraitExpression, } from '@internal/sql-relational-core/expression'; -import type { FullTextSearchLanguage } from '../core/query-operations'; +import type { FullTextSearchLanguage } from '../core/text-search-languages'; type CodecTypesBase = Record; @@ -14,8 +14,6 @@ type TextualSelf = TraitExpression = CodecExpression<'pg/text@1', false, CT>; -export type { FullTextSearchLanguage }; - export type QueryOperationTypes = SqlQueryOperationTypes< CT, { diff --git a/packages/3-targets/3-targets/postgres/test/query-operations.test.ts b/packages/3-targets/3-targets/postgres/test/query-operations.test.ts index 0976aa25cebe..bef138a9ccd8 100644 --- a/packages/3-targets/3-targets/postgres/test/query-operations.test.ts +++ b/packages/3-targets/3-targets/postgres/test/query-operations.test.ts @@ -1,12 +1,13 @@ import { createSqlOperationRegistry } from '@internal/sql-operations'; import { LiteralExpr, OperationExpr, ParamRef } from '@internal/sql-relational-core/ast'; import { describe, expect, it } from 'vitest'; +import { POSTGRES_TEXT_SEARCH_LANGUAGES } from '../src/core/text-search-languages'; import postgresTargetDescriptor from '../src/exports/runtime'; const TEXT_COLUMN_AST = ParamRef.of('body', { codec: { codecId: 'pg/text@1' } }); -// Stands in for a contract-bound text column: the operations take an -// Expression on `self` and read its AST, not a bare AST node. +// Stands in for a contract-bound text column: the operations take an Expression on `self` and read +// its AST, not a bare AST node. const TEXT_COLUMN = { returnType: { codecId: 'pg/text@1', nullable: false }, buildAst: () => TEXT_COLUMN_AST, @@ -124,3 +125,39 @@ describe('postgres target query operations', () => { ]); }); }); + +describe('the text-search language allowlist', () => { + it('is exactly the configurations a stock PostgreSQL server ships with', () => { + expect(POSTGRES_TEXT_SEARCH_LANGUAGES).toEqual([ + 'simple', + 'arabic', + 'armenian', + 'basque', + 'catalan', + 'danish', + 'dutch', + 'english', + 'finnish', + 'french', + 'german', + 'greek', + 'hindi', + 'hungarian', + 'indonesian', + 'irish', + 'italian', + 'lithuanian', + 'nepali', + 'norwegian', + 'portuguese', + 'romanian', + 'russian', + 'serbian', + 'spanish', + 'swedish', + 'tamil', + 'turkish', + 'yiddish', + ]); + }); +}); diff --git a/packages/3-targets/6-adapters/postgres/test/descriptor-meta.test.ts b/packages/3-targets/6-adapters/postgres/test/descriptor-meta.test.ts index 0777e0688613..e08292fa419d 100644 --- a/packages/3-targets/6-adapters/postgres/test/descriptor-meta.test.ts +++ b/packages/3-targets/6-adapters/postgres/test/descriptor-meta.test.ts @@ -256,8 +256,8 @@ describe('precision bounds agree between authoring and expansion', () => { }); describe('postgres adapter query operations', () => { - // Postgres built-in operations moved to @internal/target-postgres; the - // adapter contributes none, so a stale slot here would register them twice. + // Postgres built-in operations moved to @internal/target-postgres; the adapter contributes none, + // so a stale slot here would register them twice. it('the runtime descriptor contributes no query operations', () => { expect(postgresRuntimeAdapterDescriptor.queryOperations).toBeUndefined(); }); From 6b66e80266d891a3954f6788b45b975d20a7fe32 Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 18 Sep 2026 15:15:01 +0200 Subject: [PATCH 12/36] docs(postgres): document full-text search and the moved operation types The target README gains a "Full-text search" section with the ORM and SQL builder calls the integration tests exercise, plus the GIN index the predicate needs and why its expression has to match the operation byte for byte. The Prisma 8 skill reference describes the three operations where it already described `ilike`. Upgrade fragments under `upgrade-instructions/pending/` tell app authors to re-emit their contract and extension authors where `QueryOperationTypes` moved. One stale example import in the emitter subsystem doc now names the target. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../subsystems/2. Contract Emitter & Types.md | 2 +- .../3-targets/3-targets/postgres/README.md | 35 +++++++++++++++++++ .../prisma-8/references/queries-postgres.md | 25 +++++++++++++ .../app/instructions.md | 30 ++++++++++++++++ .../extension/instructions.md | 28 +++++++++++++++ 5 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 upgrade-instructions/pending/postgres-full-text-search/app/instructions.md create mode 100644 upgrade-instructions/pending/postgres-full-text-search/extension/instructions.md diff --git a/docs/architecture docs/subsystems/2. Contract Emitter & Types.md b/docs/architecture docs/subsystems/2. Contract Emitter & Types.md index 4693f073f0b3..d877d23c351e 100644 --- a/docs/architecture docs/subsystems/2. Contract Emitter & Types.md +++ b/docs/architecture docs/subsystems/2. Contract Emitter & Types.md @@ -218,7 +218,7 @@ Minimal excerpt (SQL): ```typescript // ⚠️ GENERATED FILE - DO NOT EDIT import type { CodecTypes as PgTypes } from '@internal/target-postgres/codec-types'; -import type { OperationTypes as PgOps } from '@internal/adapter-postgres/operation-types'; +import type { QueryOperationTypes as PgOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, TypeMaps as TypeMapsType } from '@internal/sql-contract/types'; import type { diff --git a/packages/3-targets/3-targets/postgres/README.md b/packages/3-targets/3-targets/postgres/README.md index 78ee7375ba72..4a2543269ea3 100644 --- a/packages/3-targets/3-targets/postgres/README.md +++ b/packages/3-targets/3-targets/postgres/README.md @@ -115,6 +115,40 @@ export const contract = defineContract({ Pack refs are pure JSON-friendly objects that make TypeScript contract authoring work in both emit and no-emit workflows without requiring separate manifest files. +### Full-text search + +This package contributes the built-in Postgres query operations — `ilike`, and the three full-text search operations below — through `queryOperations` on its runtime descriptor, with their types on `./operation-types`. Emitted `contract.d.ts` files import them from there. + +`fullTextMatches` is a predicate, `fullTextRank` scores a row for ordering, and `fullTextHeadline` returns the matched text with `` around the matching words. All three take the search string as a bound parameter and lower to `websearch_to_tsquery`, so a user can type `"an exact phrase"` and `-excluded` and get what those mean in a search box. Each takes an optional second argument naming the text-search configuration, which defaults to `english`; only the configurations a stock PostgreSQL server ships with are accepted, because the name is written into the SQL as an inline literal. + +Through the ORM: + +```typescript +const hits = await db.orm.public.Message.select('id', 'text') + .where((row) => row.text.fullTextMatches(query)) + .orderBy((row) => row.text.fullTextRank(query).desc()) + .limit(20) + .all(); +``` + +Through the SQL builder: + +```typescript +const snippets = db.public.message + .select('id') + .select('snippet', (f, fns) => fns.fullTextHeadline(f.text, query)) + .where((f, fns) => fns.fullTextMatches(f.text, query)) + .build(); +``` + +Postgres computes `to_tsvector` per row unless an index covers that exact expression, so declare one in the schema: + +```prisma +@@index(expression: "to_tsvector('english', \"text\")", type: "gin", name: "message_text_search") +``` + +Write the index expression exactly as the operation renders it — `to_tsvector('', "")`, with the same language you pass to the operation — or Postgres will not use the index. + ## Codec descriptor authoring PostgreSQL-bound codecs use the public `PostgresCodecDescriptor` protocol, `postgresCodec(...)` adapter, and `definePostgresCodecs(...)` tuple helper exported from `@internal/target-postgres/codec-descriptor`. See the [codec authoring guide](../../../../docs/reference/codec-authoring-guide.md#target-owned-sql-codec-descriptors) for subclassing, generic adaptation, stack contribution, validation, array projection, and the current renderer transition. @@ -158,6 +192,7 @@ Postgres prints a `timestamptz` value in the session's time zone, and dates and - `./control`: Control plane entry point for `SqlControlTargetDescriptor` - `./runtime`: Runtime entry point for target-specific runtime code - `./pack`: Pure pack ref for `defineContract({ family, target: postgresPack, ... })` +- `./operation-types`: `QueryOperationTypes` for the built-in Postgres query operations, plus `FullTextSearchLanguage` - `./prisma7-binding`: `prisma7PostgresBinding`, this target's view for the Prisma 7 contract source (see above) ## Tests diff --git a/skills/prisma-8/references/queries-postgres.md b/skills/prisma-8/references/queries-postgres.md index 1f0354751a93..5750b266af34 100644 --- a/skills/prisma-8/references/queries-postgres.md +++ b/skills/prisma-8/references/queries-postgres.md @@ -62,6 +62,31 @@ db.orm.public.User.where({ kind: 'admin' }); Operators on the field proxy include `.eq`, `.neq`, `.lt`, `.lte`, `.gt`, `.gte`, `.like`, `.ilike`, `.in([...])`, `.isNull()`, `.isNotNull()`. Extensions add target-specific operators on extension-typed columns (`pgvector`'s `.cosineDistance(...)`, `postgis`'s `.within(...)` / `.intersectsBbox(...)` / `.distanceSphere(...)`). +**Full-text search** is built into the Postgres target, on any text column: `.fullTextMatches(q)` is the predicate, `.fullTextRank(q)` scores a row so you can order by relevance, and `.fullTextHeadline(q)` returns the text with `` around the matches. The search string is a bound parameter lowered to `websearch_to_tsquery`, so `"an exact phrase"` and `-excluded` work the way a user expects from a search box. Each takes an optional second argument naming the text-search configuration; it defaults to `'english'` and only accepts the configurations a stock PostgreSQL server ships with (`'simple'`, `'german'`, `'french'`, … — anything else throws `RUNTIME.ARGUMENT_INVALID` when the query is built). + +```typescript +// ORM: filter by the query, order by relevance. +const hits = await db.orm.public.Message + .select('id', 'text') + .where((m) => m.text.fullTextMatches(query)) + .orderBy((m) => m.text.fullTextRank(query).desc()) + .limit(20) + .all(); + +// SQL builder: the same predicate, plus a highlighted snippet. +const snippets = db.sql.public.message + .select('id') + .select('snippet', (f, fns) => fns.fullTextHeadline(f.text, query)) + .where((f, fns) => fns.fullTextMatches(f.text, query)) + .build(); +``` + +Without an index Postgres recomputes `to_tsvector` for every row. Declare one whose expression matches what the operation renders, character for character, including the language: + +```prisma +@@index(expression: "to_tsvector('english', \"text\")", type: "gin", name: "message_text_search") +``` + **There is no `.between(a, b)` operator.** Express ranges either as two chained `.where(...)` clauses (the idiomatic form — clauses AND-compose) or with the `and(...)` combinator inside one clause: ```typescript diff --git a/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md b/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md new file mode 100644 index 000000000000..d4e49c3df912 --- /dev/null +++ b/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md @@ -0,0 +1,30 @@ +--- +changes: + - id: re-emit-the-contract-for-the-moved-query-operation-types + summary: | + Emitted Postgres `contract.d.ts` files import `QueryOperationTypes` from the target package + instead of the adapter. Run `prisma contract emit` once; an un-emitted contract names a + subpath that no longer exists and stops type-checking. + detection: + glob: "**/contract.d.ts" + contains: + - "/adapter/operation-types" +--- + +## `re-emit-the-contract-for-the-moved-query-operation-types` + +The built-in Postgres query operations (`ilike`, and the new `fullTextMatches`, `fullTextRank` and `fullTextHeadline`) are contributed by the Postgres target rather than the Postgres adapter. Emitted contract types follow: the generated line + +```ts +import type { QueryOperationTypes as PgAdapterQueryOps } from '@prisma/orm-postgres/adapter/operation-types'; +``` + +becomes + +```ts +import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgres/target/operation-types'; +``` + +Run `prisma contract emit` and commit the regenerated `contract.d.ts`. Nothing else in the file changes, `contract.json` does not change, and no contract hash moves. Do not hand-edit the generated file. + +Application code that imported `@prisma/orm-postgres/adapter/operation-types` directly imports `@prisma/orm-postgres/target/operation-types` instead. That subpath no longer exists; there is no compatibility re-export. diff --git a/upgrade-instructions/pending/postgres-full-text-search/extension/instructions.md b/upgrade-instructions/pending/postgres-full-text-search/extension/instructions.md new file mode 100644 index 000000000000..9d83f8eef9cc --- /dev/null +++ b/upgrade-instructions/pending/postgres-full-text-search/extension/instructions.md @@ -0,0 +1,28 @@ +--- +changes: + - id: query-operation-types-move-to-the-postgres-target + summary: | + `QueryOperationTypes` moves from `@internal/adapter-postgres/operation-types` to + `@internal/target-postgres/operation-types`. The adapter subpath is gone, with no + compatibility re-export. + detection: + glob: "**/*.{ts,mts,cts}" + matches: + - "adapter-postgres/operation-types" + - "orm-postgres/adapter/operation-types" +--- + +## `query-operation-types-move-to-the-postgres-target` + +The Postgres adapter no longer contributes query operations; the target does. Change the import: + +```ts +// before +import type { QueryOperationTypes } from '@internal/adapter-postgres/operation-types'; +// after +import type { QueryOperationTypes } from '@internal/target-postgres/operation-types'; +``` + +Under the published facade, `@prisma/orm-postgres/adapter/operation-types` becomes `@prisma/orm-postgres/target/operation-types`. Emitted contracts name the target import under the alias `PgTargetQueryOps` instead of `PgAdapterQueryOps`, so a snapshot or fixture that pins emitted contract text needs regenerating. + +The type's shape is unchanged apart from three added operations — `fullTextMatches`, `fullTextRank` and `fullTextHeadline`, all on `textual` columns — so an extension that intersects its own `QueryOperationTypes` with the Postgres one needs no other edit. From fca80fdba14f3a271ba60e7325ffd8cb26394d4c Mon Sep 17 00:00:00 2001 From: willbot Date: Fri, 18 Sep 2026 15:41:21 +0200 Subject: [PATCH 13/36] docs: name the builder lane db.sql and the target as an operations contributor Review rework. The full-text SQL builder example wrote `db.public.message`; on a client that exposes `db.orm`, the builder lane is `db.sql`. The operations package README still said only adapters and extensions return `queryOperations()` factories, which a target does too since ADR 253. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- packages/2-sql/1-core/operations/README.md | 2 +- packages/3-targets/3-targets/postgres/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/2-sql/1-core/operations/README.md b/packages/2-sql/1-core/operations/README.md index 6162628aae5d..d9e7929f54e2 100644 --- a/packages/2-sql/1-core/operations/README.md +++ b/packages/2-sql/1-core/operations/README.md @@ -17,7 +17,7 @@ This package provides SQL-specific operation types that extend the generic `Oper - **SQL Operation Types**: SQL-specific operation entry and descriptor types - `SqlOperationEntry`: Extends `OperationEntry` with a `lowering` field (`SqlLoweringSpec`) - `SqlOperationDescriptor`: Alias for `SqlOperationEntry` used at registration sites - - `SqlOperationDescriptors`: `Readonly>` — the keyed-record shape adapter/extension `queryOperations()` factories return + - `SqlOperationDescriptors`: `Readonly>` — the keyed-record shape target/adapter/extension `queryOperations()` factories return - `SqlLoweringSpec`: SQL-specific lowering specification (`targetFamily`, `strategy`, `template`) - `SqlOperationRegistry`: Typed registry alias (`OperationRegistry`) diff --git a/packages/3-targets/3-targets/postgres/README.md b/packages/3-targets/3-targets/postgres/README.md index 4a2543269ea3..0c31ed152917 100644 --- a/packages/3-targets/3-targets/postgres/README.md +++ b/packages/3-targets/3-targets/postgres/README.md @@ -134,7 +134,7 @@ const hits = await db.orm.public.Message.select('id', 'text') Through the SQL builder: ```typescript -const snippets = db.public.message +const snippets = db.sql.public.message .select('id') .select('snippet', (f, fns) => fns.fullTextHeadline(f.text, query)) .where((f, fns) => fns.fullTextMatches(f.text, query)) From 50aa48f68461209468a55369e3a61bc2f18103f9 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 09:33:39 +0200 Subject: [PATCH 14/36] feat(authoring): a contributed model attribute may lower to an index A model-attribute lowering now returns either the entity it always could or `{ index }`, an opaque payload the family narrows. The SQL interpreter checks it with `isAuthoredIndexInput` and pushes it onto the same `indexNodes` list `@@index` fills, so naming, index-type registration and the name/map rules are shared rather than duplicated. Two smaller additions serve the same case: a descriptor may declare itself `repeatable`, which skips the duplicate-attribute diagnostic, and the lowering context can resolve a field of the declaring model to its storage name, so a lowering that renders storage-level text never has to guess past `@map`. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../src/exports/authoring.ts | 2 + .../src/shared/framework-authoring.ts | 40 +++- .../contract/src/exports/index-naming.ts | 1 + .../2-sql/1-core/contract/src/index-naming.ts | 29 +++ .../contract-psl/src/interpreter.ts | 16 +- ...nterpreter.model-attribute-indexes.test.ts | 184 ++++++++++++++++++ 6 files changed, 266 insertions(+), 6 deletions(-) create mode 100644 packages/2-sql/2-authoring/contract-psl/test/interpreter.model-attribute-indexes.test.ts diff --git a/packages/1-framework/1-core/framework-components/src/exports/authoring.ts b/packages/1-framework/1-core/framework-components/src/exports/authoring.ts index d70efe0566e4..9a195e494d88 100644 --- a/packages/1-framework/1-core/framework-components/src/exports/authoring.ts +++ b/packages/1-framework/1-core/framework-components/src/exports/authoring.ts @@ -16,6 +16,8 @@ export type { AuthoringModelAttributeContext, AuthoringModelAttributeDescriptor, AuthoringModelAttributeDescriptorNamespace, + AuthoringModelAttributeEntityOutput, + AuthoringModelAttributeIndexOutput, AuthoringModelAttributeLoweringOutput, AuthoringPslBlockDescriptor, AuthoringPslBlockDescriptorNamespace, diff --git a/packages/1-framework/1-core/framework-components/src/shared/framework-authoring.ts b/packages/1-framework/1-core/framework-components/src/shared/framework-authoring.ts index 6181fc0b654b..50a313afa944 100644 --- a/packages/1-framework/1-core/framework-components/src/shared/framework-authoring.ts +++ b/packages/1-framework/1-core/framework-components/src/shared/framework-authoring.ts @@ -474,21 +474,46 @@ export interface AuthoringModelAttributeContext extends AuthoringEntityContext { readonly modelName: string; readonly storageName: string; readonly namespaceId: string; + /** + * The storage name a field of the declaring model maps to, or `undefined` + * when the model declares no such field. The interpreter owns the mapping + * — a lowering that renders storage-level text must ask for the name here + * rather than reusing the authored field name, which `@map` may rename. + */ + readonly fieldStorageName: (fieldName: string) => string | undefined; } /** * What a model-attribute lowering returns when it produces an entity: `key` * is the identity the entity is stored under within its `entries` slot - * (`entries[attribute][key]`); `entity` is the value stored there. A - * lowering that instead pushed a diagnostic through - * {@link AuthoringModelAttributeContext.diagnostics} returns `undefined` — - * the same convention {@link AuthoringEntityTypeFactoryOutput} uses. + * (`entries[attribute][key]`); `entity` is the value stored there. */ -export interface AuthoringModelAttributeLoweringOutput { +export interface AuthoringModelAttributeEntityOutput { readonly key: string; readonly entity: unknown; } +/** + * What a model-attribute lowering returns when it produces an index on the + * declaring model's storage rather than a standalone entity. The framework + * never reads `index`: its shape is the family's authored-index input, which + * the family interpreter narrows and files through the same path its own + * index attribute uses, so naming and validation are shared. + */ +export interface AuthoringModelAttributeIndexOutput { + readonly index: unknown; +} + +/** + * What a model-attribute lowering returns. A lowering that instead pushed a + * diagnostic through {@link AuthoringModelAttributeContext.diagnostics} + * returns `undefined` — the same convention + * {@link AuthoringEntityTypeFactoryOutput} uses. + */ +export type AuthoringModelAttributeLoweringOutput = + | AuthoringModelAttributeEntityOutput + | AuthoringModelAttributeIndexOutput; + /** * Declarative descriptor for an extension-contributed `@@` model attribute. * @@ -512,6 +537,11 @@ export interface AuthoringModelAttributeDescriptor { readonly kind: 'modelAttribute'; readonly attribute: string; readonly spec: unknown; + /** + * Whether one model may declare this attribute more than once. Defaults to + * false, which is what the duplicate diagnostic enforces. + */ + readonly repeatable?: boolean; readonly lower: ( parsed: Out, ctx: AuthoringModelAttributeContext, diff --git a/packages/2-sql/1-core/contract/src/exports/index-naming.ts b/packages/2-sql/1-core/contract/src/exports/index-naming.ts index 316c4589cc02..6cb09a639687 100644 --- a/packages/2-sql/1-core/contract/src/exports/index-naming.ts +++ b/packages/2-sql/1-core/contract/src/exports/index-naming.ts @@ -2,5 +2,6 @@ export { type AuthoredIndexInput, type AuthoredIndexMethod, exactNameBodyWarning, + isAuthoredIndexInput, lowerAuthoredIndex, } from '../index-naming'; diff --git a/packages/2-sql/1-core/contract/src/index-naming.ts b/packages/2-sql/1-core/contract/src/index-naming.ts index d36dff253876..6b609769275c 100644 --- a/packages/2-sql/1-core/contract/src/index-naming.ts +++ b/packages/2-sql/1-core/contract/src/index-naming.ts @@ -45,6 +45,35 @@ export type AuthoredIndexInput = AuthoredIndexElements & readonly name: string | undefined; }; +/** + * Narrows the opaque payload a contributed model attribute returns under + * `index` (see `AuthoringModelAttributeIndexOutput`). The framework hands the + * value through untyped because an index's shape belongs to the family; this + * is the SQL family's boundary check. It proves the structure only — the + * name/map and expression rules stay where `@@index` enforces them, in + * {@link lowerAuthoredIndex}. + */ +export function isAuthoredIndexInput(value: unknown): value is AuthoredIndexInput { + if (typeof value !== 'object' || value === null) return false; + const candidate: Record = { ...value }; + const hasExpression = typeof candidate['expression'] === 'string'; + const hasColumns = + Array.isArray(candidate['columns']) && + candidate['columns'].every((element) => typeof element === 'string'); + if (hasExpression === hasColumns) return false; + if (!isOptionalString(candidate['where'])) return false; + if (!isOptionalString(candidate['map'])) return false; + if (!isOptionalString(candidate['name'])) return false; + if (candidate['unique'] !== undefined && typeof candidate['unique'] !== 'boolean') return false; + if (candidate['type'] === undefined) return candidate['options'] === undefined; + if (typeof candidate['type'] !== 'string') return false; + return candidate['options'] === undefined || typeof candidate['options'] === 'object'; +} + +function isOptionalString(value: unknown): boolean { + return value === undefined || typeof value === 'string'; +} + const EXACT_NAME_BODY_PREAMBLE = "Drift detection compares the authored SQL text byte-for-byte against Postgres's reprinted form, which is only reliable when the text was captured by contract infer."; diff --git a/packages/2-sql/2-authoring/contract-psl/src/interpreter.ts b/packages/2-sql/2-authoring/contract-psl/src/interpreter.ts index 111a66b2a89d..1fd4733c2dd8 100644 --- a/packages/2-sql/2-authoring/contract-psl/src/interpreter.ts +++ b/packages/2-sql/2-authoring/contract-psl/src/interpreter.ts @@ -60,6 +60,7 @@ import { } from '@internal/psl-parser'; import { fkRelationPairKey, type InvalidFkPairing } from '@internal/psl-parser/interpret'; import type { SourceFile } from '@internal/psl-parser/syntax'; +import { isAuthoredIndexInput } from '@internal/sql-contract/index-naming'; import type { SqlModelStorage, SqlNamespaceBase, @@ -1129,7 +1130,10 @@ function buildModelNodeFromPsl(input: BuildModelNodeInput): BuildModelNodeResult } const contributedModelAttribute = input.modelAttributesByName.get(modelAttribute.name); if (contributedModelAttribute !== undefined) { - if (declaredContributedModelAttributes.has(modelAttribute.name)) { + if ( + contributedModelAttribute.repeatable !== true && + declaredContributedModelAttributes.has(modelAttribute.name) + ) { diagnostics.push( duplicateModelAttributeDiagnostic({ name: modelAttribute.name, @@ -1179,6 +1183,7 @@ function buildModelNodeFromPsl(input: BuildModelNodeInput): BuildModelNodeResult target: input.targetId, modelName: model.name, storageName: tableName, + fieldStorageName: (fieldName) => mapping.fieldColumns.get(fieldName), namespaceId: modelNamespaceId ?? input.defaultNamespaceId, sourceId, diagnostics: { @@ -1192,6 +1197,15 @@ function buildModelNodeFromPsl(input: BuildModelNodeInput): BuildModelNodeResult if (lowered === undefined) { continue; } + if ('index' in lowered) { + if (!isAuthoredIndexInput(lowered.index)) { + throw new InternalError( + `Model attribute "@@${modelAttribute.name}" lowered to a malformed index; a contributed attribute that returns { index } must return an authored-index input`, + ); + } + indexNodes.push(lowered.index); + continue; + } const slot = modelAttributeEntities[contributedModelAttribute.attribute] ?? {}; modelAttributeEntities[contributedModelAttribute.attribute] = slot; slot[lowered.key] = lowered.entity; diff --git a/packages/2-sql/2-authoring/contract-psl/test/interpreter.model-attribute-indexes.test.ts b/packages/2-sql/2-authoring/contract-psl/test/interpreter.model-attribute-indexes.test.ts new file mode 100644 index 000000000000..e25b08c3ce93 --- /dev/null +++ b/packages/2-sql/2-authoring/contract-psl/test/interpreter.model-attribute-indexes.test.ts @@ -0,0 +1,184 @@ +/** + * A contributed model attribute may lower to a table index instead of a + * namespaced entity. The interpreter files it through the same path `@@index` + * uses, so naming and validation are shared rather than duplicated. + */ +import type { AuthoringContributions } from '@internal/framework-components/authoring'; +import type { ModelAttributeSpecFactory } from '@internal/psl-parser'; +import { fieldRef, list, modelAttribute, optional, str } from '@internal/psl-parser'; +import { defineIndexTypes } from '@internal/sql-contract/index-types'; +import { type } from 'arktype'; +import { describe, expect, it } from 'vitest'; +import { createTestSqlNamespace } from '../../../1-core/contract/test/test-support'; +import { interpretPslDocumentToSqlContract } from '../src/interpreter'; +import { + createBuiltinLikeControlMutationDefaults, + postgresScalarTypeDescriptors, + postgresTarget, + symbolTableInputFromParseArgs, +} from './fixtures'; +import { sqlStorageFromSuccessfulSqlInterpretation } from './interpret-sql-contract-storage'; +import { unboundTables } from './unbound-tables'; + +const builtinControlMutationDefaults = createBuiltinLikeControlMutationDefaults(); + +/** + * The contributed index goes through the target's index-type registration + * like any other, so the test target has to register the method it names. + */ +const targetWithIndexTypes = { + ...postgresTarget, + indexTypes: defineIndexTypes().add('gin', { options: type('object') }), +}; + +const searchIndexSpecFactory: ModelAttributeSpecFactory = () => + modelAttribute('searchIndex', { + documentation: 'Indexes one text column for full-text search.', + positional: [ + { + key: 'fields', + type: list(fieldRef(), { allowEmpty: false, unique: true }), + documentation: 'The single field to index.', + }, + ], + named: { + name: { type: optional(str()), documentation: 'Wire-name prefix for the index.' }, + }, + }); + +type SearchIndexParsed = { readonly fields: readonly string[]; readonly name?: string }; + +function searchIndexContributions(repeatable?: boolean): AuthoringContributions { + return { + modelAttributes: { + searchIndex: { + kind: 'modelAttribute', + attribute: 'searchIndex', + spec: searchIndexSpecFactory, + ...(repeatable === undefined ? {} : { repeatable }), + lower: (parsed: SearchIndexParsed, ctx) => { + const field = parsed.fields[0]; + if (field === undefined) return undefined; + const storageName = ctx.fieldStorageName(field); + if (storageName === undefined) return undefined; + return { + index: { + expression: `to_tsvector('english', "${storageName}")`, + type: 'gin', + // `undefined`, not `{}`: the string form leaves `options` + // absent when the author writes none, and an empty bag would + // make the two forms differ in the emitted contract. + options: undefined, + where: undefined, + unique: undefined, + map: undefined, + name: parsed.name, + }, + }; + }, + }, + }, + }; +} + +function interpret(schema: string, authoringContributions?: AuthoringContributions) { + const document = symbolTableInputFromParseArgs({ schema, sourceId: 'schema.prisma' }); + return interpretPslDocumentToSqlContract({ + ...document, + target: targetWithIndexTypes, + scalarColumnDescriptors: postgresScalarTypeDescriptors, + composedExtensionContracts: new Map(), + controlMutationDefaults: builtinControlMutationDefaults, + createNamespace: createTestSqlNamespace, + capabilities: { sql: { scalarList: true } }, + ...(authoringContributions !== undefined ? { authoringContributions } : {}), + }); +} + +function indexesOf(schema: string, authoringContributions?: AuthoringContributions) { + const result = interpret(schema, authoringContributions); + expect(result.ok).toBe(true); + if (!result.ok) return []; + return unboundTables(sqlStorageFromSuccessfulSqlInterpretation(result.value))['Message']!.indexes; +} + +describe('a contributed model attribute that lowers to an index', () => { + it('produces the same index as the equivalent @@index(expression:)', () => { + const contributed = indexesOf( + `model Message { + id Int @id + text String + @@searchIndex([text], name: "message_text_search") +}`, + searchIndexContributions(), + ); + + const authored = indexesOf( + `model Message { + id Int @id + text String + @@index(expression: "to_tsvector('english', \\"text\\")", type: "gin", name: "message_text_search") +}`, + ); + + expect(contributed).toEqual(authored); + expect(contributed).toHaveLength(1); + }); + + it('renders the storage column name of a renamed field, not the field name', () => { + const indexes = indexesOf( + `model Message { + id Int @id + text String @map("body_text") + @@searchIndex([text], name: "message_text_search") +}`, + searchIndexContributions(), + ); + + expect(indexes[0]).toMatchObject({ + expression: `to_tsvector('english', "body_text")`, + }); + }); + + it('files two indexes when the descriptor is repeatable', () => { + const indexes = indexesOf( + `model Message { + id Int @id + text String + summary String + @@searchIndex([text], name: "message_text_search") + @@searchIndex([summary], name: "message_summary_search") +}`, + searchIndexContributions(true), + ); + + expect(indexes.map((index) => index.prefix)).toEqual([ + 'message_text_search', + 'message_summary_search', + ]); + }); + + it('still rejects a duplicate when the descriptor is not repeatable', () => { + const result = interpret( + `model Message { + id Int @id + text String + summary String + @@searchIndex([text], name: "message_text_search") + @@searchIndex([summary], name: "message_summary_search") +}`, + searchIndexContributions(), + ); + + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.failure.diagnostics).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + code: 'PSL_DUPLICATE_ATTRIBUTE', + message: '`@@searchIndex` declared more than once on model "Message".', + }), + ]), + ); + }); +}); From 23b8a51042e18d284a161b6e1f24175457721f13 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 09:39:26 +0200 Subject: [PATCH 15/36] feat(postgres): @@fullTextIndex renders the index the operations need MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The attribute takes one field and an optional language and lowers to the same GIN expression index an author could write by hand, except that it derives the expression from the resolved storage column and the same language allowlist the query operations check — so the index and the predicate cannot drift. It is repeatable, since a model may search more than one column, and its name/map rules mirror the ones `@@index` enforces for an expression index. `renderFullTextIndexExpression` is the one place the expression is spelled. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../3-targets/postgres/src/core/authoring.ts | 129 ++++++++++++- .../src/core/full-text-index-expression.ts | 16 ++ .../postgres/src/exports/sql-utils.ts | 1 + .../postgres/test/psl-full-text-index.test.ts | 180 ++++++++++++++++++ 4 files changed, 325 insertions(+), 1 deletion(-) create mode 100644 packages/3-targets/3-targets/postgres/src/core/full-text-index-expression.ts create mode 100644 packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts diff --git a/packages/3-targets/3-targets/postgres/src/core/authoring.ts b/packages/3-targets/3-targets/postgres/src/core/authoring.ts index 9d871dc3b00a..bb969d9ede95 100644 --- a/packages/3-targets/3-targets/postgres/src/core/authoring.ts +++ b/packages/3-targets/3-targets/postgres/src/core/authoring.ts @@ -17,7 +17,16 @@ import type { import { UNBOUND_NAMESPACE_ID } from '@internal/framework-components/ir'; import type { ContributedPslDiagnosticCode } from '@internal/framework-components/psl-ast'; import type { ModelAttributeSpecFactory } from '@internal/psl-parser'; -import { blockAttribute, leafDiagnostic, modelAttribute, str } from '@internal/psl-parser'; +import { + blockAttribute, + fieldRef, + leafDiagnostic, + list, + modelAttribute, + oneOf, + optional, + str, +} from '@internal/psl-parser'; import type { EntityHandleLoweringInput, LoweredPackEntity, @@ -39,6 +48,7 @@ import { PG_TIMESTAMPTZ_TEMPORAL_CODEC_ID, } from './codec-ids'; import { postgresError } from './errors'; +import { renderFullTextIndexExpression } from './full-text-index-expression'; import { postgresNowGeneratorIds } from './now-generators'; import { PostgresNativeEnum } from './postgres-native-enum'; import { PostgresRlsEnablement, type PostgresRlsEnablementInput } from './postgres-rls-enablement'; @@ -51,6 +61,11 @@ import { PostgresRoleSchema, } from './postgres-validators'; import { computeContentHash, POLICY_OPERATION_PREDICATES } from './rls/canonicalize'; +import { + DEFAULT_FULL_TEXT_SEARCH_LANGUAGE, + type FullTextSearchLanguage, + POSTGRES_TEXT_SEARCH_LANGUAGES, +} from './text-search-languages'; // Contributed diagnostic codes, declared once as typed consts — the // `ContributedPslDiagnosticCode` type is the only thing enforcing the @@ -60,6 +75,11 @@ import { computeContentHash, POLICY_OPERATION_PREDICATES } from './rls/canonical const PSL_RLS_PREDICATE_NOT_FOR_OPERATION: ContributedPslDiagnosticCode = 'PSL_RLS_PREDICATE_NOT_FOR_OPERATION'; const PSL_POLICY_INVALID_MAP: ContributedPslDiagnosticCode = 'PSL_POLICY_INVALID_MAP'; +const PSL_FULL_TEXT_INDEX_ONE_FIELD: ContributedPslDiagnosticCode = 'PSL_FULL_TEXT_INDEX_ONE_FIELD'; +const PSL_FULL_TEXT_INDEX_REQUIRES_NAME: ContributedPslDiagnosticCode = + 'PSL_FULL_TEXT_INDEX_REQUIRES_NAME'; +const PSL_FULL_TEXT_INDEX_NAME_XOR_MAP: ContributedPslDiagnosticCode = + 'PSL_FULL_TEXT_INDEX_NAME_XOR_MAP'; const PSL_NATIVE_ENUM_BARE_MEMBER: ContributedPslDiagnosticCode = 'PSL_NATIVE_ENUM_BARE_MEMBER'; const PSL_EXTENSION_INVALID_VALUE: ContributedPslDiagnosticCode = 'PSL_EXTENSION_INVALID_VALUE'; const PSL_NATIVE_ENUM_DUPLICATE_MEMBER_VALUE: ContributedPslDiagnosticCode = @@ -687,6 +707,80 @@ const postgresRlsSpec = modelAttribute('rls', { const postgresRlsSpecFactory: ModelAttributeSpecFactory = () => postgresRlsSpec; +const [firstLanguage, ...remainingLanguages] = POSTGRES_TEXT_SEARCH_LANGUAGES; + +const postgresFullTextIndexSpec = modelAttribute('fullTextIndex', { + documentation: + 'Indexes one text column for full-text search, rendering the expression `fullTextMatches`, `fullTextRank` and `fullTextHeadline` lower to.', + positional: [ + { + key: 'fields', + type: list(fieldRef(), { allowEmpty: false, unique: true }), + documentation: 'The single field to index.', + }, + ], + named: { + language: { + type: optional( + oneOf(str(firstLanguage), ...remainingLanguages.map((language) => str(language))), + ), + documentation: + 'The text-search configuration. Defaults to `english`, and must match the language the query operations are given.', + }, + name: { + type: optional(str()), + documentation: 'The index name. Mutually exclusive with `map`.', + }, + map: { + type: optional(str()), + documentation: 'The database index name. Mutually exclusive with `name`.', + }, + }, + refine: (value, ctx, attributeNode) => { + const diagnostics = []; + if (value.fields.length !== 1) { + diagnostics.push( + leafDiagnostic( + ctx, + attributeNode, + 'The full-text operations work on one column; declare one `@@fullTextIndex` per column', + PSL_FULL_TEXT_INDEX_ONE_FIELD, + ), + ); + } + if (value.name === undefined && value.map === undefined) { + diagnostics.push( + leafDiagnostic( + ctx, + attributeNode, + '`@@fullTextIndex` requires a `name` or `map` argument (a default name cannot be derived from an expression)', + PSL_FULL_TEXT_INDEX_REQUIRES_NAME, + ), + ); + } + if (value.name !== undefined && value.map !== undefined) { + diagnostics.push( + leafDiagnostic( + ctx, + attributeNode, + '`@@fullTextIndex` takes at most one of `name` and `map`', + PSL_FULL_TEXT_INDEX_NAME_XOR_MAP, + ), + ); + } + return diagnostics; + }, +}); + +const postgresFullTextIndexSpecFactory: ModelAttributeSpecFactory = () => postgresFullTextIndexSpec; + +type PostgresFullTextIndexParsed = { + readonly fields: readonly string[]; + readonly language?: FullTextSearchLanguage; + readonly name?: string; + readonly map?: string; +}; + /** * `@@` model attributes contributed by the Postgres target pack. * @@ -709,6 +803,39 @@ export const postgresAuthoringModelAttributes = { }), }), }, + fullTextIndex: { + kind: 'modelAttribute', + attribute: 'fullTextIndex', + spec: postgresFullTextIndexSpecFactory, + repeatable: true, + lower: (parsed: PostgresFullTextIndexParsed, ctx: AuthoringModelAttributeContext) => { + const fieldName = parsed.fields[0]; + // The spec's refine already diagnosed an empty or multi-field list; a + // lowering still runs after a refine diagnostic, so it returns quietly. + if (fieldName === undefined || parsed.fields.length !== 1) return undefined; + const columnName = ctx.fieldStorageName(fieldName); + // `fieldRef()` resolves the name against the declaring model while + // parsing, so an unknown field is already a diagnostic by here. + invariant( + columnName !== undefined, + `@@fullTextIndex on "${ctx.modelName}" resolved no storage name for field "${fieldName}"`, + ); + return { + index: { + expression: renderFullTextIndexExpression( + parsed.language ?? DEFAULT_FULL_TEXT_SEARCH_LANGUAGE, + columnName, + ), + type: 'gin', + options: undefined, + where: undefined, + unique: undefined, + name: parsed.name, + map: parsed.map, + }, + }; + }, + }, } as const satisfies AuthoringModelAttributeDescriptorNamespace; export const postgresAuthoringFieldPresets = { diff --git a/packages/3-targets/3-targets/postgres/src/core/full-text-index-expression.ts b/packages/3-targets/3-targets/postgres/src/core/full-text-index-expression.ts new file mode 100644 index 000000000000..e2d0fa1515a3 --- /dev/null +++ b/packages/3-targets/3-targets/postgres/src/core/full-text-index-expression.ts @@ -0,0 +1,16 @@ +import { quoteIdentifier } from './sql-utils'; +import type { FullTextSearchLanguage } from './text-search-languages'; + +/** + * The index expression that covers `fullTextMatches`, `fullTextRank` and + * `fullTextHeadline` on a column. Postgres only uses an expression index when + * the indexed expression matches the query's byte for byte, so both the + * `@@fullTextIndex` attribute and the TypeScript helper render it here rather + * than each spelling it out. + */ +export function renderFullTextIndexExpression( + language: FullTextSearchLanguage, + columnName: string, +): string { + return `to_tsvector('${language}', ${quoteIdentifier(columnName)})`; +} diff --git a/packages/3-targets/3-targets/postgres/src/exports/sql-utils.ts b/packages/3-targets/3-targets/postgres/src/exports/sql-utils.ts index 05a2b7803850..f86cf18301e2 100644 --- a/packages/3-targets/3-targets/postgres/src/exports/sql-utils.ts +++ b/packages/3-targets/3-targets/postgres/src/exports/sql-utils.ts @@ -1,3 +1,4 @@ +export { renderFullTextIndexExpression } from '../core/full-text-index-expression'; export { escapeLiteral, qualifyName, diff --git a/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts b/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts new file mode 100644 index 000000000000..c37af78e2d93 --- /dev/null +++ b/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts @@ -0,0 +1,180 @@ +/** + * `@@fullTextIndex` renders the same expression the full-text operations + * lower to, so the index and the predicate cannot drift. It is the documented + * way to index a text column; `@@index(expression:)` stays available for + * anything this attribute does not cover. + */ +import { assembleAuthoringContributions } from '@internal/framework-components/control'; +import { buildSymbolTable } from '@internal/psl-parser'; +import { parse } from '@internal/psl-parser/syntax'; +import { interpretPslDocumentToSqlContract } from '@internal/sql-contract-psl'; +import { describe, expect, it } from 'vitest'; +import { + postgresAuthoringEntityTypes, + postgresAuthoringModelAttributes, + postgresAuthoringPslBlockDescriptors, +} from '../src/core/authoring'; +import { postgresIndexTypes } from '../src/core/index-types'; +import { type PostgresSchema, postgresCreateNamespace } from '../src/core/postgres-schema'; + +const assembled = assembleAuthoringContributions([ + { + authoring: { + entityTypes: postgresAuthoringEntityTypes, + pslBlockDescriptors: postgresAuthoringPslBlockDescriptors, + modelAttributes: postgresAuthoringModelAttributes, + }, + }, +]); + +const postgresTarget = { + kind: 'target' as const, + familyId: 'sql' as const, + targetId: 'postgres' as const, + id: 'postgres', + version: '0.0.1', + capabilities: {}, + defaultNamespaceId: 'public', + indexTypes: postgresIndexTypes, +}; + +const scalarTypeDescriptors = new Map([ + ['String', { codecId: 'pg/text@1', nativeType: 'text' }], + ['Int', { codecId: 'pg/int4@1', nativeType: 'int4' }], +]); + +function interpret(source: string) { + const { document, sourceFile } = parse(source); + const { table: symbolTable, diagnostics } = buildSymbolTable({ + document, + sourceFile, + pslBlockDescriptors: assembled.pslBlockDescriptors, + }); + expect(diagnostics).toEqual([]); + + return interpretPslDocumentToSqlContract({ + symbolTable, + sourceFile, + sourceId: 'schema.prisma', + target: postgresTarget, + scalarColumnDescriptors: scalarTypeDescriptors, + authoringContributions: assembled, + composedExtensionContracts: new Map(), + createNamespace: postgresCreateNamespace, + capabilities: { sql: { scalarList: true } }, + }); +} + +function indexesOf(source: string) { + const result = interpret(source); + expect(result.ok).toBe(true); + if (!result.ok) return []; + const namespace = result.value.storage.namespaces['public'] as PostgresSchema; + return namespace.table['Message']?.indexes ?? []; +} + +function diagnosticsOf(source: string) { + const result = interpret(source); + expect(result.ok).toBe(false); + if (result.ok) return []; + return result.failure.diagnostics; +} + +const model = (body: string) => ` +model Message { + id Int @id + text String + summary String +${body} +} +`; + +describe('@@fullTextIndex', () => { + it('produces the index the equivalent @@index(expression:) produces', () => { + const typed = indexesOf(model(` @@fullTextIndex([text], name: "message_text_search")`)); + const authored = indexesOf( + model( + ` @@index(expression: "to_tsvector('english', \\"text\\")", type: "gin", name: "message_text_search")`, + ), + ); + + expect(typed).toEqual(authored); + expect(typed).toHaveLength(1); + expect(typed[0]).toMatchObject({ + expression: `to_tsvector('english', "text")`, + type: 'gin', + prefix: 'message_text_search', + }); + }); + + it('renders the language it was given', () => { + const indexes = indexesOf( + model(` @@fullTextIndex([text], language: "german", name: "message_text_search_de")`), + ); + + expect(indexes[0]).toMatchObject({ expression: `to_tsvector('german', "text")` }); + }); + + it('renders the storage column name of a renamed field, not the field name', () => { + const indexes = indexesOf(` +model Message { + id Int @id + text String @map("body_text") + @@fullTextIndex([text], name: "message_text_search") +} +`); + + expect(indexes[0]).toMatchObject({ expression: `to_tsvector('english', "body_text")` }); + }); + + it('files one index per declaration, so a model may search two columns', () => { + const indexes = indexesOf( + model(` @@fullTextIndex([text], name: "message_text_search") + @@fullTextIndex([summary], name: "message_summary_search")`), + ); + + expect(indexes.map((index) => index.prefix)).toEqual([ + 'message_text_search', + 'message_summary_search', + ]); + }); + + it('rejects a language Postgres does not ship, naming the ones it does', () => { + const [diagnostic] = diagnosticsOf( + model(` @@fullTextIndex([text], language: "klingon", name: "x")`), + ); + + expect(diagnostic?.message).toContain('"english"'); + expect(diagnostic?.message).toContain('"german"'); + }); + + it('rejects more than one field', () => { + expect(diagnosticsOf(model(` @@fullTextIndex([text, summary], name: "x")`))).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + message: expect.stringContaining('one column'), + }), + ]), + ); + }); + + it('requires a name or a map', () => { + expect(diagnosticsOf(model(' @@fullTextIndex([text])'))).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + message: expect.stringContaining('`name` or `map`'), + }), + ]), + ); + }); + + it('takes at most one of name and map', () => { + expect(diagnosticsOf(model(` @@fullTextIndex([text], name: "a", map: "b")`))).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + message: expect.stringContaining('at most one of `name` and `map`'), + }), + ]), + ); + }); +}); From 803b96bebde4baece1892dca725fb0f20cb05b87 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 09:43:16 +0200 Subject: [PATCH 16/36] test(postgres): plan and emit @@fullTextIndex end to end The planner test now covers both authoring forms and proves they plan the same CREATE INDEX. The self-relations PSL fixture declares the attribute, so `contract emit` carries it through the real CLI into `contract.json`: a GIN expression index with no options key, byte-identical to the hand-written form. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../full-text-index-planning.test.ts | 43 ++++++++++++++----- .../fixtures/self-relations/contract.prisma | 1 + .../self-relations/generated/contract.d.ts | 9 +++- .../self-relations/generated/contract.json | 9 +++- 4 files changed, 49 insertions(+), 13 deletions(-) diff --git a/packages/3-targets/3-targets/postgres/test/migrations/full-text-index-planning.test.ts b/packages/3-targets/3-targets/postgres/test/migrations/full-text-index-planning.test.ts index f62543f8a0c7..157cc1eb2b58 100644 --- a/packages/3-targets/3-targets/postgres/test/migrations/full-text-index-planning.test.ts +++ b/packages/3-targets/3-targets/postgres/test/migrations/full-text-index-planning.test.ts @@ -1,8 +1,9 @@ /** - * A GIN index over `to_tsvector(...)`, authored in PSL, reaches the planner as - * a `PostgresCreateIndex` carrying the access method and the expression - * verbatim. The SQL bytes are asserted beside the renderer in the adapter - * package. + * A GIN index over `to_tsvector(...)` reaches the planner as a + * `PostgresCreateIndex` carrying the access method and the expression + * verbatim — whether it came from `@@fullTextIndex`, which renders the + * expression, or from a hand-written `@@index(expression:)`. The SQL bytes are + * asserted beside the renderer in the adapter package. */ import type { Contract } from '@internal/contract/types'; import type { ExecuteRequestLowerer } from '@internal/family-sql/control-adapter'; @@ -18,6 +19,7 @@ import { blindCast } from '@internal/utils/casts'; import { describe, expect, it } from 'vitest'; import { postgresAuthoringEntityTypes, + postgresAuthoringModelAttributes, postgresAuthoringPslBlockDescriptors, } from '../../src/core/authoring'; import { PostgresCreateIndex } from '../../src/core/ddl/nodes'; @@ -28,7 +30,15 @@ import { PostgresDatabaseSchemaNode } from '../../src/core/schema-ir/postgres-da import { PostgresNamespaceSchemaNode } from '../../src/core/schema-ir/postgres-namespace-schema-node'; import { PostgresTableSchemaNode } from '../../src/core/schema-ir/postgres-table-schema-node'; -const SCHEMA = ` +const TYPED_ATTRIBUTE_SCHEMA = ` +model Message { + id Int @id + text String + @@fullTextIndex([text], name: "message_text_search") +} +`; + +const HAND_WRITTEN_EXPRESSION_SCHEMA = ` model Message { id Int @id text String @@ -41,6 +51,7 @@ const assembled = assembleAuthoringContributions([ authoring: { entityTypes: postgresAuthoringEntityTypes, pslBlockDescriptors: postgresAuthoringPslBlockDescriptors, + modelAttributes: postgresAuthoringModelAttributes, type: { Int: { kind: 'typeConstructor', output: { codecId: 'pg/int4@1', nativeType: 'int4' } }, String: { kind: 'typeConstructor', output: { codecId: 'pg/text@1', nativeType: 'text' } }, @@ -49,8 +60,8 @@ const assembled = assembleAuthoringContributions([ }, ]); -function authoredContract(): Contract { - const { document, sourceFile } = parse(SCHEMA); +function authoredContract(schema: string): Contract { + const { document, sourceFile } = parse(schema); const { table: symbolTable } = buildSymbolTable({ document, sourceFile, @@ -106,7 +117,7 @@ function liveSchemaWithoutTheIndex(): PostgresDatabaseSchemaNode { }); } -async function plannedCreateIndexNodes(): Promise { +async function plannedCreateIndexNodes(schema: string): Promise { const lowered: unknown[] = []; const lowerer: ExecuteRequestLowerer = { lower: () => ({ sql: 'stub', params: [] }), @@ -116,7 +127,7 @@ async function plannedCreateIndexNodes(): Promise { - it('plans one CREATE INDEX carrying the access method and the expression verbatim', async () => { - const nodes = await plannedCreateIndexNodes(); + it('plans one CREATE INDEX from @@fullTextIndex', async () => { + const nodes = await plannedCreateIndexNodes(TYPED_ATTRIBUTE_SCHEMA); + expect(nodes).toHaveLength(1); + const node = nodes[0]!; + expect(node.type).toBe('gin'); + expect(node.elements).toEqual({ expression: `to_tsvector('english', "text")` }); + expect(node.table).toBe('Message'); + expect(node.name.startsWith('message_text_search')).toBe(true); + }); + + it('plans the same CREATE INDEX from a hand-written @@index(expression:)', async () => { + const nodes = await plannedCreateIndexNodes(HAND_WRITTEN_EXPRESSION_SCHEMA); expect(nodes).toHaveLength(1); const node = nodes[0]!; expect(node.type).toBe('gin'); diff --git a/test/integration/test/sql-orm-client/fixtures/self-relations/contract.prisma b/test/integration/test/sql-orm-client/fixtures/self-relations/contract.prisma index 72f11e033a0b..36b5939d245f 100644 --- a/test/integration/test/sql-orm-client/fixtures/self-relations/contract.prisma +++ b/test/integration/test/sql-orm-client/fixtures/self-relations/contract.prisma @@ -16,6 +16,7 @@ model Person { outgoingLinks PersonConnection[] @relation("connectionSource") incomingLinks PersonConnection[] @relation("connectionTarget") + @@fullTextIndex([name], name: "person_name_search") @@map("people") } diff --git a/test/integration/test/sql-orm-client/fixtures/self-relations/generated/contract.d.ts b/test/integration/test/sql-orm-client/fixtures/self-relations/generated/contract.d.ts index 29d418c6079a..5adb9565063b 100644 --- a/test/integration/test/sql-orm-client/fixtures/self-relations/generated/contract.d.ts +++ b/test/integration/test/sql-orm-client/fixtures/self-relations/generated/contract.d.ts @@ -34,7 +34,7 @@ import type { } from '@internal/contract/types'; export type StorageHash = - StorageHashBase<'03064b14cc66f1a136c019a42aef7f614624869dca2bd20211872b482eb8fb2a'>; + StorageHashBase<'68cbf64f1e2ea804ae94e926908ae4a093edc4f7e897b835b1eacc66ddd89b2b'>; export type ExecutionHash = ExecutionHashBase; export type ProfileHash = ProfileHashBase<'3916f444a8a17ad749191acf9e08dad97d1a327b88c2f1d45d12f240296aa8b2'>; @@ -423,6 +423,13 @@ type ContractBase = Omit< readonly columns: readonly ['manager_id']; readonly unique: false; }, + { + readonly name: 'person_name_search_2455a3e1'; + readonly prefix: 'person_name_search'; + readonly expression: 'to_tsvector(\'english\', "name")'; + readonly unique: false; + readonly type: 'gin'; + }, ]; foreignKeys: readonly [ { diff --git a/test/integration/test/sql-orm-client/fixtures/self-relations/generated/contract.json b/test/integration/test/sql-orm-client/fixtures/self-relations/generated/contract.json index 20a23e4a63f3..8a459ad86367 100644 --- a/test/integration/test/sql-orm-client/fixtures/self-relations/generated/contract.json +++ b/test/integration/test/sql-orm-client/fixtures/self-relations/generated/contract.json @@ -434,6 +434,13 @@ "name": "people_manager_id_idx_c3dee277", "prefix": "people_manager_id_idx", "unique": false + }, + { + "expression": "to_tsvector('english', \"name\")", + "name": "person_name_search_2455a3e1", + "prefix": "person_name_search", + "type": "gin", + "unique": false } ], "primaryKey": { @@ -606,7 +613,7 @@ "kind": "postgres-schema" } }, - "storageHash": "03064b14cc66f1a136c019a42aef7f614624869dca2bd20211872b482eb8fb2a" + "storageHash": "68cbf64f1e2ea804ae94e926908ae4a093edc4f7e897b835b1eacc66ddd89b2b" }, "capabilities": { "postgres": { From 4c8f1166903a31493a6a9fd4202517133f7e9465 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 09:46:20 +0200 Subject: [PATCH 17/36] docs(postgres): lead with @@fullTextIndex, keep the raw expression as the escape hatch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The README, both skill references, the app upgrade fragment and ADR 253 now show the attribute first. The sentence telling authors to write the `to_tsvector` expression exactly as the operation renders it is gone — that is the attribute's job. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- ... 253 - Target-owned built-in query operations.md | 5 ++++- packages/3-targets/3-targets/postgres/README.md | 6 +++--- skills/prisma-8/references/contract.md | 9 +++++++++ skills/prisma-8/references/queries-postgres.md | 4 ++-- .../postgres-full-text-search/app/instructions.md | 13 +++++++++++++ 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/docs/architecture docs/adrs/ADR 253 - Target-owned built-in query operations.md b/docs/architecture docs/adrs/ADR 253 - Target-owned built-in query operations.md index e552b813f57c..ce491dd5da56 100644 --- a/docs/architecture docs/adrs/ADR 253 - Target-owned built-in query operations.md +++ b/docs/architecture docs/adrs/ADR 253 - Target-owned built-in query operations.md @@ -39,16 +39,19 @@ Full-text search needs no new codec, no capability key and no extension. `tsvect Performance is the application's responsibility, because the operation does not create indexes. `fullTextMatches` renders `to_tsvector('', "")`, so a GIN index that is to answer the predicate must declare exactly that expression: ```prisma -@@index(expression: "to_tsvector('english', \"text\")", type: "gin", name: "message_text_search") +@@fullTextIndex([text], name: "message_text_search") ``` An index whose expression differs — a different language, or a `tsvector` column maintained by a trigger — will not be used. +Because that expression has to match byte for byte, the target contributes the index as well as the operations: `@@fullTextIndex([text], name: …)` renders it from the resolved storage column and the same language allowlist, so an author never writes `to_tsvector` by hand and the two cannot drift apart. This needed no new IR — the attribute lowers to the `IndexNode` `@@index(expression:)` already produces — but it did need the framework to let a contributed model attribute return an index instead of a namespaced entity, and to let a descriptor declare itself repeatable. `@@index(expression:)` stays for expressions the attribute does not cover. + The set of accepted languages is a hand-maintained list. A server with a custom text-search configuration installed cannot name it. That is the price of keeping the language out of the parameter list; widening it later means deciding how Prisma learns what a given server has configured, which is a question this decision does not answer. ## Implementation anchors - The operations and the language list: [`query-operations.ts`](../../../packages/3-targets/3-targets/postgres/src/core/query-operations.ts). +- The index attribute and the one place its expression is rendered: [`authoring.ts`](../../../packages/3-targets/3-targets/postgres/src/core/authoring.ts), [`full-text-index-expression.ts`](../../../packages/3-targets/3-targets/postgres/src/core/full-text-index-expression.ts). - Their type-level surface, re-exported as the package's `./operation-types` entry: [`operation-types.ts`](../../../packages/3-targets/3-targets/postgres/src/types/operation-types.ts). - The runtime target descriptor that contributes them: [`runtime.ts`](../../../packages/3-targets/3-targets/postgres/src/exports/runtime.ts). - The import spec the emitter writes into `contract.d.ts`: [`descriptor-meta.ts`](../../../packages/3-targets/3-targets/postgres/src/core/descriptor-meta.ts). diff --git a/packages/3-targets/3-targets/postgres/README.md b/packages/3-targets/3-targets/postgres/README.md index 0c31ed152917..86a4fc88920e 100644 --- a/packages/3-targets/3-targets/postgres/README.md +++ b/packages/3-targets/3-targets/postgres/README.md @@ -141,13 +141,13 @@ const snippets = db.sql.public.message .build(); ``` -Postgres computes `to_tsvector` per row unless an index covers that exact expression, so declare one in the schema: +Postgres computes `to_tsvector` per row unless an index covers that exact expression, and it only uses an index whose expression matches the query's byte for byte. `@@fullTextIndex`, contributed by this package, renders that expression from the field and the language, so the index and the predicate cannot drift: ```prisma -@@index(expression: "to_tsvector('english', \"text\")", type: "gin", name: "message_text_search") +@@fullTextIndex([text], name: "message_text_search") ``` -Write the index expression exactly as the operation renders it — `to_tsvector('', "")`, with the same language you pass to the operation — or Postgres will not use the index. +It takes exactly one field, an optional `language` (default `english`, from the same allowlist the operations accept), and `name:` xor `map:` like any expression index; it is repeatable, so a model may index several columns. The column name comes from the resolved storage column, so `@map` is honoured. `@@index(expression: "to_tsvector('english', \"text\")", type: "gin", name: …)` still works for anything the attribute does not cover — but then the expression is yours to keep in step. ## Codec descriptor authoring diff --git a/skills/prisma-8/references/contract.md b/skills/prisma-8/references/contract.md index 19935a37f997..d75cfcef2f2c 100644 --- a/skills/prisma-8/references/contract.md +++ b/skills/prisma-8/references/contract.md @@ -126,6 +126,15 @@ Then run `pnpm prisma contract emit` (or rely on the Vite plugin — see `refere `name:` declares a wire-named index (physical name `_<8-hex hash>`, renames plan as `ALTER INDEX … RENAME`); `map:` adopts an exact physical name verbatim (for infer-captured objects — combining it with a SQL body warns, because drift detection byte-compares the authored text against Postgres's reprint). An `expression:` requires `name:` or `map:`. The TS builder mirrors this via `constraints.index([cols.x], {...})` / `constraints.index({ expression, ... })` — see `packages/2-sql/2-authoring/contract-ts/README.md`. +**Full-text search indexes (PostgreSQL).** Do not hand-write the `to_tsvector` expression — Postgres only uses the index when it matches the query byte for byte. Declare `@@fullTextIndex`, which renders the same expression `fullTextMatches` / `fullTextRank` / `fullTextHeadline` lower to (see `references/queries-postgres.md`): + +```prisma +@@fullTextIndex([text], name: "message_text_search") +@@fullTextIndex([summary], language: "german", name: "message_summary_search_de") +``` + +It takes exactly one field, an optional `language` (default `english`, from the same allowlist the operations accept), and `name:` xor `map:` like any expression index. It is repeatable, so a model may index several columns. It lowers to a GIN index over `to_tsvector('', "")` — the column name resolved through `@map` — so `@@index(expression: …)` remains only for expressions this attribute does not cover. + PSL alias surface for repeated types lives in a top-level `types {}` block: ```prisma diff --git a/skills/prisma-8/references/queries-postgres.md b/skills/prisma-8/references/queries-postgres.md index 5750b266af34..5cb3a45bd895 100644 --- a/skills/prisma-8/references/queries-postgres.md +++ b/skills/prisma-8/references/queries-postgres.md @@ -81,10 +81,10 @@ const snippets = db.sql.public.message .build(); ``` -Without an index Postgres recomputes `to_tsvector` for every row. Declare one whose expression matches what the operation renders, character for character, including the language: +Without an index Postgres recomputes `to_tsvector` for every row, and it only uses an index whose expression matches the query's byte for byte. `@@fullTextIndex` renders that expression for you — pass it the field and, if you use one, the same language: ```prisma -@@index(expression: "to_tsvector('english', \"text\")", type: "gin", name: "message_text_search") +@@fullTextIndex([text], name: "message_text_search") ``` **There is no `.between(a, b)` operator.** Express ranges either as two chained `.where(...)` clauses (the idiomatic form — clauses AND-compose) or with the `and(...)` combinator inside one clause: diff --git a/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md b/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md index d4e49c3df912..048ac70f2ae6 100644 --- a/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md +++ b/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md @@ -28,3 +28,16 @@ import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgr Run `prisma contract emit` and commit the regenerated `contract.d.ts`. Nothing else in the file changes, `contract.json` does not change, and no contract hash moves. Do not hand-edit the generated file. Application code that imported `@prisma/orm-postgres/adapter/operation-types` directly imports `@prisma/orm-postgres/target/operation-types` instead. That subpath no longer exists; there is no compatibility re-export. + +To use the new operations, index the column with `@@fullTextIndex`, which renders the `to_tsvector` expression the predicate needs: + +```prisma +model Message { + id Int @id + text String + + @@fullTextIndex([text], name: "message_text_search") +} +``` + +Postgres only uses a full-text index when its expression matches the query's byte for byte, so prefer the attribute over writing `@@index(expression: "to_tsvector(…)", type: "gin", …)` by hand. From 25f2d5539cbf434eb8a49cbe3b79bfed4a86b2d7 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 09:57:17 +0200 Subject: [PATCH 18/36] test(integration): record @@fullTextIndex in the model-attribute surface inventory Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../test/authoring/attribute-specs.lsp-consumability.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/integration/test/authoring/attribute-specs.lsp-consumability.test.ts b/test/integration/test/authoring/attribute-specs.lsp-consumability.test.ts index 109511651659..89b06a68c3e7 100644 --- a/test/integration/test/authoring/attribute-specs.lsp-consumability.test.ts +++ b/test/integration/test/authoring/attribute-specs.lsp-consumability.test.ts @@ -123,6 +123,7 @@ describe('mongo attribute specs are consumable from a resolved language-server p 'check', 'control', 'discriminator', + 'fullTextIndex', 'id', 'index', 'map', From 6cc9f677e72e555750d3169a8c68464638893c49 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 10:02:51 +0200 Subject: [PATCH 19/36] fix(authoring): report a malformed contributed index as a pack contribution error Review rework. A contributed attribute returning the wrong index shape is an extension-author mistake, so it raises `CONTRACT.PACK_CONTRIBUTION_INVALID` with the attribute and model in its payload, like the entries-slot collision beside it, and the error reference lists the case. The narrowing predicate no longer accepts `null` or an array as an options bag, and ADR 236 points at ADR 253 where it describes what a lowering returns. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../adrs/ADR 236 - Target-contributed model attributes.md | 2 +- docs/reference/error-reference.md | 2 +- packages/2-sql/1-core/contract/src/index-naming.ts | 6 +++++- packages/2-sql/2-authoring/contract-psl/src/interpreter.ts | 6 ++++-- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/docs/architecture docs/adrs/ADR 236 - Target-contributed model attributes.md b/docs/architecture docs/adrs/ADR 236 - Target-contributed model attributes.md index 66520c86791e..13e9b45a3589 100644 --- a/docs/architecture docs/adrs/ADR 236 - Target-contributed model attributes.md +++ b/docs/architecture docs/adrs/ADR 236 - Target-contributed model attributes.md @@ -72,7 +72,7 @@ A registry of `AuthoringModelAttributeDescriptor`s. Each descriptor: - **claims a bare `@@` attribute name** (`attribute: 'rls'`); - **supplies a factory for the declarative parameter spec** — a `ModelAttributeSpecFactory`, called with the declaring model's context and returning a spec built with the same `modelAttribute(...)` constructors as every other declarative attribute ([ADR 231](ADR%20231%20-%20Declarative%20attribute%20specifications.md)) — so parsing, validation, and printing come for free from the generic machinery. A spec that needs nothing from the context, like `@@rls`, returns a hoisted module constant so its identity is stable across calls; -- **supplies a `lower` function** that turns the parsed attribute into a pack entity keyed into the namespace's `entries`. +- **supplies a `lower` function** that turns the parsed attribute into a pack entity keyed into the namespace's `entries`. Since [ADR 253](ADR%20253%20-%20Target-owned%20built-in%20query%20operations.md) a lowering may instead return `{ index }`, which the family interpreter files onto the declaring model's table through the same path `@@index` uses — the Postgres `@@fullTextIndex` attribute is the first to do so. The factory indirection is uniform across every registered attribute spec, so one entry shape serves both this channel and the family built-ins that share the registry. diff --git a/docs/reference/error-reference.md b/docs/reference/error-reference.md index 47859dae548b..421b55289f01 100644 --- a/docs/reference/error-reference.md +++ b/docs/reference/error-reference.md @@ -379,7 +379,7 @@ A native type name in the contract fails the identifier-safety pattern required ### CONTRACT.PACK_CONTRIBUTION_INVALID -A composed pack's contribution is malformed or collides with another contribution; this is the extension-author-facing bucket. Covers: entity types colliding with reserved helper keys, duplicate entity kinds or index-type registrations, a registered entity kind with no `lowerEntityHandles` lowering, an invalid `indexTypes` shape, entries-slot collisions between a model attribute and a block entry kind, bad authoring-helper paths, a codec registered with an entity-ref arg but no `columnFromEntity` hook, and print-time contribution mismatches (missing/mismatched PSL block descriptor, param descriptor kind disagreeing with the AST node, unregistered codec id, raw literal that is not valid JSON). Raised during contract authoring/lowering and PSL printing. Payload: `packId`, `contribution`, `reason`, `keyword`, `paramName`, `codecId`. +A composed pack's contribution is malformed or collides with another contribution; this is the extension-author-facing bucket. Covers: entity types colliding with reserved helper keys, duplicate entity kinds or index-type registrations, a registered entity kind with no `lowerEntityHandles` lowering, an invalid `indexTypes` shape, entries-slot collisions between a model attribute and a block entry kind, a model attribute that lowers to a malformed index, bad authoring-helper paths, a codec registered with an entity-ref arg but no `columnFromEntity` hook, and print-time contribution mismatches (missing/mismatched PSL block descriptor, param descriptor kind disagreeing with the AST node, unregistered codec id, raw literal that is not valid JSON). Raised during contract authoring/lowering and PSL printing. Payload: `packId`, `contribution`, `reason`, `keyword`, `paramName`, `codecId`. ### CONTRACT.PACK_FAMILY_MISMATCH diff --git a/packages/2-sql/1-core/contract/src/index-naming.ts b/packages/2-sql/1-core/contract/src/index-naming.ts index 6b609769275c..637e7afcb90c 100644 --- a/packages/2-sql/1-core/contract/src/index-naming.ts +++ b/packages/2-sql/1-core/contract/src/index-naming.ts @@ -67,7 +67,11 @@ export function isAuthoredIndexInput(value: unknown): value is AuthoredIndexInpu if (candidate['unique'] !== undefined && typeof candidate['unique'] !== 'boolean') return false; if (candidate['type'] === undefined) return candidate['options'] === undefined; if (typeof candidate['type'] !== 'string') return false; - return candidate['options'] === undefined || typeof candidate['options'] === 'object'; + const options = candidate['options']; + return ( + options === undefined || + (typeof options === 'object' && options !== null && !Array.isArray(options)) + ); } function isOptionalString(value: unknown): boolean { diff --git a/packages/2-sql/2-authoring/contract-psl/src/interpreter.ts b/packages/2-sql/2-authoring/contract-psl/src/interpreter.ts index 1fd4733c2dd8..c2ed140919d1 100644 --- a/packages/2-sql/2-authoring/contract-psl/src/interpreter.ts +++ b/packages/2-sql/2-authoring/contract-psl/src/interpreter.ts @@ -1199,8 +1199,10 @@ function buildModelNodeFromPsl(input: BuildModelNodeInput): BuildModelNodeResult } if ('index' in lowered) { if (!isAuthoredIndexInput(lowered.index)) { - throw new InternalError( - `Model attribute "@@${modelAttribute.name}" lowered to a malformed index; a contributed attribute that returns { index } must return an authored-index input`, + throw contractError( + 'CONTRACT.PACK_CONTRIBUTION_INVALID', + `model attribute "@@${modelAttribute.name}" on model "${model.name}" lowered to a malformed index. A contributed attribute that returns { index } must return an authored-index input: exactly one of a columns list or an expression, plus explicit where/unique/name/map and a type-with-options pair.`, + { meta: { attribute: modelAttribute.name, modelName: model.name } }, ); } indexNodes.push(lowered.index); From 780e1b4696bbd5f4513b17bbd2c0d42a01e42a63 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 10:12:27 +0200 Subject: [PATCH 20/36] feat(contract-ts): an index expression may be rendered at lowering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `constraints.index({ expression })` now also accepts `{ fields, render }`. The field refs resolve exactly as the fields form resolves them — a `.column()` override first, then the contract column naming convention — and the renderer is handed the resolved names. Authoring code knows neither, so this is the only way an expression over a column can keep matching that column. The rendered string is what reaches the IR; nothing downstream changes. The Postgres facade uses it for `fullTextIndex(cols.text, { name })`, the TypeScript twin of `@@fullTextIndex`, sharing the target's one expression renderer with the PSL attribute. The sql-builder fixture authors it, so `fixtures:check` carries it through a real emit. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../2-sql/2-authoring/contract-ts/README.md | 2 + .../contract-ts/src/contract-dsl.ts | 22 +++- .../contract-ts/src/contract-lowering.ts | 14 ++- .../src/exports/contract-builder.ts | 9 +- ...-builder.deferred-index-expression.test.ts | 111 +++++++++++++++++ .../postgres/src/contract/full-text-index.ts | 37 ++++++ .../postgres/src/exports/contract-builder.ts | 1 + .../contract-builder/full-text-index.test.ts | 117 ++++++++++++++++++ .../3-targets/3-targets/postgres/README.md | 8 ++ skills/prisma-8/references/contract.md | 2 +- .../prisma-8/references/queries-postgres.md | 8 ++ .../test/sql-builder/fixtures/contract.ts | 13 +- .../fixtures/generated/contract.d.ts | 12 +- .../fixtures/generated/contract.json | 12 +- .../app/instructions.md | 12 +- 15 files changed, 367 insertions(+), 13 deletions(-) create mode 100644 packages/2-sql/2-authoring/contract-ts/test/contract-builder.deferred-index-expression.test.ts create mode 100644 packages/3-extensions/postgres/src/contract/full-text-index.ts create mode 100644 packages/3-extensions/postgres/test/contract-builder/full-text-index.test.ts diff --git a/packages/2-sql/2-authoring/contract-ts/README.md b/packages/2-sql/2-authoring/contract-ts/README.md index 0a36a483e00f..fe2e8d04a6b5 100644 --- a/packages/2-sql/2-authoring/contract-ts/README.md +++ b/packages/2-sql/2-authoring/contract-ts/README.md @@ -245,6 +245,8 @@ constraints.index({ expression: 'eql_v3.eq_term(email)', name: 'users_email_eq' - **Fields form** — `constraints.index(cols | [cols...], options?)`. Options: `unique?`, `where?` (partial-index predicate, WHERE body without the keyword), `name?` xor `map?`, and — when the target pack registers index types — `type?` paired with its `options?` (e.g. `type: 'hash', options: {}`). The pack-typed arm requires the `options` key at compile time; PSL accepts `type:` without `options:` (absent validates as `{}`) — both lower to the same IR. - **Expression form** — `constraints.index({ expression, ...options })`. The expression is the whole CREATE INDEX element list as one opaque string; `name` or `map` is required (no default name can be derived from an expression). Same remaining options as the fields form. + The expression may instead be `{ fields, render }`, which defers rendering until lowering knows the storage column names: `fields` are `ColumnRef`s resolved exactly as the fields form resolves them — a `.column()` override first, then the contract's column naming convention — and `render` receives the resolved names in order and returns the element list. Use this whenever the expression names a column, because neither the override nor the naming convention is knowable while the model is being authored; a string written by hand silently stops matching the column it names when either changes. The rendered string is what reaches the IR, so nothing downstream sees a new shape. The Postgres facade's `fullTextIndex(cols.text, { name })` is built this way. + `name:` declares a **wire-named** index: the physical name is `_<8-hex content hash>`, and renames plan as `ALTER INDEX … RENAME`. `map:` adopts an **exact** physical name verbatim (no hash) — intended for objects captured by `contract infer`. Combining `map:` with a SQL body (`expression`/`where`) emits the `PN_EXACT_NAME_BODY_COMPARISON` warning at build time: drift detection byte-compares the authored text against Postgres's reprinted form, which is only reliable for infer-captured text. Prefer `name:` for hand-authored bodies. ### Helper Notes diff --git a/packages/2-sql/2-authoring/contract-ts/src/contract-dsl.ts b/packages/2-sql/2-authoring/contract-ts/src/contract-dsl.ts index 94526bace037..ef7f0699a106 100644 --- a/packages/2-sql/2-authoring/contract-ts/src/contract-dsl.ts +++ b/packages/2-sql/2-authoring/contract-ts/src/contract-dsl.ts @@ -841,7 +841,7 @@ type IndexInput< type ExpressionIndexInput< Name extends string | undefined, IndexTypes extends IndexTypeMap, -> = IndexInput & { readonly expression: string }; +> = IndexInput & { readonly expression: IndexExpressionInput }; type ForeignKeyOptions = ConstraintOptions & { @@ -870,6 +870,22 @@ export type UniqueConstraint string; +}; + +/** Opaque SQL, either written out or rendered at lowering. */ +export type IndexExpressionInput = string | DeferredIndexExpression; + /** An authored index constraint's element structure — field tuple xor expression. */ export type IndexConstraintElements = | { @@ -880,7 +896,7 @@ export type IndexConstraintElements ref.fieldName), + spec.fieldToColumn, + ), + ), + } : { ...carried, columns: mapFieldNamesToColumnNames( diff --git a/packages/2-sql/2-authoring/contract-ts/src/exports/contract-builder.ts b/packages/2-sql/2-authoring/contract-ts/src/exports/contract-builder.ts index 2c72c06829eb..88f016945320 100644 --- a/packages/2-sql/2-authoring/contract-ts/src/exports/contract-builder.ts +++ b/packages/2-sql/2-authoring/contract-ts/src/exports/contract-builder.ts @@ -30,7 +30,14 @@ export type { RelationNode, UniqueConstraintNode, } from '../contract-definition'; -export type { CheckKind, TargetFieldRef } from '../contract-dsl'; +export type { + CheckKind, + ColumnRef, + DeferredIndexExpression, + IndexConstraint, + IndexExpressionInput, + TargetFieldRef, +} from '../contract-dsl'; export { buildContractDefinition } from '../contract-lowering'; export type { ExtractCodecTypesFromPack } from '../contract-types'; export { autoincrement, now } from '../default-functions'; diff --git a/packages/2-sql/2-authoring/contract-ts/test/contract-builder.deferred-index-expression.test.ts b/packages/2-sql/2-authoring/contract-ts/test/contract-builder.deferred-index-expression.test.ts new file mode 100644 index 000000000000..9b7497c6600a --- /dev/null +++ b/packages/2-sql/2-authoring/contract-ts/test/contract-builder.deferred-index-expression.test.ts @@ -0,0 +1,111 @@ +/** + * An index expression may be deferred: the author names fields and supplies a + * renderer, and lowering resolves each field to its storage column before + * rendering. That is the only way an expression index can survive a + * `.column()` override or a contract-level column naming convention, both of + * which are unknown while the model is being authored. + */ +import type { FamilyPackRef, TargetPackRef } from '@internal/framework-components/components'; +import { describe, expect, it } from 'vitest'; +import { createTestSqlNamespace } from '../../../1-core/contract/test/test-support'; +import { type ContractInput, defineContract, field, model } from '../src/contract-builder'; +import { columnDescriptor } from './helpers/column-descriptor'; +import { unboundTables } from './unbound-tables'; + +const int4Column = columnDescriptor('pg/int4@1'); +const textColumn = columnDescriptor('pg/text@1'); + +const bareFamilyPack: FamilyPackRef<'sql'> = { + kind: 'family', + id: 'sql', + familyId: 'sql', + version: '0.0.1', +}; + +const postgresTargetPack: TargetPackRef<'sql', 'postgres'> = { + kind: 'target', + id: 'postgres', + familyId: 'sql', + targetId: 'postgres', + version: '0.0.1', + defaultNamespaceId: 'public', +}; + +const render = (columnNames: readonly string[]) => `to_tsvector('english', "${columnNames[0]}")`; + +function messageIndexes(options: { + readonly mappedColumn?: string; + readonly naming?: ContractInput['naming']; +}) { + const searchText = options.mappedColumn + ? field.column(textColumn).column(options.mappedColumn) + : field.column(textColumn); + const contract = defineContract({ + family: bareFamilyPack, + target: postgresTargetPack, + createNamespace: createTestSqlNamespace, + ...(options.naming !== undefined ? { naming: options.naming } : {}), + models: { + Message: model('Message', { + fields: { id: field.column(int4Column).id(), searchText }, + }).sql(({ cols, constraints }) => ({ + table: 'message', + indexes: [ + constraints.index({ + expression: { fields: [cols.searchText], render }, + name: 'message_text_search', + }), + ], + })), + }, + }); + return unboundTables(contract.storage)['message']!.indexes; +} + +describe('a deferred index expression', () => { + it('renders the column name the default mapping produces', () => { + expect(messageIndexes({})[0]).toMatchObject({ + expression: `to_tsvector('english', "searchText")`, + prefix: 'message_text_search', + }); + }); + + it('renders a .column() override, not the field name', () => { + expect(messageIndexes({ mappedColumn: 'body_text' })[0]).toMatchObject({ + expression: `to_tsvector('english', "body_text")`, + }); + }); + + it("renders the contract's column naming convention", () => { + expect(messageIndexes({ naming: { columns: 'snake_case' } })[0]).toMatchObject({ + expression: `to_tsvector('english', "search_text")`, + }); + }); + + it('lowers to exactly what the equivalent string expression lowers to', () => { + const deferred = messageIndexes({ mappedColumn: 'body_text' }); + const literal = defineContract({ + family: bareFamilyPack, + target: postgresTargetPack, + createNamespace: createTestSqlNamespace, + models: { + Message: model('Message', { + fields: { + id: field.column(int4Column).id(), + searchText: field.column(textColumn).column('body_text'), + }, + }).sql(({ constraints }) => ({ + table: 'message', + indexes: [ + constraints.index({ + expression: `to_tsvector('english', "body_text")`, + name: 'message_text_search', + }), + ], + })), + }, + }); + + expect(deferred).toEqual(unboundTables(literal.storage)['message']!.indexes); + }); +}); diff --git a/packages/3-extensions/postgres/src/contract/full-text-index.ts b/packages/3-extensions/postgres/src/contract/full-text-index.ts new file mode 100644 index 000000000000..296e4cba043c --- /dev/null +++ b/packages/3-extensions/postgres/src/contract/full-text-index.ts @@ -0,0 +1,37 @@ +import type { ColumnRef, IndexConstraint } from '@internal/sql-contract-ts/contract-builder'; +import type { FullTextSearchLanguage } from '@internal/target-postgres/operation-types'; +import { renderFullTextIndexExpression } from '@internal/target-postgres/sql-utils'; + +type FullTextIndexOptions = { readonly language?: FullTextSearchLanguage } & ( + | { readonly name: string; readonly map?: never } + | { readonly map: string; readonly name?: never } +); + +const DEFAULT_LANGUAGE: FullTextSearchLanguage = 'english'; + +/** + * A GIN index over the `to_tsvector` expression `fullTextMatches`, + * `fullTextRank` and `fullTextHeadline` lower to — the TypeScript twin of + * `@@fullTextIndex`. Pass it to a model's `sql({ indexes: [...] })`. + * + * The expression is rendered at lowering, once the column's storage name is + * known, so a `.column()` override or a column naming convention is honoured + * and the index cannot stop matching the predicate. + */ +export function fullTextIndex( + column: ColumnRef, + options: FullTextIndexOptions, +): IndexConstraint { + const language = options.language ?? DEFAULT_LANGUAGE; + return { + kind: 'index', + expression: { + fields: [column], + render: (columnNames: readonly string[]) => + renderFullTextIndexExpression(language, columnNames[0] ?? ''), + }, + type: 'gin', + ...(options.name !== undefined ? { name: options.name } : {}), + ...(options.map !== undefined ? { map: options.map } : {}), + }; +} diff --git a/packages/3-extensions/postgres/src/exports/contract-builder.ts b/packages/3-extensions/postgres/src/exports/contract-builder.ts index d55f725af220..464728f0b425 100644 --- a/packages/3-extensions/postgres/src/exports/contract-builder.ts +++ b/packages/3-extensions/postgres/src/exports/contract-builder.ts @@ -28,6 +28,7 @@ export { } from '@internal/sql-contract-ts/contract-builder'; export { defineContract } from '../contract/define-contract'; export { enumType } from '../contract/enum-type'; +export { fullTextIndex } from '../contract/full-text-index'; export { type NativeEnumHandle, nativeEnum, pg } from '../contract/native-enum'; export { policyAll, diff --git a/packages/3-extensions/postgres/test/contract-builder/full-text-index.test.ts b/packages/3-extensions/postgres/test/contract-builder/full-text-index.test.ts new file mode 100644 index 000000000000..4ab5e7e32a13 --- /dev/null +++ b/packages/3-extensions/postgres/test/contract-builder/full-text-index.test.ts @@ -0,0 +1,117 @@ +/** + * `fullTextIndex(cols.x, { name })` is the TypeScript twin of + * `@@fullTextIndex([x], name: …)`. Both render the expression the full-text + * operations lower to, from the resolved storage column, so the two surfaces + * produce the same index for the same model. + */ +import { assembleAuthoringContributions } from '@internal/framework-components/control'; +import { buildSymbolTable } from '@internal/psl-parser'; +import { parse } from '@internal/psl-parser/syntax'; +import { interpretPslDocumentToSqlContract } from '@internal/sql-contract-psl'; +import postgresTargetControl from '@internal/target-postgres/control'; +import type { PostgresSchema } from '@internal/target-postgres/types'; +import { postgresCreateNamespace } from '@internal/target-postgres/types'; +import { describe, expect, it } from 'vitest'; +import { defineContract, field, fullTextIndex, model } from '../../src/exports/contract-builder'; + +const intColumn = { codecId: 'pg/int4@1', nativeType: 'int4' } as const; +const textColumn = { codecId: 'pg/text@1', nativeType: 'text' } as const; + +const PSL = ` +model Message { + id Int @id + text String @map("body_text") + + @@fullTextIndex([text], name: "message_text_search") + @@map("message") +} +`; + +// The real target descriptor, so the attribute surface under test is the one +// a composed stack actually gets. +const assembled = assembleAuthoringContributions([postgresTargetControl]); + +function pslIndexes() { + const { document, sourceFile } = parse(PSL); + const { table: symbolTable } = buildSymbolTable({ + document, + sourceFile, + pslBlockDescriptors: assembled.pslBlockDescriptors, + }); + const result = interpretPslDocumentToSqlContract({ + symbolTable, + sourceFile, + sourceId: 'schema.prisma', + capabilities: {}, + target: { + kind: 'target', + familyId: 'sql', + targetId: 'postgres', + id: 'postgres', + version: '0.0.1', + capabilities: {}, + defaultNamespaceId: 'public', + indexTypes: postgresTargetControl.indexTypes, + }, + scalarColumnDescriptors: new Map([ + ['Int', { codecId: 'pg/int4@1', nativeType: 'int4' }], + ['String', { codecId: 'pg/text@1', nativeType: 'text' }], + ]), + authoringContributions: assembled, + composedExtensionContracts: new Map(), + createNamespace: postgresCreateNamespace, + }); + expect(result.ok).toBe(true); + if (!result.ok) return []; + const namespace = result.value.storage.namespaces['public'] as PostgresSchema; + return namespace.table['message']?.indexes ?? []; +} + +function tsIndexes() { + const contract = defineContract({ + models: { + Message: model('Message', { + fields: { + id: field.column(intColumn).id(), + text: field.column(textColumn).column('body_text'), + }, + }).sql(({ cols }) => ({ + table: 'message', + indexes: [fullTextIndex(cols.text, { name: 'message_text_search' })], + })), + }, + }); + const namespace = contract.storage.namespaces['public'] as PostgresSchema; + return namespace.table['message']?.indexes ?? []; +} + +describe('fullTextIndex, the TypeScript twin of @@fullTextIndex', () => { + it('renders the storage column name, not the field name', () => { + expect(tsIndexes()[0]).toMatchObject({ + expression: `to_tsvector('english', "body_text")`, + type: 'gin', + prefix: 'message_text_search', + }); + }); + + it('produces the index the PSL attribute produces for the same model', () => { + expect(tsIndexes()).toEqual(pslIndexes()); + }); + + it('renders a non-default language', () => { + const contract = defineContract({ + models: { + Message: model('Message', { + fields: { id: field.column(intColumn).id(), text: field.column(textColumn) }, + }).sql(({ cols }) => ({ + table: 'message', + indexes: [fullTextIndex(cols.text, { language: 'german', name: 'message_de' })], + })), + }, + }); + const namespace = contract.storage.namespaces['public'] as PostgresSchema; + expect(namespace.table['message']?.indexes[0]).toMatchObject({ + expression: `to_tsvector('german', "text")`, + }); + }); +}); diff --git a/packages/3-targets/3-targets/postgres/README.md b/packages/3-targets/3-targets/postgres/README.md index 86a4fc88920e..951ab536f9c2 100644 --- a/packages/3-targets/3-targets/postgres/README.md +++ b/packages/3-targets/3-targets/postgres/README.md @@ -147,6 +147,14 @@ Postgres computes `to_tsvector` per row unless an index covers that exact expres @@fullTextIndex([text], name: "message_text_search") ``` +The TypeScript contract builder has the same helper, exported from the facade's contract-builder entry: + +```typescript +model('Message', { fields: { id, text } }).sql(({ cols }) => ({ + indexes: [fullTextIndex(cols.text, { name: 'message_text_search' })], +})); +``` + It takes exactly one field, an optional `language` (default `english`, from the same allowlist the operations accept), and `name:` xor `map:` like any expression index; it is repeatable, so a model may index several columns. The column name comes from the resolved storage column, so `@map` is honoured. `@@index(expression: "to_tsvector('english', \"text\")", type: "gin", name: …)` still works for anything the attribute does not cover — but then the expression is yours to keep in step. ## Codec descriptor authoring diff --git a/skills/prisma-8/references/contract.md b/skills/prisma-8/references/contract.md index d75cfcef2f2c..dcf5dd5642fc 100644 --- a/skills/prisma-8/references/contract.md +++ b/skills/prisma-8/references/contract.md @@ -133,7 +133,7 @@ Then run `pnpm prisma contract emit` (or rely on the Vite plugin — see `refere @@fullTextIndex([summary], language: "german", name: "message_summary_search_de") ``` -It takes exactly one field, an optional `language` (default `english`, from the same allowlist the operations accept), and `name:` xor `map:` like any expression index. It is repeatable, so a model may index several columns. It lowers to a GIN index over `to_tsvector('', "")` — the column name resolved through `@map` — so `@@index(expression: …)` remains only for expressions this attribute does not cover. +The TS builder has the same helper: `fullTextIndex(cols.text, { name: 'message_text_search' })`, from `@prisma/orm-postgres/contract-builder`, inside the model's `sql({ indexes: [...] })`. It takes exactly one field, an optional `language` (default `english`, from the same allowlist the operations accept), and `name:` xor `map:` like any expression index. It is repeatable, so a model may index several columns. It lowers to a GIN index over `to_tsvector('', "")` — the column name resolved through `@map` — so `@@index(expression: …)` remains only for expressions this attribute does not cover. PSL alias surface for repeated types lives in a top-level `types {}` block: diff --git a/skills/prisma-8/references/queries-postgres.md b/skills/prisma-8/references/queries-postgres.md index 5cb3a45bd895..5372b76d4dca 100644 --- a/skills/prisma-8/references/queries-postgres.md +++ b/skills/prisma-8/references/queries-postgres.md @@ -87,6 +87,14 @@ Without an index Postgres recomputes `to_tsvector` for every row, and it only us @@fullTextIndex([text], name: "message_text_search") ``` +In a TypeScript contract, the same helper from `@prisma/orm-postgres/contract-builder`: + +```typescript +model('Message', { fields: { id, text } }).sql(({ cols }) => ({ + indexes: [fullTextIndex(cols.text, { name: 'message_text_search' })], +})); +``` + **There is no `.between(a, b)` operator.** Express ranges either as two chained `.where(...)` clauses (the idiomatic form — clauses AND-compose) or with the `and(...)` combinator inside one clause: ```typescript diff --git a/test/integration/test/sql-builder/fixtures/contract.ts b/test/integration/test/sql-builder/fixtures/contract.ts index 7594bd89267a..f5cafae9cf1e 100644 --- a/test/integration/test/sql-builder/fixtures/contract.ts +++ b/test/integration/test/sql-builder/fixtures/contract.ts @@ -2,7 +2,13 @@ import { int4Column, textColumn } from '@internal/adapter-postgres/column-types' import { vector } from '@internal/extension-pgvector/column-types'; import pgvector from '@internal/extension-pgvector/pack'; import { uuidv4 } from '@internal/ids'; -import { defineContract, field, model, rel } from '@internal/postgres/contract-builder'; +import { + defineContract, + field, + fullTextIndex, + model, + rel, +} from '@internal/postgres/contract-builder'; const UserBase = model('User', { fields: { @@ -33,7 +39,10 @@ const Comment = model('Comment', { body: field.column(textColumn), postId: field.column(int4Column).column('post_id'), }, -}).sql({ table: 'comments' }); +}).sql(({ cols }) => ({ + table: 'comments', + indexes: [fullTextIndex(cols.body, { name: 'comments_body_search' })], +})); const Profile = model('Profile', { fields: { diff --git a/test/integration/test/sql-builder/fixtures/generated/contract.d.ts b/test/integration/test/sql-builder/fixtures/generated/contract.d.ts index 0fc1e5ff2b7d..634e3e105136 100644 --- a/test/integration/test/sql-builder/fixtures/generated/contract.d.ts +++ b/test/integration/test/sql-builder/fixtures/generated/contract.d.ts @@ -36,7 +36,7 @@ import type { } from '@internal/contract/types'; export type StorageHash = - StorageHashBase<'121dbb4712cd62b323dfeb9c77a406b0f824adb69ed9454150bb537ed460ba38'>; + StorageHashBase<'98799071414933fa0728a9979e3153a32bfec7d95419d408b663c07aab0deca5'>; export type ExecutionHash = ExecutionHashBase<'566d74b60e6b5393dcdbf9f250120fa4e1f12c0ae51e1c0958a131d8ed9667b5'>; export type ProfileHash = @@ -478,7 +478,15 @@ type ContractBase = Omit< }; primaryKey: { readonly columns: readonly ['id'] }; uniques: readonly []; - indexes: readonly []; + indexes: readonly [ + { + readonly name: 'comments_body_search_7b2cde4d'; + readonly prefix: 'comments_body_search'; + readonly expression: 'to_tsvector(\'english\', "body")'; + readonly unique: false; + readonly type: 'gin'; + }, + ]; foreignKeys: readonly []; }; readonly posts: { diff --git a/test/integration/test/sql-builder/fixtures/generated/contract.json b/test/integration/test/sql-builder/fixtures/generated/contract.json index 523227c00b70..57a6efb3bba5 100644 --- a/test/integration/test/sql-builder/fixtures/generated/contract.json +++ b/test/integration/test/sql-builder/fixtures/generated/contract.json @@ -408,7 +408,15 @@ } }, "foreignKeys": [], - "indexes": [], + "indexes": [ + { + "expression": "to_tsvector('english', \"body\")", + "name": "comments_body_search_7b2cde4d", + "prefix": "comments_body_search", + "type": "gin", + "unique": false + } + ], "primaryKey": { "columns": [ "id" @@ -521,7 +529,7 @@ "kind": "postgres-schema" } }, - "storageHash": "121dbb4712cd62b323dfeb9c77a406b0f824adb69ed9454150bb537ed460ba38" + "storageHash": "98799071414933fa0728a9979e3153a32bfec7d95419d408b663c07aab0deca5" }, "execution": { "executionHash": "566d74b60e6b5393dcdbf9f250120fa4e1f12c0ae51e1c0958a131d8ed9667b5", diff --git a/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md b/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md index 048ac70f2ae6..b8dbca1e9e90 100644 --- a/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md +++ b/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md @@ -40,4 +40,14 @@ model Message { } ``` -Postgres only uses a full-text index when its expression matches the query's byte for byte, so prefer the attribute over writing `@@index(expression: "to_tsvector(…)", type: "gin", …)` by hand. +In a TypeScript contract, use the matching helper inside the model's `sql({ indexes: [...] })`: + +```ts +import { fullTextIndex } from '@prisma/orm-postgres/contract-builder'; + +model('Message', { fields: { id, text } }).sql(({ cols }) => ({ + indexes: [fullTextIndex(cols.text, { name: 'message_text_search' })], +})); +``` + +Postgres only uses a full-text index when its expression matches the query's byte for byte, so prefer these over writing `@@index(expression: "to_tsvector(…)", type: "gin", …)` by hand. From d07dbe13a37e4de3bfc1188de7c8bf5f209aa0fd Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 10:15:45 +0200 Subject: [PATCH 21/36] fix(test): type the facade parity test against the shapes both surfaces share The PSL and TS builds produce differently-typed namespace values, so the test reads the one shape they agree on, and interprets PSL against the target pack ref rather than a hand-built target literal that cannot carry index types. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../contract-builder/full-text-index.test.ts | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/packages/3-extensions/postgres/test/contract-builder/full-text-index.test.ts b/packages/3-extensions/postgres/test/contract-builder/full-text-index.test.ts index 4ab5e7e32a13..97d3c910726b 100644 --- a/packages/3-extensions/postgres/test/contract-builder/full-text-index.test.ts +++ b/packages/3-extensions/postgres/test/contract-builder/full-text-index.test.ts @@ -9,11 +9,25 @@ import { buildSymbolTable } from '@internal/psl-parser'; import { parse } from '@internal/psl-parser/syntax'; import { interpretPslDocumentToSqlContract } from '@internal/sql-contract-psl'; import postgresTargetControl from '@internal/target-postgres/control'; -import type { PostgresSchema } from '@internal/target-postgres/types'; +import postgresPack from '@internal/target-postgres/pack'; import { postgresCreateNamespace } from '@internal/target-postgres/types'; +import { blindCast } from '@internal/utils/casts'; import { describe, expect, it } from 'vitest'; import { defineContract, field, fullTextIndex, model } from '../../src/exports/contract-builder'; +/** + * Both surfaces file the index onto the namespace's `message` table; the two + * namespace values have different static types, so this reads the one shape + * both share. + */ +function indexesOfPublicMessage(namespace: unknown): readonly { expression?: string }[] { + const table = blindCast< + { readonly table?: Record }, + 'both the PSL and the TS build produce a Postgres namespace; only its indexes are read here' + >(namespace).table; + return table?.['message']?.indexes ?? []; +} + const intColumn = { codecId: 'pg/int4@1', nativeType: 'int4' } as const; const textColumn = { codecId: 'pg/text@1', nativeType: 'text' } as const; @@ -43,16 +57,7 @@ function pslIndexes() { sourceFile, sourceId: 'schema.prisma', capabilities: {}, - target: { - kind: 'target', - familyId: 'sql', - targetId: 'postgres', - id: 'postgres', - version: '0.0.1', - capabilities: {}, - defaultNamespaceId: 'public', - indexTypes: postgresTargetControl.indexTypes, - }, + target: postgresPack, scalarColumnDescriptors: new Map([ ['Int', { codecId: 'pg/int4@1', nativeType: 'int4' }], ['String', { codecId: 'pg/text@1', nativeType: 'text' }], @@ -63,8 +68,7 @@ function pslIndexes() { }); expect(result.ok).toBe(true); if (!result.ok) return []; - const namespace = result.value.storage.namespaces['public'] as PostgresSchema; - return namespace.table['message']?.indexes ?? []; + return indexesOfPublicMessage(result.value.storage.namespaces['public']); } function tsIndexes() { @@ -81,8 +85,7 @@ function tsIndexes() { })), }, }); - const namespace = contract.storage.namespaces['public'] as PostgresSchema; - return namespace.table['message']?.indexes ?? []; + return indexesOfPublicMessage(contract.storage.namespaces['public']); } describe('fullTextIndex, the TypeScript twin of @@fullTextIndex', () => { @@ -109,8 +112,7 @@ describe('fullTextIndex, the TypeScript twin of @@fullTextIndex', () => { })), }, }); - const namespace = contract.storage.namespaces['public'] as PostgresSchema; - expect(namespace.table['message']?.indexes[0]).toMatchObject({ + expect(indexesOfPublicMessage(contract.storage.namespaces['public'])[0]).toMatchObject({ expression: `to_tsvector('german', "text")`, }); }); From 23abe73c85e35ee6b854fb618823f7531096fdec Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 10:35:36 +0200 Subject: [PATCH 22/36] refactor(postgres): one default language, and assertions that name their codes Review rework. The target exports `DEFAULT_FULL_TEXT_SEARCH_LANGUAGE` beside the expression renderer, and the facade helper reads it instead of declaring its own copy, so the PSL and TypeScript forms cannot default differently; a test pins the helper against the constant. The unreachable field-count guard in the lowering becomes an invariant like the one below it, its comment claiming the opposite deleted, and the three negative attribute tests assert the diagnostic code rather than only the message. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../postgres/src/contract/full-text-index.ts | 9 +++++---- .../test/contract-builder/full-text-index.test.ts | 10 ++++++++++ .../3-targets/3-targets/postgres/src/core/authoring.ts | 7 ++++--- .../3-targets/postgres/src/exports/sql-utils.ts | 1 + .../postgres/test/psl-full-text-index.test.ts | 3 +++ 5 files changed, 23 insertions(+), 7 deletions(-) diff --git a/packages/3-extensions/postgres/src/contract/full-text-index.ts b/packages/3-extensions/postgres/src/contract/full-text-index.ts index 296e4cba043c..b5e21a931515 100644 --- a/packages/3-extensions/postgres/src/contract/full-text-index.ts +++ b/packages/3-extensions/postgres/src/contract/full-text-index.ts @@ -1,14 +1,15 @@ import type { ColumnRef, IndexConstraint } from '@internal/sql-contract-ts/contract-builder'; import type { FullTextSearchLanguage } from '@internal/target-postgres/operation-types'; -import { renderFullTextIndexExpression } from '@internal/target-postgres/sql-utils'; +import { + DEFAULT_FULL_TEXT_SEARCH_LANGUAGE, + renderFullTextIndexExpression, +} from '@internal/target-postgres/sql-utils'; type FullTextIndexOptions = { readonly language?: FullTextSearchLanguage } & ( | { readonly name: string; readonly map?: never } | { readonly map: string; readonly name?: never } ); -const DEFAULT_LANGUAGE: FullTextSearchLanguage = 'english'; - /** * A GIN index over the `to_tsvector` expression `fullTextMatches`, * `fullTextRank` and `fullTextHeadline` lower to — the TypeScript twin of @@ -22,7 +23,7 @@ export function fullTextIndex( column: ColumnRef, options: FullTextIndexOptions, ): IndexConstraint { - const language = options.language ?? DEFAULT_LANGUAGE; + const language = options.language ?? DEFAULT_FULL_TEXT_SEARCH_LANGUAGE; return { kind: 'index', expression: { diff --git a/packages/3-extensions/postgres/test/contract-builder/full-text-index.test.ts b/packages/3-extensions/postgres/test/contract-builder/full-text-index.test.ts index 97d3c910726b..b9443d659521 100644 --- a/packages/3-extensions/postgres/test/contract-builder/full-text-index.test.ts +++ b/packages/3-extensions/postgres/test/contract-builder/full-text-index.test.ts @@ -10,6 +10,10 @@ import { parse } from '@internal/psl-parser/syntax'; import { interpretPslDocumentToSqlContract } from '@internal/sql-contract-psl'; import postgresTargetControl from '@internal/target-postgres/control'; import postgresPack from '@internal/target-postgres/pack'; +import { + DEFAULT_FULL_TEXT_SEARCH_LANGUAGE, + renderFullTextIndexExpression, +} from '@internal/target-postgres/sql-utils'; import { postgresCreateNamespace } from '@internal/target-postgres/types'; import { blindCast } from '@internal/utils/casts'; import { describe, expect, it } from 'vitest'; @@ -101,6 +105,12 @@ describe('fullTextIndex, the TypeScript twin of @@fullTextIndex', () => { expect(tsIndexes()).toEqual(pslIndexes()); }); + it('defaults to the language the target declares, not a copy of it', () => { + expect(tsIndexes()[0]?.expression).toBe( + renderFullTextIndexExpression(DEFAULT_FULL_TEXT_SEARCH_LANGUAGE, 'body_text'), + ); + }); + it('renders a non-default language', () => { const contract = defineContract({ models: { diff --git a/packages/3-targets/3-targets/postgres/src/core/authoring.ts b/packages/3-targets/3-targets/postgres/src/core/authoring.ts index bb969d9ede95..f9b9107ec28a 100644 --- a/packages/3-targets/3-targets/postgres/src/core/authoring.ts +++ b/packages/3-targets/3-targets/postgres/src/core/authoring.ts @@ -810,9 +810,10 @@ export const postgresAuthoringModelAttributes = { repeatable: true, lower: (parsed: PostgresFullTextIndexParsed, ctx: AuthoringModelAttributeContext) => { const fieldName = parsed.fields[0]; - // The spec's refine already diagnosed an empty or multi-field list; a - // lowering still runs after a refine diagnostic, so it returns quietly. - if (fieldName === undefined || parsed.fields.length !== 1) return undefined; + invariant( + fieldName !== undefined && parsed.fields.length === 1, + `@@fullTextIndex on "${ctx.modelName}" lowered with ${parsed.fields.length} fields`, + ); const columnName = ctx.fieldStorageName(fieldName); // `fieldRef()` resolves the name against the declaring model while // parsing, so an unknown field is already a diagnostic by here. diff --git a/packages/3-targets/3-targets/postgres/src/exports/sql-utils.ts b/packages/3-targets/3-targets/postgres/src/exports/sql-utils.ts index f86cf18301e2..ee5c4723e3d2 100644 --- a/packages/3-targets/3-targets/postgres/src/exports/sql-utils.ts +++ b/packages/3-targets/3-targets/postgres/src/exports/sql-utils.ts @@ -6,3 +6,4 @@ export { quoteQualifiedName, validateEnumValueLength, } from '../core/sql-utils'; +export { DEFAULT_FULL_TEXT_SEARCH_LANGUAGE } from '../core/text-search-languages'; diff --git a/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts b/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts index c37af78e2d93..7f14e9887b5f 100644 --- a/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts +++ b/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts @@ -152,6 +152,7 @@ model Message { expect(diagnosticsOf(model(` @@fullTextIndex([text, summary], name: "x")`))).toEqual( expect.arrayContaining([ expect.objectContaining({ + code: 'PSL_FULL_TEXT_INDEX_ONE_FIELD', message: expect.stringContaining('one column'), }), ]), @@ -162,6 +163,7 @@ model Message { expect(diagnosticsOf(model(' @@fullTextIndex([text])'))).toEqual( expect.arrayContaining([ expect.objectContaining({ + code: 'PSL_FULL_TEXT_INDEX_REQUIRES_NAME', message: expect.stringContaining('`name` or `map`'), }), ]), @@ -172,6 +174,7 @@ model Message { expect(diagnosticsOf(model(` @@fullTextIndex([text], name: "a", map: "b")`))).toEqual( expect.arrayContaining([ expect.objectContaining({ + code: 'PSL_FULL_TEXT_INDEX_NAME_XOR_MAP', message: expect.stringContaining('at most one of `name` and `map`'), }), ]), From 3277607aa014e78899660ca05f8d79e25824844a Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 10:36:52 +0200 Subject: [PATCH 23/36] refactor(postgres): assert the resolved column name instead of defaulting it Review rework. Lowering resolves one column name per field it is given, or raises `CONTRACT.FIELD_UNKNOWN`, and the helper passes exactly one ref, so the empty-string fallback could only ever have hidden a bug. It becomes an invariant naming the field, like the one the PSL lowering uses. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../postgres/src/contract/full-text-index.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/3-extensions/postgres/src/contract/full-text-index.ts b/packages/3-extensions/postgres/src/contract/full-text-index.ts index b5e21a931515..540d544ae2c8 100644 --- a/packages/3-extensions/postgres/src/contract/full-text-index.ts +++ b/packages/3-extensions/postgres/src/contract/full-text-index.ts @@ -4,6 +4,7 @@ import { DEFAULT_FULL_TEXT_SEARCH_LANGUAGE, renderFullTextIndexExpression, } from '@internal/target-postgres/sql-utils'; +import { invariant } from '@internal/utils/assertions'; type FullTextIndexOptions = { readonly language?: FullTextSearchLanguage } & ( | { readonly name: string; readonly map?: never } @@ -28,8 +29,16 @@ export function fullTextIndex( kind: 'index', expression: { fields: [column], - render: (columnNames: readonly string[]) => - renderFullTextIndexExpression(language, columnNames[0] ?? ''), + render: (columnNames: readonly string[]) => { + const columnName = columnNames[0]; + // Lowering resolves one name per field it was given, or raises + // `CONTRACT.FIELD_UNKNOWN`; this helper hands it exactly one. + invariant( + columnName !== undefined, + `fullTextIndex resolved no column name for field "${column.fieldName}"`, + ); + return renderFullTextIndexExpression(language, columnName); + }, }, type: 'gin', ...(options.name !== undefined ? { name: options.name } : {}), From 2b9cb0c9300e89b678198b8ad9692328f23ef29d Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 13:03:10 +0200 Subject: [PATCH 24/36] test(integration): prove Postgres uses the full-text index for the SQL we lower Prisma 7 built such an index and the planner never chose it, so nothing here is assumed. The index is created from the DDL our own op factory and adapter render for the fixture contract's index node; the queries are the real lowered SQL and bound params of the SQL builder and the ORM; `EXPLAIN (FORMAT JSON)` on exactly that SQL has to name the index. Two controls keep the assertions honest: a german query must not use the english index, and neither must an index over the same column in another configuration. The fixture gains a varchar sibling of `comments.body` with its own `fullTextIndex`, because a varchar column stores `(col)::text` inside the index expression and that had to be checked rather than assumed. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../test/sql-builder/fixtures/contract.ts | 11 +- .../fixtures/generated/contract.d.ts | 29 +- .../fixtures/generated/contract.json | 30 ++- .../sql-builder/full-text-index-usage.test.ts | 250 ++++++++++++++++++ test/integration/test/sql-builder/setup.ts | 40 ++- 5 files changed, 345 insertions(+), 15 deletions(-) create mode 100644 test/integration/test/sql-builder/full-text-index-usage.test.ts diff --git a/test/integration/test/sql-builder/fixtures/contract.ts b/test/integration/test/sql-builder/fixtures/contract.ts index f5cafae9cf1e..5234f1eb69a5 100644 --- a/test/integration/test/sql-builder/fixtures/contract.ts +++ b/test/integration/test/sql-builder/fixtures/contract.ts @@ -1,4 +1,4 @@ -import { int4Column, textColumn } from '@internal/adapter-postgres/column-types'; +import { int4Column, textColumn, varcharColumn } from '@internal/adapter-postgres/column-types'; import { vector } from '@internal/extension-pgvector/column-types'; import pgvector from '@internal/extension-pgvector/pack'; import { uuidv4 } from '@internal/ids'; @@ -37,11 +37,18 @@ const Comment = model('Comment', { fields: { id: field.column(int4Column).id(), body: field.column(textColumn), + // A varchar sibling of `body`: Postgres stores `(subject)::text` inside the + // index expression, and the full-text integration test checks that a query + // over the same column still matches that index. + subject: field.column(varcharColumn(200)), postId: field.column(int4Column).column('post_id'), }, }).sql(({ cols }) => ({ table: 'comments', - indexes: [fullTextIndex(cols.body, { name: 'comments_body_search' })], + indexes: [ + fullTextIndex(cols.body, { name: 'comments_body_search' }), + fullTextIndex(cols.subject, { name: 'comments_subject_search' }), + ], })); const Profile = model('Profile', { diff --git a/test/integration/test/sql-builder/fixtures/generated/contract.d.ts b/test/integration/test/sql-builder/fixtures/generated/contract.d.ts index 634e3e105136..2290eaf040eb 100644 --- a/test/integration/test/sql-builder/fixtures/generated/contract.d.ts +++ b/test/integration/test/sql-builder/fixtures/generated/contract.d.ts @@ -36,7 +36,7 @@ import type { } from '@internal/contract/types'; export type StorageHash = - StorageHashBase<'98799071414933fa0728a9979e3153a32bfec7d95419d408b663c07aab0deca5'>; + StorageHashBase<'b5bc225c3a57bcc7d0700cbbb16d41db99559a617569122f86e21350fa477a1b'>; export type ExecutionHash = ExecutionHashBase<'566d74b60e6b5393dcdbf9f250120fa4e1f12c0ae51e1c0958a131d8ed9667b5'>; export type ProfileHash = @@ -258,6 +258,7 @@ export type FieldOutputTypes = { readonly body: CodecTypes['pg/text@1']['output']; readonly id: CodecTypes['pg/int4@1']['output']; readonly postId: CodecTypes['pg/int4@1']['output']; + readonly subject: Varchar<200>; }; readonly Post: { readonly embedding: Vector<3> | null; @@ -289,6 +290,7 @@ export type FieldInputTypes = { readonly body: CodecTypes['pg/text@1']['input']; readonly id: CodecTypes['pg/int4@1']['input']; readonly postId: CodecTypes['pg/int4@1']['input']; + readonly subject: CodecTypes['sql/varchar@1']['input']; }; readonly Post: { readonly embedding: CodecTypes['pg/vector@1']['input'] | null; @@ -317,6 +319,7 @@ export type StorageColumnTypes = { readonly body: CodecTypes['pg/text@1']['output']; readonly id: CodecTypes['pg/int4@1']['output']; readonly post_id: CodecTypes['pg/int4@1']['output']; + readonly subject: Varchar<200>; }; readonly posts: { readonly embedding: Vector<3> | null; @@ -348,6 +351,7 @@ export type StorageColumnInputTypes = { readonly body: CodecTypes['pg/text@1']['input']; readonly id: CodecTypes['pg/int4@1']['input']; readonly post_id: CodecTypes['pg/int4@1']['input']; + readonly subject: CodecTypes['sql/varchar@1']['input']; }; readonly posts: { readonly embedding: CodecTypes['pg/vector@1']['input'] | null; @@ -380,6 +384,7 @@ export namespace Models { body: CodecTypes['pg/text@1']['output']; id: CodecTypes['pg/int4@1']['output']; postId: CodecTypes['pg/int4@1']['output']; + subject: Varchar<200>; readonly [RelationKeys]?: never; }; export type public_Post = { @@ -475,6 +480,12 @@ type ContractBase = Omit< readonly codecId: 'pg/int4@1'; readonly nullable: false; }; + readonly subject: { + readonly nativeType: 'character varying'; + readonly codecId: 'sql/varchar@1'; + readonly nullable: false; + readonly typeParams: { readonly length: 200 }; + }; }; primaryKey: { readonly columns: readonly ['id'] }; uniques: readonly []; @@ -486,6 +497,13 @@ type ContractBase = Omit< readonly unique: false; readonly type: 'gin'; }, + { + readonly name: 'comments_subject_search_2b3d17a7'; + readonly prefix: 'comments_subject_search'; + readonly expression: 'to_tsvector(\'english\', "subject")'; + readonly unique: false; + readonly type: 'gin'; + }, ]; foreignKeys: readonly []; }; @@ -634,6 +652,14 @@ type ContractBase = Omit< readonly nullable: false; readonly type: { readonly kind: 'scalar'; readonly codecId: 'pg/int4@1' }; }; + readonly subject: { + readonly nullable: false; + readonly type: { + readonly kind: 'scalar'; + readonly codecId: 'sql/varchar@1'; + readonly typeParams: { readonly length: 200 }; + }; + }; }; readonly relations: Record; readonly storage: { @@ -643,6 +669,7 @@ type ContractBase = Omit< readonly body: { readonly column: 'body' }; readonly id: { readonly column: 'id' }; readonly postId: { readonly column: 'post_id' }; + readonly subject: { readonly column: 'subject' }; }; }; }; diff --git a/test/integration/test/sql-builder/fixtures/generated/contract.json b/test/integration/test/sql-builder/fixtures/generated/contract.json index 57a6efb3bba5..77e2574b0710 100644 --- a/test/integration/test/sql-builder/fixtures/generated/contract.json +++ b/test/integration/test/sql-builder/fixtures/generated/contract.json @@ -85,6 +85,16 @@ "codecId": "pg/int4@1", "kind": "scalar" } + }, + "subject": { + "nullable": false, + "type": { + "codecId": "sql/varchar@1", + "kind": "scalar", + "typeParams": { + "length": 200 + } + } } }, "relations": {}, @@ -98,6 +108,9 @@ }, "postId": { "column": "post_id" + }, + "subject": { + "column": "subject" } }, "namespaceId": "public", @@ -405,6 +418,14 @@ "codecId": "pg/int4@1", "nativeType": "int4", "nullable": false + }, + "subject": { + "codecId": "sql/varchar@1", + "nativeType": "character varying", + "nullable": false, + "typeParams": { + "length": 200 + } } }, "foreignKeys": [], @@ -415,6 +436,13 @@ "prefix": "comments_body_search", "type": "gin", "unique": false + }, + { + "expression": "to_tsvector('english', \"subject\")", + "name": "comments_subject_search_2b3d17a7", + "prefix": "comments_subject_search", + "type": "gin", + "unique": false } ], "primaryKey": { @@ -529,7 +557,7 @@ "kind": "postgres-schema" } }, - "storageHash": "98799071414933fa0728a9979e3153a32bfec7d95419d408b663c07aab0deca5" + "storageHash": "b5bc225c3a57bcc7d0700cbbb16d41db99559a617569122f86e21350fa477a1b" }, "execution": { "executionHash": "566d74b60e6b5393dcdbf9f250120fa4e1f12c0ae51e1c0958a131d8ed9667b5", diff --git a/test/integration/test/sql-builder/full-text-index-usage.test.ts b/test/integration/test/sql-builder/full-text-index-usage.test.ts new file mode 100644 index 000000000000..694c100d732a --- /dev/null +++ b/test/integration/test/sql-builder/full-text-index-usage.test.ts @@ -0,0 +1,250 @@ +/** + * Does Postgres actually use the GIN index our `@@fullTextIndex` attribute + * emits, for the SQL our lanes lower? Prisma 7 built such an index and the + * planner never chose it, so nothing here is assumed: + * + * - the index is created from the DDL our own op factory and adapter render + * for the fixture contract's index node, never hand-written; + * - the queries are the real lowered SQL and bound params of the SQL builder + * and the ORM; + * - `EXPLAIN (FORMAT JSON)` on exactly that SQL has to name the index; + * - two negative controls (a different language, and an index built with the + * one-argument `to_tsvector`) must NOT be chosen, so a passing assertion + * means something. + * + * `enable_seqscan = off` makes this a question of whether the index is usable + * at all rather than one about cost estimates on a small table. + */ +import { + createPostgresBuiltinCodecLookup, + PostgresControlAdapter, +} from '@internal/adapter-postgres/control'; +import { Collection } from '@internal/sql-orm-client'; +import type { SqlQueryPlan } from '@internal/sql-relational-core/plan'; +import { CreateIndexCall } from '@internal/target-postgres/op-factory-call'; +import { blindCast } from '@internal/utils/casts'; +import { beforeAll, describe, expect, it } from 'vitest'; +import { setupIntegrationTest, timeouts } from './setup'; + +const QUERY = 'zebra'; + +/** Every `Index Name` anywhere in an EXPLAIN plan tree. */ +function indexNames(node: unknown): readonly string[] { + if (Array.isArray(node)) return node.flatMap(indexNames); + if (node === null || typeof node !== 'object') return []; + const record: Record = { ...node }; + const own = typeof record['Index Name'] === 'string' ? [record['Index Name']] : []; + return [...own, ...Object.values(record).flatMap(indexNames)]; +} + +/** Every `Node Type` anywhere in an EXPLAIN plan tree. */ +function nodeTypes(node: unknown): readonly string[] { + if (Array.isArray(node)) return node.flatMap(nodeTypes); + if (node === null || typeof node !== 'object') return []; + const record: Record = { ...node }; + const own = typeof record['Node Type'] === 'string' ? [record['Node Type']] : []; + return [...own, ...Object.values(record).flatMap(nodeTypes)]; +} + +describe('full-text index usage', { timeout: timeouts.databaseOperation }, () => { + const { db, runtime, client, contract, context, lower } = setupIntegrationTest(); + + const controlAdapter = new PostgresControlAdapter(createPostgresBuiltinCodecLookup()); + + /** The index nodes the fixture's `fullTextIndex(...)` helpers emitted. */ + function fixtureIndexes() { + const namespace = blindCast< + { readonly table: Record[] }> }, + 'the fixture contract is a Postgres schema; only its comment indexes are read here' + >(contract().storage.namespaces['public']); + return namespace.table['comments']!.indexes; + } + + async function createIndexFromContract(index: Record) { + const call = new CreateIndexCall( + 'public', + 'comments', + String(index['name']), + { expression: String(index['expression']) }, + { type: String(index['type']) }, + ); + const op = await call.toOp(controlAdapter); + for (const step of op.execute) { + await client().query(step.sql); + } + return op.execute[0]!.sql; + } + + /** `lowerSqlPlan` already unwrapped the renderer's slots to bare bound values. */ + async function explain(sql: string, params: readonly unknown[]) { + const result = await client().query(`EXPLAIN (FORMAT JSON) ${sql}`, [...params]); + return result.rows[0]['QUERY PLAN']; + } + + function loweredOf(plan: SqlQueryPlan) { + return lower(plan); + } + + beforeAll(async () => { + for (const index of fixtureIndexes()) await createIndexFromContract(index); + + // A control index over the same column in another configuration: buildable, + // and not the expression our english query renders. + await client().query( + `CREATE INDEX comments_body_simple ON comments USING gin (to_tsvector('simple', "body"))`, + ); + + await client().query(` + INSERT INTO comments (id, body, subject, post_id) + SELECT 1000 + n, + CASE WHEN n % 97 = 0 THEN 'a zebra grazes here' ELSE 'ordinary filler text ' || n END, + CASE WHEN n % 97 = 0 THEN 'zebra subject' ELSE 'filler subject ' || n END, + 1 + FROM generate_series(1, 600) AS n + `); + await client().query('ANALYZE comments'); + await client().query('SET enable_seqscan = off'); + }, timeouts.spinUpPpgDev); + + it('creates the index from the DDL our own op factory and adapter render', async () => { + const [bodyIndex] = fixtureIndexes(); + expect(bodyIndex).toBeDefined(); + if (bodyIndex === undefined) return; + const call = new CreateIndexCall( + 'public', + 'comments', + String(bodyIndex['name']), + { expression: String(bodyIndex['expression']) }, + { type: String(bodyIndex['type']) }, + ); + const op = await call.toOp(controlAdapter); + + expect(op.execute[0]?.sql).toBe( + `CREATE INDEX "comments_body_search_7b2cde4d" ON "public"."comments" USING "gin" (to_tsvector('english', "body"))`, + ); + }); + + it('lowers the predicate to the index expression, with the query bound as a parameter', () => { + const lowered = loweredOf( + db() + .public.comments.select('id') + .where((f, fns) => fns.fullTextMatches(f.body, QUERY)) + .build(), + ); + + // Byte-identical to the index expression in the builder's case. The ORM + // qualifies the column instead, and still matches: Postgres compares parsed + // expression trees, not text. + expect(lowered.sql).toContain(`to_tsvector('english', "body")`); + expect(lowered.sql).toContain(`websearch_to_tsquery('english', $1)`); + expect(lowered.params).toEqual([QUERY]); + }); + + it('uses the index for the SQL builder predicate', async () => { + const lowered = loweredOf( + db() + .public.comments.select('id') + .where((f, fns) => fns.fullTextMatches(f.body, QUERY)) + .build(), + ); + + const plan = await explain(lowered.sql, lowered.params); + expect(indexNames(plan)).toContain('comments_body_search_7b2cde4d'); + }); + + it('uses the index when the same predicate is ordered by rank and limited', async () => { + const lowered = loweredOf( + db() + .public.comments.select('id') + .where((f, fns) => fns.fullTextMatches(f.body, QUERY)) + .orderBy((f, fns) => fns.fullTextRank(f.body, QUERY), { direction: 'desc' }) + .limit(10) + .build(), + ); + + const plan = await explain(lowered.sql, lowered.params); + expect(indexNames(plan)).toContain('comments_body_search_7b2cde4d'); + }); + + it('uses the index for the ORM predicate ordered by rank', async () => { + const captured: SqlQueryPlan[] = []; + const real = runtime(); + const recording = blindCast< + typeof real, + 'a recording proxy over the suite runtime; the collection only queries through it' + >({ + ...real, + query: ((plan: SqlQueryPlan, options?: Parameters[1]) => { + captured.push(plan); + return real.query(plan, options); + }) satisfies (...args: never[]) => unknown, + }); + + const comments = new Collection({ runtime: recording, context: context() }, 'Comment', { + namespaceId: 'public', + }); + await comments + .select('id') + .where((row) => row.body.fullTextMatches(QUERY)) + .orderBy((row) => row.body.fullTextRank(QUERY).desc()) + .all(); + + const plan = captured[0]; + expect(plan).toBeDefined(); + if (plan === undefined) return; + const lowered = loweredOf(plan); + expect(lowered.sql).toContain(`to_tsvector('english', "comments"."body")`); + + const explained = await explain(lowered.sql, lowered.params); + expect(indexNames(explained)).toContain('comments_body_search_7b2cde4d'); + }); + + it('matches the index on a varchar column too', async () => { + const lowered = loweredOf( + db() + .public.comments.select('id') + .where((f, fns) => fns.fullTextMatches(f.subject, QUERY)) + .build(), + ); + + const plan = await explain(lowered.sql, lowered.params); + expect(indexNames(plan)).toContain('comments_subject_search_2b3d17a7'); + }); + + describe('negative controls', () => { + it('does not use the english index for a german query', async () => { + const lowered = loweredOf( + db() + .public.comments.select('id') + .where((f, fns) => fns.fullTextMatches(f.body, QUERY, 'german')) + .build(), + ); + + const plan = await explain(lowered.sql, lowered.params); + expect(indexNames(plan)).not.toContain('comments_body_search_7b2cde4d'); + expect(nodeTypes(plan)).toContain('Seq Scan'); + }); + + it('does not use an index over the same column in another configuration', async () => { + const lowered = loweredOf( + db() + .public.comments.select('id') + .where((f, fns) => fns.fullTextMatches(f.body, QUERY)) + .build(), + ); + + const plan = await explain(lowered.sql, lowered.params); + expect(indexNames(plan)).not.toContain('comments_body_simple'); + }); + + // The one-argument `to_tsvector(body)` reads `default_text_search_config`, + // so it is not IMMUTABLE and Postgres refuses to index it at all. Rendering + // the configuration into the expression, as the attribute does, is what + // makes the index possible — not merely what makes it match. + it('rejects an index over the one-argument to_tsvector outright', async () => { + await expect( + client().query('CREATE INDEX c_default_config ON comments USING gin (to_tsvector(body))'), + ).rejects.toThrow(/IMMUTABLE/); + }); + }); +}); diff --git a/test/integration/test/sql-builder/setup.ts b/test/integration/test/sql-builder/setup.ts index c56c17bf167e..27ae6951fdfd 100644 --- a/test/integration/test/sql-builder/setup.ts +++ b/test/integration/test/sql-builder/setup.ts @@ -5,10 +5,13 @@ import pgvector from '@internal/extension-pgvector/runtime'; import { instantiateExecutionStack } from '@internal/framework-components/execution'; import { PostgresRuntimeImpl } from '@internal/postgres/runtime'; import { sql } from '@internal/sql-builder/runtime'; +import type { Adapter, AnyQueryAst, LoweredStatement } from '@internal/sql-relational-core/ast'; +import type { SqlQueryPlan } from '@internal/sql-relational-core/plan'; import type { ExecutionContext } from '@internal/sql-relational-core/query-lane-context'; import { createExecutionContext, createSqlExecutionStack, + lowerSqlPlan, type Runtime, } from '@internal/sql-runtime'; import postgresTarget, { PostgresContractSerializer } from '@internal/target-postgres/runtime'; @@ -30,11 +33,13 @@ const sqlContract = blindCast< export function setupIntegrationTest() { let runtime: Runtime; let context: ExecutionContext; + let client: Client; + let adapter: Adapter; const closeFns: Array<() => Promise> = []; beforeAll(async () => { const database = await createDevDatabase(); - const client = new Client({ connectionString: database.connectionString }); + client = new Client({ connectionString: database.connectionString }); await client.connect(); await setupTestDatabase(client, sqlContract, async (c) => { @@ -60,6 +65,7 @@ export function setupIntegrationTest() { CREATE TABLE comments ( id int4 PRIMARY KEY, body text NOT NULL, + subject varchar(200) NOT NULL, post_id int4 NOT NULL ) `); @@ -86,16 +92,16 @@ export function setupIntegrationTest() { (4, 'Another One', 3, 10, '[1,1,0]') `); await c.query(` - INSERT INTO comments (id, body, post_id) VALUES - (1, 'Great post!', 1), - (2, 'Nice work', 1), - (3, 'Interesting', 3), - (101, 'alice wrote the report', 1), - (102, 'alice met alice and alice again', 1), - (103, 'bob wrote the report', 1), - (104, 'the quick brown fox jumps', 1), - (105, 'a brown dog and a quick cat', 1), - (106, 'alice manuscript draft', 1) + INSERT INTO comments (id, body, subject, post_id) VALUES + (1, 'Great post!', 'praise', 1), + (2, 'Nice work', 'praise', 1), + (3, 'Interesting', 'remark', 3), + (101, 'alice wrote the report', 'alice subject line', 1), + (102, 'alice met alice and alice again', 'meeting notes', 1), + (103, 'bob wrote the report', 'bob subject line', 1), + (104, 'the quick brown fox jumps', 'animals', 1), + (105, 'a brown dog and a quick cat', 'animals', 1), + (106, 'alice manuscript draft', 'drafts', 1) `); await c.query(` INSERT INTO profiles (id, user_id, bio) VALUES @@ -131,6 +137,10 @@ export function setupIntegrationTest() { driver: cursorDisabledDriver, }); const driver = stackInstance.driver!; + adapter = blindCast< + Adapter, + 'the stack-composed adapter lowers this contract; the instance type erases the contract parameter' + >(stackInstance.adapter); await driver.connect({ kind: 'pgClient', client }); runtime = new PostgresRuntimeImpl({ @@ -159,5 +169,13 @@ export function setupIntegrationTest() { return { db: () => sql({ context, rawCodecInferer: postgresRawCodecInferer }), runtime: () => runtime, + /** The contract the fixture emits, for tests that read its storage. */ + contract: () => sqlContract, + /** The execution context, for tests that drive another lane over the same stack. */ + context: () => context, + /** The raw connection, for tests that need SQL the DSL does not express (EXPLAIN, DDL). */ + client: () => client, + /** The SQL and bound params a plan lowers to, exactly as the runtime sends them. */ + lower: (plan: SqlQueryPlan) => lowerSqlPlan(adapter, sqlContract, plan), }; } From a0f4bc6aadcc69debf780ef67d8c63b1e7b0cfc2 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 13:13:00 +0200 Subject: [PATCH 25/36] test(integration): record the cast Postgres stores in the varchar index `pg_get_indexdef` shows the expression as `to_tsvector(...,(subject)::text)`: Postgres adds the cast because the function takes text, and adds the same one to the query, which is why a varchar column matches an index our renderer wrote as `"subject"`. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../test/sql-builder/full-text-index-usage.test.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/integration/test/sql-builder/full-text-index-usage.test.ts b/test/integration/test/sql-builder/full-text-index-usage.test.ts index 694c100d732a..b325526d1c96 100644 --- a/test/integration/test/sql-builder/full-text-index-usage.test.ts +++ b/test/integration/test/sql-builder/full-text-index-usage.test.ts @@ -211,6 +211,17 @@ describe('full-text index usage', { timeout: timeouts.databaseOperation }, () => expect(indexNames(plan)).toContain('comments_subject_search_2b3d17a7'); }); + it('stores the varchar index with the cast Postgres adds, and matches it anyway', async () => { + const definition = await client().query( + `SELECT pg_get_indexdef('comments_subject_search_2b3d17a7'::regclass) AS def`, + ); + + // Postgres rewrites our `"subject"` to `(subject)::text` inside the stored + // expression, because `to_tsvector(regconfig, text)` takes text. The query + // gets the same implicit cast, which is why the two still meet. + expect(definition.rows[0].def).toContain('(subject)::text'); + }); + describe('negative controls', () => { it('does not use the english index for a german query', async () => { const lowered = loweredOf( From 5d3e474be3f5245ae164f74062ede2b97362bb03 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 14:31:28 +0200 Subject: [PATCH 26/36] docs(postgres): state the real index-matching rule, and the silent language trap The integration test proved the docs overstated it: Postgres compares parsed expressions, not text, so the SQL builder's unqualified column and the ORM's qualified one both match the same index. The rule is the same `to_tsvector`, the same configuration literal and the same column. Each place also gains the one trap a user can fall into: a language mismatch between the index and the operation raises nothing, it just stops using the index. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../ADR 253 - Target-owned built-in query operations.md | 7 ++++--- packages/3-targets/3-targets/postgres/README.md | 4 ++-- .../postgres/src/core/full-text-index-expression.ts | 8 ++++---- skills/prisma-8/references/contract.md | 4 ++-- skills/prisma-8/references/queries-postgres.md | 4 +++- .../pending/postgres-full-text-search/app/instructions.md | 2 +- 6 files changed, 16 insertions(+), 13 deletions(-) diff --git a/docs/architecture docs/adrs/ADR 253 - Target-owned built-in query operations.md b/docs/architecture docs/adrs/ADR 253 - Target-owned built-in query operations.md index ce491dd5da56..1937573df2d3 100644 --- a/docs/architecture docs/adrs/ADR 253 - Target-owned built-in query operations.md +++ b/docs/architecture docs/adrs/ADR 253 - Target-owned built-in query operations.md @@ -36,15 +36,15 @@ An extension or application that imported `@internal/adapter-postgres/operation- Full-text search needs no new codec, no capability key and no extension. `tsvector` and `tsquery` never leave the server — they are constructed and consumed inside a single expression — so nothing has to cross the wire in a shape the codec registry does not already know. -Performance is the application's responsibility, because the operation does not create indexes. `fullTextMatches` renders `to_tsvector('', "")`, so a GIN index that is to answer the predicate must declare exactly that expression: +Performance is the application's responsibility, because the operation does not create indexes. `fullTextMatches` renders `to_tsvector('', "")`, so a GIN index that is to answer the predicate has to be the same `to_tsvector` over the same configuration literal and the same column — Postgres compares parsed expressions, not text, so qualifying the column or not makes no difference: ```prisma @@fullTextIndex([text], name: "message_text_search") ``` -An index whose expression differs — a different language, or a `tsvector` column maintained by a trigger — will not be used. +An index whose expression differs — a different language, or a `tsvector` column maintained by a trigger — will not be used, and nothing says so: the query simply falls back to a sequential scan, with no error and no warning. That silent failure is the reason the attribute exists. -Because that expression has to match byte for byte, the target contributes the index as well as the operations: `@@fullTextIndex([text], name: …)` renders it from the resolved storage column and the same language allowlist, so an author never writes `to_tsvector` by hand and the two cannot drift apart. This needed no new IR — the attribute lowers to the `IndexNode` `@@index(expression:)` already produces — but it did need the framework to let a contributed model attribute return an index instead of a namespaced entity, and to let a descriptor declare itself repeatable. `@@index(expression:)` stays for expressions the attribute does not cover. +Because the index and the predicate have to agree on the function, the configuration and the column, the target contributes the index as well as the operations: `@@fullTextIndex([text], name: …)` renders it from the resolved storage column and the same language allowlist, so an author never writes `to_tsvector` by hand and the two cannot drift apart. This needed no new IR — the attribute lowers to the `IndexNode` `@@index(expression:)` already produces — but it did need the framework to let a contributed model attribute return an index instead of a namespaced entity, and to let a descriptor declare itself repeatable. `@@index(expression:)` stays for expressions the attribute does not cover. The set of accepted languages is a hand-maintained list. A server with a custom text-search configuration installed cannot name it. That is the price of keeping the language out of the parameter list; widening it later means deciding how Prisma learns what a given server has configured, which is a question this decision does not answer. @@ -52,6 +52,7 @@ The set of accepted languages is a hand-maintained list. A server with a custom - The operations and the language list: [`query-operations.ts`](../../../packages/3-targets/3-targets/postgres/src/core/query-operations.ts). - The index attribute and the one place its expression is rendered: [`authoring.ts`](../../../packages/3-targets/3-targets/postgres/src/core/authoring.ts), [`full-text-index-expression.ts`](../../../packages/3-targets/3-targets/postgres/src/core/full-text-index-expression.ts). +- That Postgres really does choose the index for the SQL the lanes lower, proved with `EXPLAIN` against a real server, including the controls that fail: [`full-text-index-usage.test.ts`](../../../test/integration/test/sql-builder/full-text-index-usage.test.ts). - Their type-level surface, re-exported as the package's `./operation-types` entry: [`operation-types.ts`](../../../packages/3-targets/3-targets/postgres/src/types/operation-types.ts). - The runtime target descriptor that contributes them: [`runtime.ts`](../../../packages/3-targets/3-targets/postgres/src/exports/runtime.ts). - The import spec the emitter writes into `contract.d.ts`: [`descriptor-meta.ts`](../../../packages/3-targets/3-targets/postgres/src/core/descriptor-meta.ts). diff --git a/packages/3-targets/3-targets/postgres/README.md b/packages/3-targets/3-targets/postgres/README.md index 951ab536f9c2..2c60cf5d4ed7 100644 --- a/packages/3-targets/3-targets/postgres/README.md +++ b/packages/3-targets/3-targets/postgres/README.md @@ -141,7 +141,7 @@ const snippets = db.sql.public.message .build(); ``` -Postgres computes `to_tsvector` per row unless an index covers that exact expression, and it only uses an index whose expression matches the query's byte for byte. `@@fullTextIndex`, contributed by this package, renders that expression from the field and the language, so the index and the predicate cannot drift: +Postgres computes `to_tsvector` per row unless an index covers the predicate's expression — the same `to_tsvector`, the same configuration literal and the same column, which it compares as parsed expressions rather than as text. `@@fullTextIndex`, contributed by this package, renders that expression from the field and the language, so the index and the predicate cannot drift: ```prisma @@fullTextIndex([text], name: "message_text_search") @@ -155,7 +155,7 @@ model('Message', { fields: { id, text } }).sql(({ cols }) => ({ })); ``` -It takes exactly one field, an optional `language` (default `english`, from the same allowlist the operations accept), and `name:` xor `map:` like any expression index; it is repeatable, so a model may index several columns. The column name comes from the resolved storage column, so `@map` is honoured. `@@index(expression: "to_tsvector('english', \"text\")", type: "gin", name: …)` still works for anything the attribute does not cover — but then the expression is yours to keep in step. +It takes exactly one field, an optional `language` (default `english`, from the same allowlist the operations accept), and `name:` xor `map:` like any expression index; it is repeatable, so a model may index several columns. Pass the same `language` here and to the operation: a mismatch is not an error, the query just stops using the index and falls back to a sequential scan. The column name comes from the resolved storage column, so `@map` is honoured. `@@index(expression: "to_tsvector('english', \"text\")", type: "gin", name: …)` still works for anything the attribute does not cover — but then the expression is yours to keep in step. ## Codec descriptor authoring diff --git a/packages/3-targets/3-targets/postgres/src/core/full-text-index-expression.ts b/packages/3-targets/3-targets/postgres/src/core/full-text-index-expression.ts index e2d0fa1515a3..940b3debba81 100644 --- a/packages/3-targets/3-targets/postgres/src/core/full-text-index-expression.ts +++ b/packages/3-targets/3-targets/postgres/src/core/full-text-index-expression.ts @@ -3,10 +3,10 @@ import type { FullTextSearchLanguage } from './text-search-languages'; /** * The index expression that covers `fullTextMatches`, `fullTextRank` and - * `fullTextHeadline` on a column. Postgres only uses an expression index when - * the indexed expression matches the query's byte for byte, so both the - * `@@fullTextIndex` attribute and the TypeScript helper render it here rather - * than each spelling it out. + * `fullTextHeadline` on a column. Postgres uses an expression index only when the + * indexed expression is the same `to_tsvector` over the same configuration literal and + * the same column as the query, so both the `@@fullTextIndex` attribute and the + * TypeScript helper render it here rather than each spelling it out. */ export function renderFullTextIndexExpression( language: FullTextSearchLanguage, diff --git a/skills/prisma-8/references/contract.md b/skills/prisma-8/references/contract.md index dcf5dd5642fc..0d5991a24746 100644 --- a/skills/prisma-8/references/contract.md +++ b/skills/prisma-8/references/contract.md @@ -126,14 +126,14 @@ Then run `pnpm prisma contract emit` (or rely on the Vite plugin — see `refere `name:` declares a wire-named index (physical name `_<8-hex hash>`, renames plan as `ALTER INDEX … RENAME`); `map:` adopts an exact physical name verbatim (for infer-captured objects — combining it with a SQL body warns, because drift detection byte-compares the authored text against Postgres's reprint). An `expression:` requires `name:` or `map:`. The TS builder mirrors this via `constraints.index([cols.x], {...})` / `constraints.index({ expression, ... })` — see `packages/2-sql/2-authoring/contract-ts/README.md`. -**Full-text search indexes (PostgreSQL).** Do not hand-write the `to_tsvector` expression — Postgres only uses the index when it matches the query byte for byte. Declare `@@fullTextIndex`, which renders the same expression `fullTextMatches` / `fullTextRank` / `fullTextHeadline` lower to (see `references/queries-postgres.md`): +**Full-text search indexes (PostgreSQL).** Do not hand-write the `to_tsvector` expression — Postgres only uses the index when it is the same `to_tsvector` over the same configuration literal and the same column as the query. Declare `@@fullTextIndex`, which renders the same expression `fullTextMatches` / `fullTextRank` / `fullTextHeadline` lower to (see `references/queries-postgres.md`): ```prisma @@fullTextIndex([text], name: "message_text_search") @@fullTextIndex([summary], language: "german", name: "message_summary_search_de") ``` -The TS builder has the same helper: `fullTextIndex(cols.text, { name: 'message_text_search' })`, from `@prisma/orm-postgres/contract-builder`, inside the model's `sql({ indexes: [...] })`. It takes exactly one field, an optional `language` (default `english`, from the same allowlist the operations accept), and `name:` xor `map:` like any expression index. It is repeatable, so a model may index several columns. It lowers to a GIN index over `to_tsvector('', "")` — the column name resolved through `@map` — so `@@index(expression: …)` remains only for expressions this attribute does not cover. +The TS builder has the same helper: `fullTextIndex(cols.text, { name: 'message_text_search' })`, from `@prisma/orm-postgres/contract-builder`, inside the model's `sql({ indexes: [...] })`. It takes exactly one field, an optional `language` (default `english`, from the same allowlist the operations accept), and `name:` xor `map:` like any expression index. It is repeatable, so a model may index several columns. Give the index and the operation the same `language` — a mismatch is silent, costing the index and falling back to a sequential scan. It lowers to a GIN index over `to_tsvector('', "")` — the column name resolved through `@map` — so `@@index(expression: …)` remains only for expressions this attribute does not cover. PSL alias surface for repeated types lives in a top-level `types {}` block: diff --git a/skills/prisma-8/references/queries-postgres.md b/skills/prisma-8/references/queries-postgres.md index 5372b76d4dca..2e8886959c70 100644 --- a/skills/prisma-8/references/queries-postgres.md +++ b/skills/prisma-8/references/queries-postgres.md @@ -81,12 +81,14 @@ const snippets = db.sql.public.message .build(); ``` -Without an index Postgres recomputes `to_tsvector` for every row, and it only uses an index whose expression matches the query's byte for byte. `@@fullTextIndex` renders that expression for you — pass it the field and, if you use one, the same language: +Without an index Postgres recomputes `to_tsvector` for every row, and it only uses one whose expression is the same `to_tsvector` over the same configuration literal and the same column. `@@fullTextIndex` renders that expression for you — pass it the field and, if you use one, the same language: ```prisma @@fullTextIndex([text], name: "message_text_search") ``` +Give the index and the operation the same `language`: a mismatch raises no error, the query silently falls back to a sequential scan. + In a TypeScript contract, the same helper from `@prisma/orm-postgres/contract-builder`: ```typescript diff --git a/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md b/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md index b8dbca1e9e90..71b3bd83697e 100644 --- a/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md +++ b/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md @@ -50,4 +50,4 @@ model('Message', { fields: { id, text } }).sql(({ cols }) => ({ })); ``` -Postgres only uses a full-text index when its expression matches the query's byte for byte, so prefer these over writing `@@index(expression: "to_tsvector(…)", type: "gin", …)` by hand. +Postgres only uses a full-text index whose expression is the same `to_tsvector` over the same configuration literal and the same column as the query, so prefer these over writing `@@index(expression: "to_tsvector(…)", type: "gin", …)` by hand. Pass the same `language` to the index and to the operation: a mismatch is silent, and the query falls back to a sequential scan. From c1f14bbd7c35d7235c616003f7a76f520ab55255 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 15:21:37 +0200 Subject: [PATCH 27/36] test(postgres): pin the options surface for the full-text operations Red. The three operations take one options object where the language used to sit positionally, `fullTextRank` gains `normalization` and `coverDensity`, `fullTextHeadline` gains the five `ts_headline` options, and `@@fullTextIndex` gains `where`. Every existing case moves to the new argument shape, and with no option beyond the language the templates must not move at all. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../postgres/test/psl-full-text-index.test.ts | 14 +++ .../postgres/test/query-operations.test.ts | 94 ++++++++++++++++++- .../sql-builder/extension-functions.test.ts | 33 ++++++- .../sql-builder/full-text-index-usage.test.ts | 18 +++- .../playground/extension-functions.test-d.ts | 23 ++++- .../extension-operations.test-d.ts | 4 +- 6 files changed, 177 insertions(+), 9 deletions(-) diff --git a/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts b/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts index 7f14e9887b5f..b9c055d2aa29 100644 --- a/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts +++ b/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts @@ -139,6 +139,20 @@ model Message { ]); }); + it('passes a where predicate through to the index, like @@index(expression:, where:)', () => { + const typed = indexesOf( + model(` @@fullTextIndex([text], where: "id > 0", name: "message_text_search_live")`), + ); + const authored = indexesOf( + model( + ` @@index(expression: "to_tsvector('english', \\"text\\")", type: "gin", where: "id > 0", name: "message_text_search_live")`, + ), + ); + + expect(typed).toEqual(authored); + expect(typed[0]).toMatchObject({ where: 'id > 0', partial: true }); + }); + it('rejects a language Postgres does not ship, naming the ones it does', () => { const [diagnostic] = diagnosticsOf( model(` @@fullTextIndex([text], language: "klingon", name: "x")`), diff --git a/packages/3-targets/3-targets/postgres/test/query-operations.test.ts b/packages/3-targets/3-targets/postgres/test/query-operations.test.ts index bef138a9ccd8..f68c9917cd9c 100644 --- a/packages/3-targets/3-targets/postgres/test/query-operations.test.ts +++ b/packages/3-targets/3-targets/postgres/test/query-operations.test.ts @@ -80,7 +80,7 @@ describe('postgres target query operations', () => { it('embeds the language as a literal, defaulting to english', () => { const withDefault = buildOpAst(method, TEXT_COLUMN, 'prisma').args[1]; - const withGerman = buildOpAst(method, TEXT_COLUMN, 'prisma', 'german').args[1]; + const withGerman = buildOpAst(method, TEXT_COLUMN, 'prisma', { language: 'german' }).args[1]; expect(withDefault?.kind).toBe('literal'); expect(withDefault).toBeInstanceOf(LiteralExpr); @@ -89,8 +89,9 @@ describe('postgres target query operations', () => { }); it('rejects a language Postgres has no configuration for', () => { - expect(() => buildOpAst(method, TEXT_COLUMN, 'prisma', 'klingon')).toThrow(/klingon/); - expect(() => buildOpAst(method, TEXT_COLUMN, 'prisma', 'klingon')).toThrow( + const klingon = { language: 'klingon' }; + expect(() => buildOpAst(method, TEXT_COLUMN, 'prisma', klingon)).toThrow(/klingon/); + expect(() => buildOpAst(method, TEXT_COLUMN, 'prisma', klingon)).toThrow( expect.objectContaining({ code: 'RUNTIME.ARGUMENT_INVALID' }), ); }); @@ -100,6 +101,93 @@ describe('postgres target query operations', () => { }); }); + describe('fullTextRank options', () => { + const rankTemplate = (ast: OperationExpr) => ast.lowering?.template; + + it('renders ts_rank with no normalization argument when none is given', () => { + expect(rankTemplate(buildOpAst('fullTextRank', TEXT_COLUMN, 'prisma', {}))).toBe( + 'ts_rank(to_tsvector({{arg1}}, {{self}}), websearch_to_tsquery({{arg1}}, {{arg0}}))', + ); + }); + + it('embeds normalization as a numeric literal in a third argument', () => { + const ast = buildOpAst('fullTextRank', TEXT_COLUMN, 'prisma', { normalization: 32 }); + + expect(rankTemplate(ast)).toBe( + 'ts_rank(to_tsvector({{arg1}}, {{self}}), websearch_to_tsquery({{arg1}}, {{arg0}}), {{arg2}})', + ); + expect(ast.args[2]).toBeInstanceOf(LiteralExpr); + expect((ast.args[2] as LiteralExpr).value).toBe(32); + }); + + it('renders ts_rank_cd when coverDensity is set', () => { + expect( + rankTemplate(buildOpAst('fullTextRank', TEXT_COLUMN, 'prisma', { coverDensity: true })), + ).toBe( + 'ts_rank_cd(to_tsvector({{arg1}}, {{self}}), websearch_to_tsquery({{arg1}}, {{arg0}}))', + ); + expect( + rankTemplate(buildOpAst('fullTextRank', TEXT_COLUMN, 'prisma', { coverDensity: false })), + ).toBe('ts_rank(to_tsvector({{arg1}}, {{self}}), websearch_to_tsquery({{arg1}}, {{arg0}}))'); + }); + + it.each([-1, 64, 1.5])('rejects a normalization of %s', (normalization) => { + expect(() => buildOpAst('fullTextRank', TEXT_COLUMN, 'prisma', { normalization })).toThrow( + expect.objectContaining({ code: 'RUNTIME.ARGUMENT_INVALID' }), + ); + }); + }); + + describe('fullTextHeadline options', () => { + const optionsLiteral = (ast: OperationExpr) => (ast.args[2] as LiteralExpr | undefined)?.value; + + it('omits the options argument when only the language is given', () => { + const ast = buildOpAst('fullTextHeadline', TEXT_COLUMN, 'prisma', { language: 'german' }); + + expect(ast.lowering?.template).toBe( + 'ts_headline({{arg1}}, {{self}}, websearch_to_tsquery({{arg1}}, {{arg0}}))', + ); + expect(ast.args).toHaveLength(3); + }); + + it("renders the options as Postgres's Key=Value list, in one literal", () => { + const ast = buildOpAst('fullTextHeadline', TEXT_COLUMN, 'prisma', { + startSel: '', + stopSel: '', + maxWords: 20, + minWords: 5, + highlightAll: false, + }); + + expect(ast.lowering?.template).toBe( + 'ts_headline({{arg1}}, {{self}}, websearch_to_tsquery({{arg1}}, {{arg0}}), {{arg2}})', + ); + expect(optionsLiteral(ast)).toBe( + 'StartSel=, StopSel=, MaxWords=20, MinWords=5, HighlightAll=false', + ); + }); + + it('rejects a maxWords that is not a positive integer', () => { + for (const maxWords of [0, -3, 2.5]) { + expect(() => buildOpAst('fullTextHeadline', TEXT_COLUMN, 'p', { maxWords })).toThrow( + expect.objectContaining({ code: 'RUNTIME.ARGUMENT_INVALID' }), + ); + } + }); + + it('rejects a minWords greater than maxWords', () => { + expect(() => + buildOpAst('fullTextHeadline', TEXT_COLUMN, 'p', { minWords: 10, maxWords: 5 }), + ).toThrow(expect.objectContaining({ code: 'RUNTIME.ARGUMENT_INVALID' })); + }); + + it.each(['', 'a,b', 'a=b', 'a"b'])('rejects the marker %o', (startSel) => { + expect(() => buildOpAst('fullTextHeadline', TEXT_COLUMN, 'p', { startSel })).toThrow( + expect.objectContaining({ code: 'RUNTIME.ARGUMENT_INVALID' }), + ); + }); + }); + it('ilike dispatches on the textual trait', () => { expect(findOperation('ilike').self).toEqual({ traits: ['textual'] }); }); diff --git a/test/integration/test/sql-builder/extension-functions.test.ts b/test/integration/test/sql-builder/extension-functions.test.ts index 7c6a1c7779b4..e740b9325b64 100644 --- a/test/integration/test/sql-builder/extension-functions.test.ts +++ b/test/integration/test/sql-builder/extension-functions.test.ts @@ -94,7 +94,7 @@ describe('integration: full-text search', { timeout: timeouts.databaseOperation .where((f, fns) => language === undefined ? fns.fullTextMatches(f.body, query) - : fns.fullTextMatches(f.body, query, language), + : fns.fullTextMatches(f.body, query, { language }), ) .build(), ); @@ -128,6 +128,37 @@ describe('integration: full-text search', { timeout: timeouts.databaseOperation expect(rows.map((row) => row.id)[0]).toBe(102); }); + it('fullTextHeadline takes the markers it is given', async () => { + const row = await runtime() + .query( + db() + .public.comments.select('id') + .select('snippet', (f, fns) => + fns.fullTextHeadline(f.body, 'alice', { startSel: '', stopSel: '' }), + ) + .where((f, fns) => fns.eq(f.id, 101)) + .build(), + ) + .firstOrThrow(); + expect(row.snippet).toBe('alice wrote the report'); + }); + + it('fullTextRank normalizes the score into (0, 1] when asked', async () => { + const rows = await runtime().query( + db() + .public.comments.select('id') + .select('rank', (f, fns) => fns.fullTextRank(f.body, 'alice', { normalization: 32 })) + .where((f, fns) => fns.fullTextMatches(f.body, 'alice')) + .build(), + ); + + expect(rows.length).toBeGreaterThan(0); + for (const row of rows) { + expect(row.rank).toBeGreaterThan(0); + expect(row.rank).toBeLessThanOrEqual(1); + } + }); + it('fullTextHeadline marks the matched word up', async () => { const row = await runtime() .query( diff --git a/test/integration/test/sql-builder/full-text-index-usage.test.ts b/test/integration/test/sql-builder/full-text-index-usage.test.ts index b325526d1c96..6020158cce54 100644 --- a/test/integration/test/sql-builder/full-text-index-usage.test.ts +++ b/test/integration/test/sql-builder/full-text-index-usage.test.ts @@ -222,12 +222,28 @@ describe('full-text index usage', { timeout: timeouts.databaseOperation }, () => expect(definition.rows[0].def).toContain('(subject)::text'); }); + it('uses a partial index for a query carrying the same predicate', async () => { + await client().query( + `CREATE INDEX comments_body_live ON comments USING gin (to_tsvector('english', "body")) WHERE (post_id = 1)`, + ); + const lowered = loweredOf( + db() + .public.comments.select('id') + .where((f, fns) => fns.fullTextMatches(f.body, QUERY)) + .where((f, fns) => fns.eq(f.postId, 1)) + .build(), + ); + + const plan = await explain(lowered.sql, lowered.params); + expect(indexNames(plan)).toContain('comments_body_live'); + }); + describe('negative controls', () => { it('does not use the english index for a german query', async () => { const lowered = loweredOf( db() .public.comments.select('id') - .where((f, fns) => fns.fullTextMatches(f.body, QUERY, 'german')) + .where((f, fns) => fns.fullTextMatches(f.body, QUERY, { language: 'german' })) .build(), ); diff --git a/test/integration/test/sql-builder/playground/extension-functions.test-d.ts b/test/integration/test/sql-builder/playground/extension-functions.test-d.ts index 53f9cc27f1c7..15ae66a13271 100644 --- a/test/integration/test/sql-builder/playground/extension-functions.test-d.ts +++ b/test/integration/test/sql-builder/playground/extension-functions.test-d.ts @@ -82,10 +82,29 @@ test('fullTextHeadline returns a non-nullable text expression', () => { }); test('the language argument is one of the configurations Postgres ships with', () => { - db.public.users.select('id').where((f, fns) => fns.fullTextMatches(f.name, 'alice', 'german')); + db.public.users + .select('id') + .where((f, fns) => fns.fullTextMatches(f.name, 'alice', { language: 'german' })); db.public.users .select('id') // @ts-expect-error 'klingon' is not a PostgreSQL text-search configuration - .where((f, fns) => fns.fullTextMatches(f.name, 'alice', 'klingon')); + .where((f, fns) => fns.fullTextMatches(f.name, 'alice', { language: 'klingon' })); +}); + +test('rank and headline options are typed', () => { + db.public.users + .select('id') + .select('rank', (f, fns) => fns.fullTextRank(f.name, 'alice', { normalization: 32 })) + .select('snippet', (f, fns) => fns.fullTextHeadline(f.name, 'alice', { startSel: '' })); + + db.public.users + .select('id') + // @ts-expect-error normalization is a number, not a word + .select('rank', (f, fns) => fns.fullTextRank(f.name, 'alice', { normalization: 'high' })); + + db.public.users + .select('id') + // @ts-expect-error startSel is the marker text, not a number + .select('snippet', (f, fns) => fns.fullTextHeadline(f.name, 'alice', { startSel: 1 })); }); diff --git a/test/integration/test/sql-orm-client/extension-operations.test-d.ts b/test/integration/test/sql-orm-client/extension-operations.test-d.ts index ae3b83d25d23..412bda34a051 100644 --- a/test/integration/test/sql-orm-client/extension-operations.test-d.ts +++ b/test/integration/test/sql-orm-client/extension-operations.test-d.ts @@ -179,8 +179,8 @@ describe('full-text search operations on text fields', () => { test('the language argument is one of the configurations Postgres ships with', () => { const title = null as unknown as PostAccessor['title']; - title.fullTextMatches('alice', 'german'); + title.fullTextMatches('alice', { language: 'german' }); // @ts-expect-error 'klingon' is not a PostgreSQL text-search configuration - title.fullTextMatches('alice', 'klingon'); + title.fullTextMatches('alice', { language: 'klingon' }); }); }); From 5150fad297255d87a7258c96c7ea7ae7384379d6 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 15:23:23 +0200 Subject: [PATCH 28/36] feat(postgres): the full-text operations take an options object MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The language moves into it, and two operations gain the rest of what their Postgres functions offer: `fullTextRank` takes a `normalization` bitmask and `coverDensity` (which selects `ts_rank_cd`), `fullTextHeadline` takes the five `ts_headline` options, rendered as its fourth argument in Postgres's `Key=Value` syntax and omitted entirely when nothing but a language was given — so a call that passes no options renders exactly the SQL it rendered before. Every option is an inline literal, never a parameter, so `full-text-options.ts` checks each one and throws `RUNTIME.ARGUMENT_INVALID` before a statement exists: the normalization range, whole positive word counts with minWords no greater than maxWords, and markers that cannot carry ts_headline's own delimiters. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../postgres/src/core/full-text-options.ts | 138 ++++++++++++++++++ .../postgres/src/core/query-operations.ts | 72 ++++----- .../postgres/src/exports/operation-types.ts | 5 + .../postgres/src/types/operation-types.ts | 12 +- .../postgres/test/query-operations.test.ts | 3 +- 5 files changed, 192 insertions(+), 38 deletions(-) create mode 100644 packages/3-targets/3-targets/postgres/src/core/full-text-options.ts diff --git a/packages/3-targets/3-targets/postgres/src/core/full-text-options.ts b/packages/3-targets/3-targets/postgres/src/core/full-text-options.ts new file mode 100644 index 000000000000..df339588f42c --- /dev/null +++ b/packages/3-targets/3-targets/postgres/src/core/full-text-options.ts @@ -0,0 +1,138 @@ +import { LiteralExpr } from '@internal/sql-relational-core/ast'; +import { postgresError } from './errors'; +import { + type FullTextSearchLanguage, + isFullTextSearchLanguage, + POSTGRES_TEXT_SEARCH_LANGUAGES, +} from './text-search-languages'; + +/** + * Every option below reaches the SQL as an inline literal rather than a bound + * parameter, because Postgres accepts no parameter in these positions. Each is + * therefore checked here first; anything unrecognized throws + * `RUNTIME.ARGUMENT_INVALID` before a statement exists. + */ + +export interface FullTextMatchesOptions { + /** Text-search configuration. Defaults to `english`. */ + readonly language?: FullTextSearchLanguage; +} + +export interface FullTextRankOptions extends FullTextMatchesOptions { + /** `ts_rank` normalization bitmask, 0 to 63; see the PostgreSQL manual. */ + readonly normalization?: number; + /** Rank by cover density (`ts_rank_cd`) instead of `ts_rank`. */ + readonly coverDensity?: boolean; +} + +export interface FullTextHeadlineOptions extends FullTextMatchesOptions { + /** Markup placed before each match. */ + readonly startSel?: string; + /** Markup placed after each match. */ + readonly stopSel?: string; + /** Longest headline, in words. */ + readonly maxWords?: number; + /** Shortest headline, in words; at most `maxWords` when both are given. */ + readonly minWords?: number; + /** Mark up the whole document rather than extracting fragments. */ + readonly highlightAll?: boolean; +} + +function invalid(method: string, argument: string, received: unknown, why: string, fix: string) { + return postgresError('RUNTIME.ARGUMENT_INVALID', `${method}: ${why}`, { + why: 'The option is written into the SQL as an inline literal, not a bound parameter, so it is checked before the statement is built.', + fix, + meta: { helper: method, argument, received }, + }); +} + +export function languageLiteral(method: string, language: string): LiteralExpr { + if (!isFullTextSearchLanguage(language)) { + throw invalid( + method, + 'language', + language, + `'${language}' is not a PostgreSQL text-search configuration Prisma recognizes.`, + `Pass one of: ${POSTGRES_TEXT_SEARCH_LANGUAGES.join(', ')}.`, + ); + } + return LiteralExpr.of(language); +} + +export function normalizationLiteral(method: string, normalization: number): LiteralExpr { + if (!Number.isInteger(normalization) || normalization < 0 || normalization > 63) { + throw invalid( + method, + 'normalization', + normalization, + `normalization must be an integer between 0 and 63, received ${normalization}.`, + 'Combine the flags documented for ts_rank, e.g. 32 to divide the rank by itself plus one.', + ); + } + return LiteralExpr.of(normalization); +} + +function checkWordCount(method: string, argument: string, value: number): void { + if (!Number.isInteger(value) || value < 1) { + throw invalid( + method, + argument, + value, + `${argument} must be a positive integer, received ${value}.`, + 'Pass a whole number of words, one or more.', + ); + } +} + +function checkMarker(method: string, argument: string, value: string): void { + if (value.length === 0 || /["=,]/.test(value)) { + throw invalid( + method, + argument, + value, + `${argument} must be non-empty and free of " , and =, received ${JSON.stringify(value)}.`, + 'ts_headline parses its options as a quoted, comma-separated list of Key=Value pairs, so a marker carrying those characters cannot survive it. Use markup such as or .', + ); + } +} + +/** + * The fourth `ts_headline` argument: one text literal of `Key=Value` pairs. + * Returns `undefined` when nothing but the language was given, so the common + * call keeps rendering the three-argument form. + */ +export function headlineOptionsLiteral( + method: string, + options: FullTextHeadlineOptions, +): LiteralExpr | undefined { + const pairs: string[] = []; + if (options.startSel !== undefined) { + checkMarker(method, 'startSel', options.startSel); + pairs.push(`StartSel=${options.startSel}`); + } + if (options.stopSel !== undefined) { + checkMarker(method, 'stopSel', options.stopSel); + pairs.push(`StopSel=${options.stopSel}`); + } + if (options.maxWords !== undefined) { + checkWordCount(method, 'maxWords', options.maxWords); + pairs.push(`MaxWords=${options.maxWords}`); + } + if (options.minWords !== undefined) { + checkWordCount(method, 'minWords', options.minWords); + if (options.maxWords !== undefined && options.minWords > options.maxWords) { + throw invalid( + method, + 'minWords', + options.minWords, + `minWords (${options.minWords}) cannot exceed maxWords (${options.maxWords}).`, + 'Lower minWords, or raise maxWords.', + ); + } + pairs.push(`MinWords=${options.minWords}`); + } + if (options.highlightAll !== undefined) { + pairs.push(`HighlightAll=${options.highlightAll}`); + } + return pairs.length === 0 ? undefined : LiteralExpr.of(pairs.join(', ')); +} diff --git a/packages/3-targets/3-targets/postgres/src/core/query-operations.ts b/packages/3-targets/3-targets/postgres/src/core/query-operations.ts index 439aac7b6349..cb5388a96ce0 100644 --- a/packages/3-targets/3-targets/postgres/src/core/query-operations.ts +++ b/packages/3-targets/3-targets/postgres/src/core/query-operations.ts @@ -1,32 +1,22 @@ -import { LiteralExpr } from '@internal/sql-relational-core/ast'; import { buildOperation, toExpr } from '@internal/sql-relational-core/expression'; import type { QueryOperationTypes } from '../types/operation-types'; import { PG_BOOL_CODEC_ID, PG_FLOAT4_CODEC_ID, PG_TEXT_CODEC_ID } from './codec-ids'; -import { postgresError } from './errors'; import { - DEFAULT_FULL_TEXT_SEARCH_LANGUAGE, - isFullTextSearchLanguage, - POSTGRES_TEXT_SEARCH_LANGUAGES, -} from './text-search-languages'; + type FullTextHeadlineOptions, + type FullTextMatchesOptions, + type FullTextRankOptions, + headlineOptionsLiteral, + languageLiteral, + normalizationLiteral, +} from './full-text-options'; +import { DEFAULT_FULL_TEXT_SEARCH_LANGUAGE } from './text-search-languages'; type CodecTypesBase = Record; const TEXT_REF = { codecId: PG_TEXT_CODEC_ID } as const; -function languageLiteral(method: string, language: string): LiteralExpr { - if (!isFullTextSearchLanguage(language)) { - throw postgresError( - 'RUNTIME.ARGUMENT_INVALID', - `${method}: '${language}' is not a PostgreSQL text-search configuration Prisma recognizes.`, - { - why: 'The language is written into the SQL as an inline literal, not a bound parameter, so it is checked against the configurations a stock PostgreSQL server ships with.', - fix: `Pass one of: ${POSTGRES_TEXT_SEARCH_LANGUAGES.join(', ')}.`, - meta: { helper: method, argument: 'language', received: language }, - }, - ); - } - return LiteralExpr.of(language); -} +const languageOf = (options: FullTextMatchesOptions) => + options.language ?? DEFAULT_FULL_TEXT_SEARCH_LANGUAGE; export function postgresQueryOperations(): QueryOperationTypes { return { @@ -42,13 +32,13 @@ export function postgresQueryOperations(): QueryOpera }, fullTextMatches: { self: { traits: ['textual'] }, - impl: (self, query, language = DEFAULT_FULL_TEXT_SEARCH_LANGUAGE) => + impl: (self, query, options: FullTextMatchesOptions = {}) => buildOperation({ method: 'fullTextMatches', args: [ toExpr(self), toExpr(query, TEXT_REF), - languageLiteral('fullTextMatches', language), + languageLiteral('fullTextMatches', languageOf(options)), ], returns: { codecId: PG_BOOL_CODEC_ID, nullable: false }, lowering: { @@ -60,36 +50,52 @@ export function postgresQueryOperations(): QueryOpera }, fullTextRank: { self: { traits: ['textual'] }, - impl: (self, query, language = DEFAULT_FULL_TEXT_SEARCH_LANGUAGE) => - buildOperation({ + impl: (self, query, options: FullTextRankOptions = {}) => { + const fn = options.coverDensity === true ? 'ts_rank_cd' : 'ts_rank'; + const normalization = + options.normalization === undefined + ? undefined + : normalizationLiteral('fullTextRank', options.normalization); + const vectorAndQuery = + 'to_tsvector({{arg1}}, {{self}}), websearch_to_tsquery({{arg1}}, {{arg0}})'; + return buildOperation({ method: 'fullTextRank', - args: [toExpr(self), toExpr(query, TEXT_REF), languageLiteral('fullTextRank', language)], + args: [ + toExpr(self), + toExpr(query, TEXT_REF), + languageLiteral('fullTextRank', languageOf(options)), + ...(normalization === undefined ? [] : [normalization]), + ], returns: { codecId: PG_FLOAT4_CODEC_ID, nullable: false }, lowering: { targetFamily: 'sql', strategy: 'function', - template: - 'ts_rank(to_tsvector({{arg1}}, {{self}}), websearch_to_tsquery({{arg1}}, {{arg0}}))', + template: `${fn}(${vectorAndQuery}${normalization === undefined ? '' : ', {{arg2}}'})`, }, - }), + }); + }, }, fullTextHeadline: { self: { traits: ['textual'] }, - impl: (self, query, language = DEFAULT_FULL_TEXT_SEARCH_LANGUAGE) => - buildOperation({ + impl: (self, query, options: FullTextHeadlineOptions = {}) => { + const headlineOptions = headlineOptionsLiteral('fullTextHeadline', options); + const base = 'ts_headline({{arg1}}, {{self}}, websearch_to_tsquery({{arg1}}, {{arg0}})'; + return buildOperation({ method: 'fullTextHeadline', args: [ toExpr(self), toExpr(query, TEXT_REF), - languageLiteral('fullTextHeadline', language), + languageLiteral('fullTextHeadline', languageOf(options)), + ...(headlineOptions === undefined ? [] : [headlineOptions]), ], returns: { codecId: PG_TEXT_CODEC_ID, nullable: false }, lowering: { targetFamily: 'sql', strategy: 'function', - template: 'ts_headline({{arg1}}, {{self}}, websearch_to_tsquery({{arg1}}, {{arg0}}))', + template: `${base}${headlineOptions === undefined ? '' : ', {{arg2}}'})`, }, - }), + }); + }, }, }; } diff --git a/packages/3-targets/3-targets/postgres/src/exports/operation-types.ts b/packages/3-targets/3-targets/postgres/src/exports/operation-types.ts index 710188a5e585..6c2380e56936 100644 --- a/packages/3-targets/3-targets/postgres/src/exports/operation-types.ts +++ b/packages/3-targets/3-targets/postgres/src/exports/operation-types.ts @@ -1,2 +1,7 @@ +export type { + FullTextHeadlineOptions, + FullTextMatchesOptions, + FullTextRankOptions, +} from '../core/full-text-options'; export type { FullTextSearchLanguage } from '../core/text-search-languages'; export type { QueryOperationTypes } from '../types/operation-types'; diff --git a/packages/3-targets/3-targets/postgres/src/types/operation-types.ts b/packages/3-targets/3-targets/postgres/src/types/operation-types.ts index 5c9fe2e44492..a0c21328fcaf 100644 --- a/packages/3-targets/3-targets/postgres/src/types/operation-types.ts +++ b/packages/3-targets/3-targets/postgres/src/types/operation-types.ts @@ -4,7 +4,11 @@ import type { Expression, TraitExpression, } from '@internal/sql-relational-core/expression'; -import type { FullTextSearchLanguage } from '../core/text-search-languages'; +import type { + FullTextHeadlineOptions, + FullTextMatchesOptions, + FullTextRankOptions, +} from '../core/full-text-options'; type CodecTypesBase = Record; @@ -29,7 +33,7 @@ export type QueryOperationTypes = SqlQueryOperationTy readonly impl: ( self: TextualSelf, query: TextArgument, - language?: FullTextSearchLanguage, + options?: FullTextMatchesOptions, ) => Expression<{ codecId: 'pg/bool@1'; nullable: false }>; }; readonly fullTextRank: { @@ -37,7 +41,7 @@ export type QueryOperationTypes = SqlQueryOperationTy readonly impl: ( self: TextualSelf, query: TextArgument, - language?: FullTextSearchLanguage, + options?: FullTextRankOptions, ) => Expression<{ codecId: 'pg/float4@1'; nullable: false }>; }; readonly fullTextHeadline: { @@ -45,7 +49,7 @@ export type QueryOperationTypes = SqlQueryOperationTy readonly impl: ( self: TextualSelf, query: TextArgument, - language?: FullTextSearchLanguage, + options?: FullTextHeadlineOptions, ) => Expression<{ codecId: 'pg/text@1'; nullable: false }>; }; } diff --git a/packages/3-targets/3-targets/postgres/test/query-operations.test.ts b/packages/3-targets/3-targets/postgres/test/query-operations.test.ts index f68c9917cd9c..721f02f0dd03 100644 --- a/packages/3-targets/3-targets/postgres/test/query-operations.test.ts +++ b/packages/3-targets/3-targets/postgres/test/query-operations.test.ts @@ -147,7 +147,8 @@ describe('postgres target query operations', () => { expect(ast.lowering?.template).toBe( 'ts_headline({{arg1}}, {{self}}, websearch_to_tsquery({{arg1}}, {{arg0}}))', ); - expect(ast.args).toHaveLength(3); + // query, language — and no third argument. + expect(ast.args).toHaveLength(2); }); it("renders the options as Postgres's Key=Value list, in one literal", () => { From 8a86f967bc6e98974c0193ef34366929fa61bfb3 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 15:24:30 +0200 Subject: [PATCH 29/36] feat(postgres): @@fullTextIndex and the TS helper take a where predicate Both pass it straight to the index node, so a partial full-text index is the same `@@index(expression:, where:)` the string form produces and goes through the same validation. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../postgres/src/contract/full-text-index.ts | 7 ++++- .../contract-builder/full-text-index.test.ts | 30 +++++++++++++++++-- .../3-targets/postgres/src/core/authoring.ts | 7 ++++- .../postgres/test/psl-full-text-index.test.ts | 2 +- 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/packages/3-extensions/postgres/src/contract/full-text-index.ts b/packages/3-extensions/postgres/src/contract/full-text-index.ts index 540d544ae2c8..556ff21e8fea 100644 --- a/packages/3-extensions/postgres/src/contract/full-text-index.ts +++ b/packages/3-extensions/postgres/src/contract/full-text-index.ts @@ -6,7 +6,11 @@ import { } from '@internal/target-postgres/sql-utils'; import { invariant } from '@internal/utils/assertions'; -type FullTextIndexOptions = { readonly language?: FullTextSearchLanguage } & ( +type FullTextIndexOptions = { + readonly language?: FullTextSearchLanguage; + /** The SQL predicate restricting rows included in a partial index. */ + readonly where?: string; +} & ( | { readonly name: string; readonly map?: never } | { readonly map: string; readonly name?: never } ); @@ -41,6 +45,7 @@ export function fullTextIndex( }, }, type: 'gin', + ...(options.where !== undefined ? { where: options.where } : {}), ...(options.name !== undefined ? { name: options.name } : {}), ...(options.map !== undefined ? { map: options.map } : {}), }; diff --git a/packages/3-extensions/postgres/test/contract-builder/full-text-index.test.ts b/packages/3-extensions/postgres/test/contract-builder/full-text-index.test.ts index b9443d659521..e624d7f36229 100644 --- a/packages/3-extensions/postgres/test/contract-builder/full-text-index.test.ts +++ b/packages/3-extensions/postgres/test/contract-builder/full-text-index.test.ts @@ -24,9 +24,16 @@ import { defineContract, field, fullTextIndex, model } from '../../src/exports/c * namespace values have different static types, so this reads the one shape * both share. */ -function indexesOfPublicMessage(namespace: unknown): readonly { expression?: string }[] { +function indexesOfPublicMessage( + namespace: unknown, +): readonly { expression?: string; where?: string }[] { const table = blindCast< - { readonly table?: Record }, + { + readonly table?: Record< + string, + { readonly indexes?: readonly { expression?: string; where?: string }[] } + >; + }, 'both the PSL and the TS build produce a Postgres namespace; only its indexes are read here' >(namespace).table; return table?.['message']?.indexes ?? []; @@ -111,6 +118,25 @@ describe('fullTextIndex, the TypeScript twin of @@fullTextIndex', () => { ); }); + it('passes a where predicate through to a partial index', () => { + const contract = defineContract({ + models: { + Message: model('Message', { + fields: { id: field.column(intColumn).id(), text: field.column(textColumn) }, + }).sql(({ cols }) => ({ + table: 'message', + indexes: [ + fullTextIndex(cols.text, { where: 'id > 0', name: 'message_text_search_live' }), + ], + })), + }, + }); + + expect(indexesOfPublicMessage(contract.storage.namespaces['public'])[0]).toMatchObject({ + where: 'id > 0', + }); + }); + it('renders a non-default language', () => { const contract = defineContract({ models: { diff --git a/packages/3-targets/3-targets/postgres/src/core/authoring.ts b/packages/3-targets/3-targets/postgres/src/core/authoring.ts index f9b9107ec28a..ef6d9e06b3de 100644 --- a/packages/3-targets/3-targets/postgres/src/core/authoring.ts +++ b/packages/3-targets/3-targets/postgres/src/core/authoring.ts @@ -735,6 +735,10 @@ const postgresFullTextIndexSpec = modelAttribute('fullTextIndex', { type: optional(str()), documentation: 'The database index name. Mutually exclusive with `name`.', }, + where: { + type: optional(str()), + documentation: 'The SQL predicate restricting rows included in a partial index.', + }, }, refine: (value, ctx, attributeNode) => { const diagnostics = []; @@ -779,6 +783,7 @@ type PostgresFullTextIndexParsed = { readonly language?: FullTextSearchLanguage; readonly name?: string; readonly map?: string; + readonly where?: string; }; /** @@ -829,7 +834,7 @@ export const postgresAuthoringModelAttributes = { ), type: 'gin', options: undefined, - where: undefined, + where: parsed.where, unique: undefined, name: parsed.name, map: parsed.map, diff --git a/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts b/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts index b9c055d2aa29..547ee9dcad7a 100644 --- a/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts +++ b/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts @@ -150,7 +150,7 @@ model Message { ); expect(typed).toEqual(authored); - expect(typed[0]).toMatchObject({ where: 'id > 0', partial: true }); + expect(typed[0]).toMatchObject({ where: 'id > 0' }); }); it('rejects a language Postgres does not ship, naming the ones it does', () => { From c74e3a492448b4b6bf5aa85cd50003b548ea92ef Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 15:26:22 +0200 Subject: [PATCH 30/36] test(integration): name the storage column in the partial-index predicate The SQL builder addresses columns, so the second clause is `f.post_id`. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- test/integration/test/sql-builder/full-text-index-usage.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/test/sql-builder/full-text-index-usage.test.ts b/test/integration/test/sql-builder/full-text-index-usage.test.ts index 6020158cce54..11f7cddf5426 100644 --- a/test/integration/test/sql-builder/full-text-index-usage.test.ts +++ b/test/integration/test/sql-builder/full-text-index-usage.test.ts @@ -230,7 +230,7 @@ describe('full-text index usage', { timeout: timeouts.databaseOperation }, () => db() .public.comments.select('id') .where((f, fns) => fns.fullTextMatches(f.body, QUERY)) - .where((f, fns) => fns.eq(f.postId, 1)) + .where((f, fns) => fns.eq(f.post_id, 1)) .build(), ); From 4c0cdcd1c8f54c4893c1b72130e2883ec5e6706f Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 15:27:09 +0200 Subject: [PATCH 31/36] docs(postgres): document the operation options and the partial index Each reference gains the options object with one example: rank normalization and cover density, the ts_headline markers and word counts, and `where:` on both authoring forms of the index. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- packages/3-targets/3-targets/postgres/README.md | 13 +++++++++++-- skills/prisma-8/references/contract.md | 3 ++- skills/prisma-8/references/queries-postgres.md | 9 ++++++--- .../postgres-full-text-search/app/instructions.md | 14 +++++++++++++- 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/packages/3-targets/3-targets/postgres/README.md b/packages/3-targets/3-targets/postgres/README.md index 2c60cf5d4ed7..2dc3aff1a64a 100644 --- a/packages/3-targets/3-targets/postgres/README.md +++ b/packages/3-targets/3-targets/postgres/README.md @@ -119,7 +119,16 @@ Pack refs are pure JSON-friendly objects that make TypeScript contract authoring This package contributes the built-in Postgres query operations — `ilike`, and the three full-text search operations below — through `queryOperations` on its runtime descriptor, with their types on `./operation-types`. Emitted `contract.d.ts` files import them from there. -`fullTextMatches` is a predicate, `fullTextRank` scores a row for ordering, and `fullTextHeadline` returns the matched text with `` around the matching words. All three take the search string as a bound parameter and lower to `websearch_to_tsquery`, so a user can type `"an exact phrase"` and `-excluded` and get what those mean in a search box. Each takes an optional second argument naming the text-search configuration, which defaults to `english`; only the configurations a stock PostgreSQL server ships with are accepted, because the name is written into the SQL as an inline literal. +`fullTextMatches` is a predicate, `fullTextRank` scores a row for ordering, and `fullTextHeadline` returns the matched text with `` around the matching words. All three take the search string as a bound parameter and lower to `websearch_to_tsquery`, so a user can type `"an exact phrase"` and `-excluded` and get what those mean in a search box. + +Each takes an options object as its second argument. `language` is common to all three and defaults to `english`; `fullTextRank` adds `normalization` (the `ts_rank` bitmask, 0 to 63) and `coverDensity` (which selects `ts_rank_cd`); `fullTextHeadline` adds `startSel`, `stopSel`, `maxWords`, `minWords` and `highlightAll`, which become `ts_headline`'s fourth argument: + +```typescript +row.text.fullTextRank(query, { language: 'german', normalization: 32, coverDensity: true }); +row.text.fullTextHeadline(query, { startSel: '', stopSel: '', maxWords: 20 }); +``` + +Postgres takes no parameter in any of those positions, so every option is written into the SQL as a literal and is therefore checked first: an unknown configuration, a normalization outside 0 to 63, a word count that is not a positive integer, a `minWords` above `maxWords`, or a marker carrying `ts_headline`'s own `"` `,` `=` delimiters all raise `RUNTIME.ARGUMENT_INVALID` before a statement is built. Through the ORM: @@ -155,7 +164,7 @@ model('Message', { fields: { id, text } }).sql(({ cols }) => ({ })); ``` -It takes exactly one field, an optional `language` (default `english`, from the same allowlist the operations accept), and `name:` xor `map:` like any expression index; it is repeatable, so a model may index several columns. Pass the same `language` here and to the operation: a mismatch is not an error, the query just stops using the index and falls back to a sequential scan. The column name comes from the resolved storage column, so `@map` is honoured. `@@index(expression: "to_tsvector('english', \"text\")", type: "gin", name: …)` still works for anything the attribute does not cover — but then the expression is yours to keep in step. +It takes exactly one field, an optional `language` (default `english`, from the same allowlist the operations accept), an optional `where:` for a partial index, and `name:` xor `map:` like any expression index; it is repeatable, so a model may index several columns. Pass the same `language` here and to the operation: a mismatch is not an error, the query just stops using the index and falls back to a sequential scan. The column name comes from the resolved storage column, so `@map` is honoured. `@@index(expression: "to_tsvector('english', \"text\")", type: "gin", name: …)` still works for anything the attribute does not cover — but then the expression is yours to keep in step. ## Codec descriptor authoring diff --git a/skills/prisma-8/references/contract.md b/skills/prisma-8/references/contract.md index 0d5991a24746..0067beba5a96 100644 --- a/skills/prisma-8/references/contract.md +++ b/skills/prisma-8/references/contract.md @@ -131,9 +131,10 @@ Then run `pnpm prisma contract emit` (or rely on the Vite plugin — see `refere ```prisma @@fullTextIndex([text], name: "message_text_search") @@fullTextIndex([summary], language: "german", name: "message_summary_search_de") +@@fullTextIndex([text], where: "archived_at IS NULL", name: "message_text_search_live") ``` -The TS builder has the same helper: `fullTextIndex(cols.text, { name: 'message_text_search' })`, from `@prisma/orm-postgres/contract-builder`, inside the model's `sql({ indexes: [...] })`. It takes exactly one field, an optional `language` (default `english`, from the same allowlist the operations accept), and `name:` xor `map:` like any expression index. It is repeatable, so a model may index several columns. Give the index and the operation the same `language` — a mismatch is silent, costing the index and falling back to a sequential scan. It lowers to a GIN index over `to_tsvector('', "")` — the column name resolved through `@map` — so `@@index(expression: …)` remains only for expressions this attribute does not cover. +The TS builder has the same helper: `fullTextIndex(cols.text, { name: 'message_text_search' })`, from `@prisma/orm-postgres/contract-builder`, inside the model's `sql({ indexes: [...] })`. It takes exactly one field, an optional `language` (default `english`, from the same allowlist the operations accept), an optional `where:` for a partial index, and `name:` xor `map:` like any expression index. It is repeatable, so a model may index several columns. Give the index and the operation the same `language` — a mismatch is silent, costing the index and falling back to a sequential scan. It lowers to a GIN index over `to_tsvector('', "")` — the column name resolved through `@map` — so `@@index(expression: …)` remains only for expressions this attribute does not cover. PSL alias surface for repeated types lives in a top-level `types {}` block: diff --git a/skills/prisma-8/references/queries-postgres.md b/skills/prisma-8/references/queries-postgres.md index 2e8886959c70..da2a263bf769 100644 --- a/skills/prisma-8/references/queries-postgres.md +++ b/skills/prisma-8/references/queries-postgres.md @@ -62,7 +62,7 @@ db.orm.public.User.where({ kind: 'admin' }); Operators on the field proxy include `.eq`, `.neq`, `.lt`, `.lte`, `.gt`, `.gte`, `.like`, `.ilike`, `.in([...])`, `.isNull()`, `.isNotNull()`. Extensions add target-specific operators on extension-typed columns (`pgvector`'s `.cosineDistance(...)`, `postgis`'s `.within(...)` / `.intersectsBbox(...)` / `.distanceSphere(...)`). -**Full-text search** is built into the Postgres target, on any text column: `.fullTextMatches(q)` is the predicate, `.fullTextRank(q)` scores a row so you can order by relevance, and `.fullTextHeadline(q)` returns the text with `` around the matches. The search string is a bound parameter lowered to `websearch_to_tsquery`, so `"an exact phrase"` and `-excluded` work the way a user expects from a search box. Each takes an optional second argument naming the text-search configuration; it defaults to `'english'` and only accepts the configurations a stock PostgreSQL server ships with (`'simple'`, `'german'`, `'french'`, … — anything else throws `RUNTIME.ARGUMENT_INVALID` when the query is built). +**Full-text search** is built into the Postgres target, on any text column: `.fullTextMatches(q)` is the predicate, `.fullTextRank(q)` scores a row so you can order by relevance, and `.fullTextHeadline(q)` returns the text with `` around the matches. The search string is a bound parameter lowered to `websearch_to_tsquery`, so `"an exact phrase"` and `-excluded` work the way a user expects from a search box. Each takes an options object as its second argument. `language` defaults to `'english'` and only accepts the configurations a stock PostgreSQL server ships with (`'simple'`, `'german'`, `'french'`, …); `fullTextRank` also takes `normalization` (the `ts_rank` bitmask, 0 to 63) and `coverDensity` (for `ts_rank_cd`); `fullTextHeadline` also takes `startSel`, `stopSel`, `maxWords`, `minWords` and `highlightAll`. Every one of them is written into the SQL as a literal, so anything invalid throws `RUNTIME.ARGUMENT_INVALID` when the query is built. ```typescript // ORM: filter by the query, order by relevance. @@ -73,10 +73,12 @@ const hits = await db.orm.public.Message .limit(20) .all(); -// SQL builder: the same predicate, plus a highlighted snippet. +// SQL builder: the same predicate, plus a snippet with your own markers. const snippets = db.sql.public.message .select('id') - .select('snippet', (f, fns) => fns.fullTextHeadline(f.text, query)) + .select('snippet', (f, fns) => + fns.fullTextHeadline(f.text, query, { startSel: '', stopSel: '', maxWords: 20 }), + ) .where((f, fns) => fns.fullTextMatches(f.text, query)) .build(); ``` @@ -85,6 +87,7 @@ Without an index Postgres recomputes `to_tsvector` for every row, and it only us ```prisma @@fullTextIndex([text], name: "message_text_search") +@@fullTextIndex([text], where: "archived_at IS NULL", name: "message_text_search_live") ``` Give the index and the operation the same `language`: a mismatch raises no error, the query silently falls back to a sequential scan. diff --git a/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md b/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md index 71b3bd83697e..c498812f703f 100644 --- a/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md +++ b/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md @@ -46,8 +46,20 @@ In a TypeScript contract, use the matching helper inside the model's `sql({ inde import { fullTextIndex } from '@prisma/orm-postgres/contract-builder'; model('Message', { fields: { id, text } }).sql(({ cols }) => ({ - indexes: [fullTextIndex(cols.text, { name: 'message_text_search' })], + indexes: [ + fullTextIndex(cols.text, { name: 'message_text_search' }), + fullTextIndex(cols.text, { where: 'archived_at IS NULL', name: 'message_text_search_live' }), + ], })); ``` +The operations themselves take an options object as their second argument — `language` for all three, plus `normalization` and `coverDensity` on `fullTextRank` and the `ts_headline` options (`startSel`, `stopSel`, `maxWords`, `minWords`, `highlightAll`) on `fullTextHeadline`: + +```ts +await db.orm.public.Message.select('id', 'text') + .where((m) => m.text.fullTextMatches(query)) + .orderBy((m) => m.text.fullTextRank(query, { normalization: 32 }).desc()) + .all(); +``` + Postgres only uses a full-text index whose expression is the same `to_tsvector` over the same configuration literal and the same column as the query, so prefer these over writing `@@index(expression: "to_tsvector(…)", type: "gin", …)` by hand. Pass the same `language` to the index and to the operation: a mismatch is silent, and the query falls back to a sequential scan. From 535dff2fef9f4b3059523a7d32d011f1b2e2e3b2 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 15:53:09 +0200 Subject: [PATCH 32/36] test(integration): build the partial index from the contract, like every other positive case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review rework. The partial-index case hand-wrote its `CREATE INDEX`, so it proved a fact about Postgres rather than one about this PR — it would have passed with the expression renderer or the `where` passthrough broken. The fixture now authors `fullTextIndex(cols.body, { where, name })`, `createIndexFromContract` carries `where` into the call, and a second DDL test pins the rendered `WHERE` clause. Physical names come from the contract now rather than being repeated as literals. `full-text-options.ts` loses its orphaned doc block, which sat a blank line above the first interface and documented nothing; it becomes a real file header above the imports, and the file's prose reflows at the formatter width. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../postgres/src/core/full-text-options.ts | 19 +++-- .../test/sql-builder/fixtures/contract.ts | 3 + .../fixtures/generated/contract.d.ts | 10 ++- .../fixtures/generated/contract.json | 10 ++- .../sql-builder/full-text-index-usage.test.ts | 71 +++++++++++-------- 5 files changed, 72 insertions(+), 41 deletions(-) diff --git a/packages/3-targets/3-targets/postgres/src/core/full-text-options.ts b/packages/3-targets/3-targets/postgres/src/core/full-text-options.ts index df339588f42c..7a6a4576abc7 100644 --- a/packages/3-targets/3-targets/postgres/src/core/full-text-options.ts +++ b/packages/3-targets/3-targets/postgres/src/core/full-text-options.ts @@ -1,3 +1,10 @@ +/** + * Options for the Postgres full-text operations, and the checks each one goes through. + * + * Every option here reaches the SQL as an inline literal rather than a bound parameter, because + * Postgres accepts no parameter in these positions. Each is therefore validated before a statement + * exists; anything unrecognized throws `RUNTIME.ARGUMENT_INVALID`. + */ import { LiteralExpr } from '@internal/sql-relational-core/ast'; import { postgresError } from './errors'; import { @@ -6,13 +13,6 @@ import { POSTGRES_TEXT_SEARCH_LANGUAGES, } from './text-search-languages'; -/** - * Every option below reaches the SQL as an inline literal rather than a bound - * parameter, because Postgres accepts no parameter in these positions. Each is - * therefore checked here first; anything unrecognized throws - * `RUNTIME.ARGUMENT_INVALID` before a statement exists. - */ - export interface FullTextMatchesOptions { /** Text-search configuration. Defaults to `english`. */ readonly language?: FullTextSearchLanguage; @@ -97,9 +97,8 @@ function checkMarker(method: string, argument: string, value: string): void { } /** - * The fourth `ts_headline` argument: one text literal of `Key=Value` pairs. - * Returns `undefined` when nothing but the language was given, so the common - * call keeps rendering the three-argument form. + * The fourth `ts_headline` argument: one text literal of `Key=Value` pairs. Returns `undefined` when + * nothing but the language was given, so the common call keeps rendering the three-argument form. */ export function headlineOptionsLiteral( method: string, diff --git a/test/integration/test/sql-builder/fixtures/contract.ts b/test/integration/test/sql-builder/fixtures/contract.ts index 5234f1eb69a5..283706ad2fed 100644 --- a/test/integration/test/sql-builder/fixtures/contract.ts +++ b/test/integration/test/sql-builder/fixtures/contract.ts @@ -48,6 +48,9 @@ const Comment = model('Comment', { indexes: [ fullTextIndex(cols.body, { name: 'comments_body_search' }), fullTextIndex(cols.subject, { name: 'comments_subject_search' }), + // Partial: the index-usage test proves Postgres picks this one up for a + // query that carries the same predicate. + fullTextIndex(cols.body, { where: 'post_id = 1', name: 'comments_body_live' }), ], })); diff --git a/test/integration/test/sql-builder/fixtures/generated/contract.d.ts b/test/integration/test/sql-builder/fixtures/generated/contract.d.ts index 2290eaf040eb..a9e3d4a9e99c 100644 --- a/test/integration/test/sql-builder/fixtures/generated/contract.d.ts +++ b/test/integration/test/sql-builder/fixtures/generated/contract.d.ts @@ -36,7 +36,7 @@ import type { } from '@internal/contract/types'; export type StorageHash = - StorageHashBase<'b5bc225c3a57bcc7d0700cbbb16d41db99559a617569122f86e21350fa477a1b'>; + StorageHashBase<'4e3e7b1a2e6aed06486b55d35bf1fe4b435c2c16ce1a0de8ba7ffc82157b6b64'>; export type ExecutionHash = ExecutionHashBase<'566d74b60e6b5393dcdbf9f250120fa4e1f12c0ae51e1c0958a131d8ed9667b5'>; export type ProfileHash = @@ -490,6 +490,14 @@ type ContractBase = Omit< primaryKey: { readonly columns: readonly ['id'] }; uniques: readonly []; indexes: readonly [ + { + readonly name: 'comments_body_live_a3f98ae2'; + readonly prefix: 'comments_body_live'; + readonly expression: 'to_tsvector(\'english\', "body")'; + readonly where: 'post_id = 1'; + readonly unique: false; + readonly type: 'gin'; + }, { readonly name: 'comments_body_search_7b2cde4d'; readonly prefix: 'comments_body_search'; diff --git a/test/integration/test/sql-builder/fixtures/generated/contract.json b/test/integration/test/sql-builder/fixtures/generated/contract.json index 77e2574b0710..37e718eecf90 100644 --- a/test/integration/test/sql-builder/fixtures/generated/contract.json +++ b/test/integration/test/sql-builder/fixtures/generated/contract.json @@ -430,6 +430,14 @@ }, "foreignKeys": [], "indexes": [ + { + "expression": "to_tsvector('english', \"body\")", + "name": "comments_body_live_a3f98ae2", + "prefix": "comments_body_live", + "type": "gin", + "unique": false, + "where": "post_id = 1" + }, { "expression": "to_tsvector('english', \"body\")", "name": "comments_body_search_7b2cde4d", @@ -557,7 +565,7 @@ "kind": "postgres-schema" } }, - "storageHash": "b5bc225c3a57bcc7d0700cbbb16d41db99559a617569122f86e21350fa477a1b" + "storageHash": "4e3e7b1a2e6aed06486b55d35bf1fe4b435c2c16ce1a0de8ba7ffc82157b6b64" }, "execution": { "executionHash": "566d74b60e6b5393dcdbf9f250120fa4e1f12c0ae51e1c0958a131d8ed9667b5", diff --git a/test/integration/test/sql-builder/full-text-index-usage.test.ts b/test/integration/test/sql-builder/full-text-index-usage.test.ts index 11f7cddf5426..d8dd19865b49 100644 --- a/test/integration/test/sql-builder/full-text-index-usage.test.ts +++ b/test/integration/test/sql-builder/full-text-index-usage.test.ts @@ -3,8 +3,9 @@ * emits, for the SQL our lanes lower? Prisma 7 built such an index and the * planner never chose it, so nothing here is assumed: * - * - the index is created from the DDL our own op factory and adapter render - * for the fixture contract's index node, never hand-written; + * - every index a positive case relies on is created from the DDL our own op + * factory and adapter render for the fixture contract's index node, the + * partial one included, never hand-written; * - the queries are the real lowered SQL and bound params of the SQL builder * and the ORM; * - `EXPLAIN (FORMAT JSON)` on exactly that SQL has to name the index; @@ -60,19 +61,27 @@ describe('full-text index usage', { timeout: timeouts.databaseOperation }, () => return namespace.table['comments']!.indexes; } - async function createIndexFromContract(index: Record) { - const call = new CreateIndexCall( + function createIndexCallFor(index: Record): CreateIndexCall { + const where = index['where']; + return new CreateIndexCall( 'public', 'comments', String(index['name']), { expression: String(index['expression']) }, - { type: String(index['type']) }, + { type: String(index['type']), ...(where === undefined ? {} : { where: String(where) }) }, ); - const op = await call.toOp(controlAdapter); + } + + async function createIndexFromContract(index: Record) { + const op = await createIndexCallFor(index).toOp(controlAdapter); for (const step of op.execute) { await client().query(step.sql); } - return op.execute[0]!.sql; + } + + /** The physical name the fixture's index carries, wire hash included. */ + function indexNamed(prefix: string): string { + return String(fixtureIndex(prefix)['name']); } /** `lowerSqlPlan` already unwrapped the renderer's slots to bare bound values. */ @@ -106,21 +115,28 @@ describe('full-text index usage', { timeout: timeouts.databaseOperation }, () => await client().query('SET enable_seqscan = off'); }, timeouts.spinUpPpgDev); + /** The index node the fixture's `fullTextIndex(...)` emitted under this prefix. */ + function fixtureIndex(prefix: string): Record { + const index = fixtureIndexes().find((candidate) => candidate['prefix'] === prefix); + if (index === undefined) throw new Error(`fixture index ${prefix} is missing`); + return index; + } + + async function renderCreateIndex(prefix: string): Promise { + const op = await createIndexCallFor(fixtureIndex(prefix)).toOp(controlAdapter); + const [step] = op.execute; + return step?.sql ?? ''; + } + it('creates the index from the DDL our own op factory and adapter render', async () => { - const [bodyIndex] = fixtureIndexes(); - expect(bodyIndex).toBeDefined(); - if (bodyIndex === undefined) return; - const call = new CreateIndexCall( - 'public', - 'comments', - String(bodyIndex['name']), - { expression: String(bodyIndex['expression']) }, - { type: String(bodyIndex['type']) }, + expect(await renderCreateIndex('comments_body_search')).toBe( + `CREATE INDEX "comments_body_search_7b2cde4d" ON "public"."comments" USING "gin" (to_tsvector('english', "body"))`, ); - const op = await call.toOp(controlAdapter); + }); - expect(op.execute[0]?.sql).toBe( - `CREATE INDEX "comments_body_search_7b2cde4d" ON "public"."comments" USING "gin" (to_tsvector('english', "body"))`, + it('renders the WHERE clause for a partial index the attribute emitted', async () => { + expect(await renderCreateIndex('comments_body_live')).toBe( + `CREATE INDEX "comments_body_live_a3f98ae2" ON "public"."comments" USING "gin" (to_tsvector('english', "body")) WHERE (post_id = 1)`, ); }); @@ -149,7 +165,7 @@ describe('full-text index usage', { timeout: timeouts.databaseOperation }, () => ); const plan = await explain(lowered.sql, lowered.params); - expect(indexNames(plan)).toContain('comments_body_search_7b2cde4d'); + expect(indexNames(plan)).toContain(indexNamed('comments_body_search')); }); it('uses the index when the same predicate is ordered by rank and limited', async () => { @@ -163,7 +179,7 @@ describe('full-text index usage', { timeout: timeouts.databaseOperation }, () => ); const plan = await explain(lowered.sql, lowered.params); - expect(indexNames(plan)).toContain('comments_body_search_7b2cde4d'); + expect(indexNames(plan)).toContain(indexNamed('comments_body_search')); }); it('uses the index for the ORM predicate ordered by rank', async () => { @@ -196,7 +212,7 @@ describe('full-text index usage', { timeout: timeouts.databaseOperation }, () => expect(lowered.sql).toContain(`to_tsvector('english', "comments"."body")`); const explained = await explain(lowered.sql, lowered.params); - expect(indexNames(explained)).toContain('comments_body_search_7b2cde4d'); + expect(indexNames(explained)).toContain(indexNamed('comments_body_search')); }); it('matches the index on a varchar column too', async () => { @@ -208,7 +224,7 @@ describe('full-text index usage', { timeout: timeouts.databaseOperation }, () => ); const plan = await explain(lowered.sql, lowered.params); - expect(indexNames(plan)).toContain('comments_subject_search_2b3d17a7'); + expect(indexNames(plan)).toContain(indexNamed('comments_subject_search')); }); it('stores the varchar index with the cast Postgres adds, and matches it anyway', async () => { @@ -222,10 +238,7 @@ describe('full-text index usage', { timeout: timeouts.databaseOperation }, () => expect(definition.rows[0].def).toContain('(subject)::text'); }); - it('uses a partial index for a query carrying the same predicate', async () => { - await client().query( - `CREATE INDEX comments_body_live ON comments USING gin (to_tsvector('english', "body")) WHERE (post_id = 1)`, - ); + it('uses the partial index @@fullTextIndex(where:) emits for a query carrying that predicate', async () => { const lowered = loweredOf( db() .public.comments.select('id') @@ -235,7 +248,7 @@ describe('full-text index usage', { timeout: timeouts.databaseOperation }, () => ); const plan = await explain(lowered.sql, lowered.params); - expect(indexNames(plan)).toContain('comments_body_live'); + expect(indexNames(plan)).toContain(indexNamed('comments_body_live')); }); describe('negative controls', () => { @@ -248,7 +261,7 @@ describe('full-text index usage', { timeout: timeouts.databaseOperation }, () => ); const plan = await explain(lowered.sql, lowered.params); - expect(indexNames(plan)).not.toContain('comments_body_search_7b2cde4d'); + expect(indexNames(plan)).not.toContain(indexNamed('comments_body_search')); expect(nodeTypes(plan)).toContain('Seq Scan'); }); From 1de810f1d8223a69495d0852124001971993ca83 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 17:00:20 +0200 Subject: [PATCH 33/36] docs(adr): renumber the target-owned query operations ADR to 255 Main landed its own 253 while this branch was open, and orm#30350 is already committed to 254 for "Data types and casts", so 255 is the first number no open work claims. A gap costs nothing; a second collision would cost whichever PR merges last. The heading, the index row and the pointers in ADRs 203, 206 and 236 move with the file. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/architecture docs/ADR-INDEX.md | 2 +- .../adrs/ADR 203 - Trait-targeted operation arguments.md | 2 +- .../adrs/ADR 206 - Operations as TypeScript functions.md | 2 +- .../adrs/ADR 236 - Target-contributed model attributes.md | 2 +- ...s.md => ADR 255 - Target-owned built-in query operations.md} | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) rename docs/architecture docs/adrs/{ADR 254 - Target-owned built-in query operations.md => ADR 255 - Target-owned built-in query operations.md} (99%) diff --git a/docs/architecture docs/ADR-INDEX.md b/docs/architecture docs/ADR-INDEX.md index be86a1e54ec3..dde083464b90 100644 --- a/docs/architecture docs/ADR-INDEX.md +++ b/docs/architecture docs/ADR-INDEX.md @@ -79,7 +79,7 @@ This document provides a comprehensive index of all Architectural Decision Recor | 210 | Prepared Statements: Author Surface and Driver SPI | Adds `runtime.prepare(declaration, callback)` (re-exposed on each DB facade as `db.prepare(...)`) and prepared execution through the existing `query()` driver SPI; lazy driver-allocated opaque handle, no global cache, cache lifetime bounded by user reference and connection. Family-level: per-driver caching strategies are out of scope here. | [ADR 210 - Prepared Statements - Author Surface and Driver SPI.md](adrs/ADR%20210%20-%20Prepared%20Statements%20-%20Author%20Surface%20and%20Driver%20SPI.md) | | 215 | Runtime middleware lifecycle: `beforeExecute` fires before `encodeParams` | Reorders the SQL family runtime so `beforeExecute` fires between `lowerToDraft` and `encodeDraftParams`, with a pre-encode `paramsMutator` over user-domain values. Extracts `runBeforeExecuteChain` from `runWithMiddleware`; `intercept` always observes a post-`beforeExecute` plan. SPI shape unchanged. | [ADR 215 - Runtime middleware lifecycle beforeExecute before encodeParams.md](adrs/ADR%20215%20-%20Runtime%20middleware%20lifecycle%20beforeExecute%20before%20encodeParams.md) | | 220 | Plan execution identity for middleware correlation | Adds `planExecutionId: string` to `RuntimeMiddlewareContext`, minted by the runtime via `crypto.randomUUID()` at the start of every runtime operation (`query`, prepared statement `query`, or `execute`). Per-operation identity (not per-plan), shared across all hooks within one operation, distinct across two operations of the same plan. Lives on the per-operation context, not on `PlanMeta`. Distinct from ADR 013's content-based `planId` and ADR 160's `groupingKey`. | [ADR 220 - Plan execution identity for middleware correlation.md](adrs/ADR%20220%20-%20Plan%20execution%20identity%20for%20middleware%20correlation.md) | -| 254 | Target-owned built-in query operations | Moves a target's built-in query operations out of its adapter and into the target pack; Postgres gains `fullTextMatches`, `fullTextRank` and `fullTextHeadline` over `websearch_to_tsquery` with an allowlisted language literal | [ADR 254 - Target-owned built-in query operations.md](adrs/ADR%20254%20-%20Target-owned%20built-in%20query%20operations.md) | +| 255 | Target-owned built-in query operations | Moves a target's built-in query operations out of its adapter and into the target pack; Postgres gains `fullTextMatches`, `fullTextRank` and `fullTextHeadline` over `websearch_to_tsquery` with an allowlisted language literal | [ADR 255 - Target-owned built-in query operations.md](adrs/ADR%20255%20-%20Target-owned%20built-in%20query%20operations.md) | ## Migration System diff --git a/docs/architecture docs/adrs/ADR 203 - Trait-targeted operation arguments.md b/docs/architecture docs/adrs/ADR 203 - Trait-targeted operation arguments.md index 02ee11600cbb..1cd8e7f2cdd3 100644 --- a/docs/architecture docs/adrs/ADR 203 - Trait-targeted operation arguments.md +++ b/docs/architecture docs/adrs/ADR 203 - Trait-targeted operation arguments.md @@ -2,7 +2,7 @@ ## Context -Adapters and extensions register query operations (e.g., `ilike`, `cosineDistance`) that attach to fields of a given shape. (Since [ADR 254](ADR%20254%20-%20Target-owned%20built-in%20query%20operations.md), a target registers its built-in operations too — `ilike` is contributed by the Postgres target, not its adapter.) Until now an operation declared its `self` argument as a specific `codecId` — `pgvector/vector@1` for `cosineDistance`, for example. The type and runtime machinery then surfaced that operation on every field whose codec matched that ID. +Adapters and extensions register query operations (e.g., `ilike`, `cosineDistance`) that attach to fields of a given shape. (Since [ADR 255](ADR%20255%20-%20Target-owned%20built-in%20query%20operations.md), a target registers its built-in operations too — `ilike` is contributed by the Postgres target, not its adapter.) Until now an operation declared its `self` argument as a specific `codecId` — `pgvector/vector@1` for `cosineDistance`, for example. The type and runtime machinery then surfaced that operation on every field whose codec matched that ID. Codec-ID targeting works when an operation is tied to one concrete codec. It breaks down when an operation is defined by a *capability* that multiple codecs share: diff --git a/docs/architecture docs/adrs/ADR 206 - Operations as TypeScript functions.md b/docs/architecture docs/adrs/ADR 206 - Operations as TypeScript functions.md index 4f0f1ce7ace8..90325d7ee8e9 100644 --- a/docs/architecture docs/adrs/ADR 206 - Operations as TypeScript functions.md +++ b/docs/architecture docs/adrs/ADR 206 - Operations as TypeScript functions.md @@ -37,7 +37,7 @@ The distinction between predicate operations (return a boolean, composable insid ## Interaction with other subsystems - **Operation arguments.** [ADR 203](ADR%20203%20-%20Trait-targeted%20operation%20arguments.md) introduced codec-identity and trait-set targeting for argument specs. The primitive survives — the self hint uses the same vocabulary — but it now applies only to the ORM column-helper dispatch. The SQL builder no longer reads argument specs; it calls the authored function directly. -- **Adapter SPI.** [ADR 016](ADR%20016%20-%20Adapter%20SPI%20for%20Lowering.md) described how adapters contribute lowering. The adapter runtime descriptor's `queryOperations` slot now yields a factory rather than a const array. The contract-assembly layer calls the factory with the contract's codec-types map. [ADR 254](ADR%20254%20-%20Target-owned%20built-in%20query%20operations.md) then moved a target's built-in operations off the adapter and onto the target descriptor's identical slot. +- **Adapter SPI.** [ADR 016](ADR%20016%20-%20Adapter%20SPI%20for%20Lowering.md) described how adapters contribute lowering. The adapter runtime descriptor's `queryOperations` slot now yields a factory rather than a const array. The contract-assembly layer calls the factory with the contract's codec-types map. [ADR 255](ADR%20255%20-%20Target-owned%20built-in%20query%20operations.md) then moved a target's built-in operations off the adapter and onto the target descriptor's identical slot. - **Codec registry.** [ADR 030](ADR%20030%20-%20Result%20decoding%20%26%20codecs%20registry.md) defines codec metadata including traits. The ORM column helper continues to read traits from the registry to expand trait-targeted self hints. Codec-types flow from the same registry into the contract and onward into each operation factory. - **Extension compatibility.** [ADR 017](ADR%20017%20-%20Extension%20Compatibility%20Policy.md) is honoured: old declarative operation records are not retained, so the decision is a breaking change for extensions that ship their own operation contributions. The breakage is local — each extension rewrites its operation contribution at the factory boundary, without changes elsewhere in the authoring surface. diff --git a/docs/architecture docs/adrs/ADR 236 - Target-contributed model attributes.md b/docs/architecture docs/adrs/ADR 236 - Target-contributed model attributes.md index c344e62f78f4..e8bbc11d8a91 100644 --- a/docs/architecture docs/adrs/ADR 236 - Target-contributed model attributes.md +++ b/docs/architecture docs/adrs/ADR 236 - Target-contributed model attributes.md @@ -72,7 +72,7 @@ A registry of `AuthoringModelAttributeDescriptor`s. Each descriptor: - **claims a bare `@@` attribute name** (`attribute: 'rls'`); - **supplies a factory for the declarative parameter spec** — a `ModelAttributeSpecFactory`, called with the declaring model's context and returning a spec built with the same `modelAttribute(...)` constructors as every other declarative attribute ([ADR 231](ADR%20231%20-%20Declarative%20attribute%20specifications.md)) — so parsing, validation, and printing come for free from the generic machinery. A spec that needs nothing from the context, like `@@rls`, returns a hoisted module constant so its identity is stable across calls; -- **supplies a `lower` function** that turns the parsed attribute into a pack entity keyed into the namespace's `entries`. Since [ADR 254](ADR%20254%20-%20Target-owned%20built-in%20query%20operations.md) a lowering may instead return `{ index }`, which the family interpreter files onto the declaring model's table through the same path `@@index` uses — the Postgres `@@fullTextIndex` attribute is the first to do so. +- **supplies a `lower` function** that turns the parsed attribute into a pack entity keyed into the namespace's `entries`. Since [ADR 255](ADR%20255%20-%20Target-owned%20built-in%20query%20operations.md) a lowering may instead return `{ index }`, which the family interpreter files onto the declaring model's table through the same path `@@index` uses — the Postgres `@@fullTextIndex` attribute is the first to do so. The factory indirection is uniform across every registered attribute spec, so one entry shape serves both this channel and the family built-ins that share the registry. diff --git a/docs/architecture docs/adrs/ADR 254 - Target-owned built-in query operations.md b/docs/architecture docs/adrs/ADR 255 - Target-owned built-in query operations.md similarity index 99% rename from docs/architecture docs/adrs/ADR 254 - Target-owned built-in query operations.md rename to docs/architecture docs/adrs/ADR 255 - Target-owned built-in query operations.md index 2f10bc9b1282..fec183223e38 100644 --- a/docs/architecture docs/adrs/ADR 254 - Target-owned built-in query operations.md +++ b/docs/architecture docs/adrs/ADR 255 - Target-owned built-in query operations.md @@ -1,4 +1,4 @@ -# ADR 254 — Target-owned built-in query operations +# ADR 255 — Target-owned built-in query operations **Status:** Accepted From 22c70c0df88fe93d041ca4956ccda6aa1c29ce59 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 21 Sep 2026 18:24:49 +0200 Subject: [PATCH 34/36] fix(postgres): tighten what the full-text options and @@fullTextIndex accept MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Six findings from a fresh-eyes review. Postgres wants MinWords strictly below MaxWords, so equal values are refused now rather than reaching the server; markers are stated positively as non-empty and free of `"` `,` `=` `\\` and whitespace, which is also what keeps quotes and backslashes off the literal path; and `highlightAll` is checked for a boolean like every sibling instead of being interpolated unread. `@@fullTextIndex` refuses a field that is not stored through a textual codec, naming the field and its codec — a relation field or an `Int` was silently accepted before and produced an index Postgres would reject. The check reads the codec descriptors the `textual` operations already dispatch on rather than a second list of ids, so the two cannot drift. It needs the field's codec, which the lowering context now exposes as `fieldCodecId` beside `fieldStorageName`. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../src/shared/framework-authoring.ts | 7 +++ .../contract-psl/src/interpreter.ts | 2 + .../3-targets/postgres/src/core/authoring.ts | 39 +++++++++++--- .../postgres/src/core/full-text-options.ts | 30 ++++++++--- .../postgres/test/psl-full-text-index.test.ts | 54 +++++++++++++++++++ .../postgres/test/query-operations.test.ts | 24 +++++++-- .../sql-builder/full-text-index-usage.test.ts | 2 +- 7 files changed, 141 insertions(+), 17 deletions(-) diff --git a/packages/1-framework/1-core/framework-components/src/shared/framework-authoring.ts b/packages/1-framework/1-core/framework-components/src/shared/framework-authoring.ts index 50a313afa944..006441130332 100644 --- a/packages/1-framework/1-core/framework-components/src/shared/framework-authoring.ts +++ b/packages/1-framework/1-core/framework-components/src/shared/framework-authoring.ts @@ -481,6 +481,13 @@ export interface AuthoringModelAttributeContext extends AuthoringEntityContext { * rather than reusing the authored field name, which `@map` may rename. */ readonly fieldStorageName: (fieldName: string) => string | undefined; + /** + * The codec a field of the declaring model stores its values through, or + * `undefined` when the model declares no such field or the field is not a + * stored value at all. A lowering that only makes sense over certain value + * kinds checks this rather than guessing from the field's declared type. + */ + readonly fieldCodecId: (fieldName: string) => string | undefined; } /** diff --git a/packages/2-sql/2-authoring/contract-psl/src/interpreter.ts b/packages/2-sql/2-authoring/contract-psl/src/interpreter.ts index efd4ed1af07b..f5b24226c110 100644 --- a/packages/2-sql/2-authoring/contract-psl/src/interpreter.ts +++ b/packages/2-sql/2-authoring/contract-psl/src/interpreter.ts @@ -1171,6 +1171,8 @@ function buildModelNodeFromPsl(input: BuildModelNodeInput): BuildModelNodeResult modelName: model.name, storageName: tableName, fieldStorageName: (fieldName) => mapping.fieldColumns.get(fieldName), + fieldCodecId: (fieldName) => + resolvedFields.find((resolved) => resolved.field.name === fieldName)?.descriptor.codecId, namespaceId: modelNamespaceId ?? input.defaultNamespaceId, sourceId: source.sources.sourceFileFor(source.node).filename, diagnostics: { diff --git a/packages/3-targets/3-targets/postgres/src/core/authoring.ts b/packages/3-targets/3-targets/postgres/src/core/authoring.ts index ef6d9e06b3de..e9ff62e0ab2b 100644 --- a/packages/3-targets/3-targets/postgres/src/core/authoring.ts +++ b/packages/3-targets/3-targets/postgres/src/core/authoring.ts @@ -47,6 +47,7 @@ import { PG_TIMESTAMPTZ_STRING_CODEC_ID, PG_TIMESTAMPTZ_TEMPORAL_CODEC_ID, } from './codec-ids'; +import { codecDescriptors } from './codecs'; import { postgresError } from './errors'; import { renderFullTextIndexExpression } from './full-text-index-expression'; import { postgresNowGeneratorIds } from './now-generators'; @@ -80,6 +81,8 @@ const PSL_FULL_TEXT_INDEX_REQUIRES_NAME: ContributedPslDiagnosticCode = 'PSL_FULL_TEXT_INDEX_REQUIRES_NAME'; const PSL_FULL_TEXT_INDEX_NAME_XOR_MAP: ContributedPslDiagnosticCode = 'PSL_FULL_TEXT_INDEX_NAME_XOR_MAP'; +const PSL_FULL_TEXT_INDEX_TEXT_FIELD: ContributedPslDiagnosticCode = + 'PSL_FULL_TEXT_INDEX_TEXT_FIELD'; const PSL_NATIVE_ENUM_BARE_MEMBER: ContributedPslDiagnosticCode = 'PSL_NATIVE_ENUM_BARE_MEMBER'; const PSL_EXTENSION_INVALID_VALUE: ContributedPslDiagnosticCode = 'PSL_EXTENSION_INVALID_VALUE'; const PSL_NATIVE_ENUM_DUPLICATE_MEMBER_VALUE: ContributedPslDiagnosticCode = @@ -709,6 +712,25 @@ const postgresRlsSpecFactory: ModelAttributeSpecFactory = () => postgresRlsSpec; const [firstLanguage, ...remainingLanguages] = POSTGRES_TEXT_SEARCH_LANGUAGES; +/** + * Read from the codec descriptors themselves rather than a second list of ids, so the attribute + * accepts exactly the columns the `textual` operations dispatch on. + */ +/** Widens each descriptor's trait tuple, so membership is a plain string test. */ +function traitsOf(descriptor: { readonly traits: readonly string[] }): readonly string[] { + return descriptor.traits; +} + +const TEXTUAL_CODEC_IDS: ReadonlySet = new Set( + codecDescriptors + .filter((descriptor) => traitsOf(descriptor).includes('textual')) + .map((descriptor) => descriptor.codecId), +); + +function isTextualCodec(codecId: string): boolean { + return TEXTUAL_CODEC_IDS.has(codecId); +} + const postgresFullTextIndexSpec = modelAttribute('fullTextIndex', { documentation: 'Indexes one text column for full-text search, rendering the expression `fullTextMatches`, `fullTextRank` and `fullTextHeadline` lower to.', @@ -820,12 +842,17 @@ export const postgresAuthoringModelAttributes = { `@@fullTextIndex on "${ctx.modelName}" lowered with ${parsed.fields.length} fields`, ); const columnName = ctx.fieldStorageName(fieldName); - // `fieldRef()` resolves the name against the declaring model while - // parsing, so an unknown field is already a diagnostic by here. - invariant( - columnName !== undefined, - `@@fullTextIndex on "${ctx.modelName}" resolved no storage name for field "${fieldName}"`, - ); + const codecId = ctx.fieldCodecId(fieldName); + // A relation field parses as a field reference but stores no value, so it + // reaches here with neither a column nor a codec. + if (columnName === undefined || codecId === undefined || !isTextualCodec(codecId)) { + ctx.diagnostics?.push({ + code: PSL_FULL_TEXT_INDEX_TEXT_FIELD, + message: `\`@@fullTextIndex\` indexes a text column, but "${ctx.modelName}.${fieldName}" is ${codecId === undefined ? 'not a stored scalar field' : `stored as \`${codecId}\``}.`, + sourceId: ctx.sourceId ?? 'unknown', + }); + return undefined; + } return { index: { expression: renderFullTextIndexExpression( diff --git a/packages/3-targets/3-targets/postgres/src/core/full-text-options.ts b/packages/3-targets/3-targets/postgres/src/core/full-text-options.ts index 7a6a4576abc7..b65fc4e340b8 100644 --- a/packages/3-targets/3-targets/postgres/src/core/full-text-options.ts +++ b/packages/3-targets/3-targets/postgres/src/core/full-text-options.ts @@ -4,6 +4,10 @@ * Every option here reaches the SQL as an inline literal rather than a bound parameter, because * Postgres accepts no parameter in these positions. Each is therefore validated before a statement * exists; anything unrecognized throws `RUNTIME.ARGUMENT_INVALID`. + * + * The headline markers are the only free text among them, and `checkMarker` restricts their + * characters precisely so that the literal path never carries a quote or a backslash for + * `escapeLiteral` to have to reason about. */ import { LiteralExpr } from '@internal/sql-relational-core/ast'; import { postgresError } from './errors'; @@ -32,7 +36,7 @@ export interface FullTextHeadlineOptions extends FullTextMatchesOptions { readonly stopSel?: string; /** Longest headline, in words. */ readonly maxWords?: number; - /** Shortest headline, in words; at most `maxWords` when both are given. */ + /** Shortest headline, in words; below `maxWords` when both are given. */ readonly minWords?: number; /** Mark up the whole document rather than extracting fragments. */ readonly highlightAll?: boolean; @@ -84,14 +88,17 @@ function checkWordCount(method: string, argument: string, value: number): void { } } +/** Non-empty, and none of `"` `,` `=` `\` or whitespace. */ +const MARKER = /^[^"=,\\\s]+$/; + function checkMarker(method: string, argument: string, value: string): void { - if (value.length === 0 || /["=,]/.test(value)) { + if (!MARKER.test(value)) { throw invalid( method, argument, value, - `${argument} must be non-empty and free of " , and =, received ${JSON.stringify(value)}.`, - 'ts_headline parses its options as a quoted, comma-separated list of Key=Value pairs, so a marker carrying those characters cannot survive it. Use markup such as or .', + `${argument} must be non-empty and free of " , = \\ and whitespace, received ${JSON.stringify(value)}.`, + 'ts_headline parses its options as a quoted, comma-separated list of Key=Value pairs, and the whole list reaches SQL as one literal, so a marker carrying those characters cannot survive either step. Use markup such as or .', ); } } @@ -119,18 +126,27 @@ export function headlineOptionsLiteral( } if (options.minWords !== undefined) { checkWordCount(method, 'minWords', options.minWords); - if (options.maxWords !== undefined && options.minWords > options.maxWords) { + if (options.maxWords !== undefined && options.minWords >= options.maxWords) { throw invalid( method, 'minWords', options.minWords, - `minWords (${options.minWords}) cannot exceed maxWords (${options.maxWords}).`, - 'Lower minWords, or raise maxWords.', + `minWords (${options.minWords}) must be below maxWords (${options.maxWords}).`, + 'Postgres requires MinWords strictly below MaxWords. Lower minWords, or raise maxWords.', ); } pairs.push(`MinWords=${options.minWords}`); } if (options.highlightAll !== undefined) { + if (typeof options.highlightAll !== 'boolean') { + throw invalid( + method, + 'highlightAll', + options.highlightAll, + `highlightAll must be a boolean, received ${JSON.stringify(options.highlightAll)}.`, + 'Pass true to mark up the whole document, or false to extract fragments.', + ); + } pairs.push(`HighlightAll=${options.highlightAll}`); } return pairs.length === 0 ? undefined : LiteralExpr.of(pairs.join(', ')); diff --git a/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts b/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts index 7266ee6a1635..18077fde1335 100644 --- a/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts +++ b/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts @@ -13,6 +13,7 @@ import { postgresAuthoringEntityTypes, postgresAuthoringModelAttributes, postgresAuthoringPslBlockDescriptors, + postgresAuthoringTypes, } from '../src/core/authoring'; import { postgresIndexTypes } from '../src/core/index-types'; import { type PostgresSchema, postgresCreateNamespace } from '../src/core/postgres-schema'; @@ -23,6 +24,7 @@ const assembled = assembleAuthoringContributions([ entityTypes: postgresAuthoringEntityTypes, pslBlockDescriptors: postgresAuthoringPslBlockDescriptors, modelAttributes: postgresAuthoringModelAttributes, + type: postgresAuthoringTypes, }, }, ]); @@ -41,6 +43,9 @@ const postgresTarget = { const scalarTypeDescriptors = new Map([ ['String', { codecId: 'pg/text@1', nativeType: 'text' }], ['Int', { codecId: 'pg/int4@1', nativeType: 'int4' }], + // The family's varchar codec, to prove the attribute accepts every `textual` + // codec rather than `pg/text@1` alone. + ['Varchar', { codecId: 'sql/varchar@1', nativeType: 'character varying' }], ]); function interpret(source: string) { @@ -153,6 +158,55 @@ model Message { expect(typed[0]).toMatchObject({ where: 'id > 0' }); }); + it('rejects a field that is not textual, naming the field and its type', () => { + const diagnostics = diagnosticsOf(model(` @@fullTextIndex([id], name: "message_id_search")`)); + + expect(diagnostics).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + code: 'PSL_FULL_TEXT_INDEX_TEXT_FIELD', + message: expect.stringContaining('Message.id'), + }), + ]), + ); + expect(diagnostics[0]?.message).toContain('pg/int4@1'); + }); + + it('rejects a relation field', () => { + expect( + diagnosticsOf(` +model Author { + id Int @id + messages Message[] +} + +model Message { + id Int @id + text String + authorId Int + author Author @relation(fields: [authorId], references: [id]) + @@fullTextIndex([author], name: "message_author_search") +} +`), + ).toEqual( + expect.arrayContaining([expect.objectContaining({ code: 'PSL_FULL_TEXT_INDEX_TEXT_FIELD' })]), + ); + }); + + it('accepts a varchar column, mapped', () => { + const indexes = indexesOf(` +model Message { + id Int @id + subject Varchar @map("subject_line") + @@fullTextIndex([subject], name: "message_subject_search") +} +`); + + expect(indexes[0]).toMatchObject({ + expression: `to_tsvector('english', "subject_line")`, + }); + }); + it('rejects a language Postgres does not ship, naming the ones it does', () => { const [diagnostic] = diagnosticsOf( model(` @@fullTextIndex([text], language: "klingon", name: "x")`), diff --git a/packages/3-targets/3-targets/postgres/test/query-operations.test.ts b/packages/3-targets/3-targets/postgres/test/query-operations.test.ts index 721f02f0dd03..bb203f1af917 100644 --- a/packages/3-targets/3-targets/postgres/test/query-operations.test.ts +++ b/packages/3-targets/3-targets/postgres/test/query-operations.test.ts @@ -176,17 +176,35 @@ describe('postgres target query operations', () => { } }); - it('rejects a minWords greater than maxWords', () => { + // Postgres itself requires MinWords strictly below MaxWords. + it.each([ + [10, 5], + [10, 10], + ])('rejects minWords %i against maxWords %i', (minWords, maxWords) => { expect(() => - buildOpAst('fullTextHeadline', TEXT_COLUMN, 'p', { minWords: 10, maxWords: 5 }), + buildOpAst('fullTextHeadline', TEXT_COLUMN, 'p', { minWords, maxWords }), ).toThrow(expect.objectContaining({ code: 'RUNTIME.ARGUMENT_INVALID' })); }); - it.each(['', 'a,b', 'a=b', 'a"b'])('rejects the marker %o', (startSel) => { + it('accepts minWords below maxWords', () => { + expect(() => + buildOpAst('fullTextHeadline', TEXT_COLUMN, 'p', { minWords: 5, maxWords: 10 }), + ).not.toThrow(); + }); + + it.each(['', 'a,b', 'a=b', 'a"b', 'a b', 'a\\b'])('rejects the marker %o', (startSel) => { expect(() => buildOpAst('fullTextHeadline', TEXT_COLUMN, 'p', { startSel })).toThrow( expect.objectContaining({ code: 'RUNTIME.ARGUMENT_INVALID' }), ); }); + + it('rejects a highlightAll that is not a boolean', () => { + expect(() => + buildOpAst('fullTextHeadline', TEXT_COLUMN, 'p', { + highlightAll: 'yes' as unknown as never, + }), + ).toThrow(expect.objectContaining({ code: 'RUNTIME.ARGUMENT_INVALID' })); + }); }); it('ilike dispatches on the textual trait', () => { diff --git a/test/integration/test/sql-builder/full-text-index-usage.test.ts b/test/integration/test/sql-builder/full-text-index-usage.test.ts index d8dd19865b49..4903aaac7306 100644 --- a/test/integration/test/sql-builder/full-text-index-usage.test.ts +++ b/test/integration/test/sql-builder/full-text-index-usage.test.ts @@ -229,7 +229,7 @@ describe('full-text index usage', { timeout: timeouts.databaseOperation }, () => it('stores the varchar index with the cast Postgres adds, and matches it anyway', async () => { const definition = await client().query( - `SELECT pg_get_indexdef('comments_subject_search_2b3d17a7'::regclass) AS def`, + `SELECT pg_get_indexdef('${indexNamed('comments_subject_search')}'::regclass) AS def`, ); // Postgres rewrites our `"subject"` to `(subject)::text` inside the stored From 7220bfe1b15914bd5333ba02879db4eb9fffddcc Mon Sep 17 00:00:00 2001 From: willbot Date: Tue, 22 Sep 2026 08:08:57 +0200 Subject: [PATCH 35/36] fix(postgres): close the PR review threads on the full-text surface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The TypeScript helper now refuses a column it cannot index. A deferred index expression receives each resolved column with the codec it stores through, not just a name, so `fullTextIndex` raises `CONTRACT.INDEX_INVALID` at build time rather than letting Postgres reject the DDL at migration time — and it shares the predicate with `@@fullTextIndex` rather than keeping a second list. Its `name` also stays literal now, through overloads for the name and map forms. The app upgrade detector scans application source as well as the emitted contract, since an application could import the deleted adapter subpath directly. The emitter subsystem excerpt is copied from a real emitted file instead of declaring an alias the emitter never writes. ADR 255 is folded into the ADRs it amended and deleted: ADR 206 gains the target-contributed operations, ADR 236 the index-producing attribute arm, and every pointer moves with them. Both say plainly what sharing one renderer does and does not buy — an author who passes different languages to the index and the operation still gets a sequential scan, with no error. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- docs/architecture docs/ADR-INDEX.md | 1 - ...03 - Trait-targeted operation arguments.md | 2 +- ...06 - Operations as TypeScript functions.md | 14 +++- ...6 - Target-contributed model attributes.md | 12 ++- ... Target-owned built-in query operations.md | 78 ------------------- .../subsystems/2. Contract Emitter & Types.md | 16 +++- .../contract-ts/src/contract-dsl.ts | 10 ++- .../contract-ts/src/contract-lowering.ts | 35 +++++++-- .../src/exports/contract-builder.ts | 1 + ...-builder.deferred-index-expression.test.ts | 4 +- .../postgres/src/contract/full-text-index.ts | 66 ++++++++++++---- packages/3-extensions/postgres/src/errors.ts | 1 + .../full-text-index.test-d.ts | 46 +++++++++++ .../contract-builder/full-text-index.test.ts | 30 +++++++ .../3-targets/3-targets/postgres/README.md | 2 +- .../3-targets/postgres/src/core/authoring.ts | 27 ++----- .../src/core/full-text-index-expression.ts | 21 +++++ .../postgres/src/exports/sql-utils.ts | 5 +- .../postgres/test/psl-full-text-index.test.ts | 3 +- .../app/instructions.md | 7 +- 20 files changed, 249 insertions(+), 132 deletions(-) delete mode 100644 docs/architecture docs/adrs/ADR 255 - Target-owned built-in query operations.md create mode 100644 packages/3-extensions/postgres/test/contract-builder/full-text-index.test-d.ts diff --git a/docs/architecture docs/ADR-INDEX.md b/docs/architecture docs/ADR-INDEX.md index dde083464b90..09753bd10f8b 100644 --- a/docs/architecture docs/ADR-INDEX.md +++ b/docs/architecture docs/ADR-INDEX.md @@ -79,7 +79,6 @@ This document provides a comprehensive index of all Architectural Decision Recor | 210 | Prepared Statements: Author Surface and Driver SPI | Adds `runtime.prepare(declaration, callback)` (re-exposed on each DB facade as `db.prepare(...)`) and prepared execution through the existing `query()` driver SPI; lazy driver-allocated opaque handle, no global cache, cache lifetime bounded by user reference and connection. Family-level: per-driver caching strategies are out of scope here. | [ADR 210 - Prepared Statements - Author Surface and Driver SPI.md](adrs/ADR%20210%20-%20Prepared%20Statements%20-%20Author%20Surface%20and%20Driver%20SPI.md) | | 215 | Runtime middleware lifecycle: `beforeExecute` fires before `encodeParams` | Reorders the SQL family runtime so `beforeExecute` fires between `lowerToDraft` and `encodeDraftParams`, with a pre-encode `paramsMutator` over user-domain values. Extracts `runBeforeExecuteChain` from `runWithMiddleware`; `intercept` always observes a post-`beforeExecute` plan. SPI shape unchanged. | [ADR 215 - Runtime middleware lifecycle beforeExecute before encodeParams.md](adrs/ADR%20215%20-%20Runtime%20middleware%20lifecycle%20beforeExecute%20before%20encodeParams.md) | | 220 | Plan execution identity for middleware correlation | Adds `planExecutionId: string` to `RuntimeMiddlewareContext`, minted by the runtime via `crypto.randomUUID()` at the start of every runtime operation (`query`, prepared statement `query`, or `execute`). Per-operation identity (not per-plan), shared across all hooks within one operation, distinct across two operations of the same plan. Lives on the per-operation context, not on `PlanMeta`. Distinct from ADR 013's content-based `planId` and ADR 160's `groupingKey`. | [ADR 220 - Plan execution identity for middleware correlation.md](adrs/ADR%20220%20-%20Plan%20execution%20identity%20for%20middleware%20correlation.md) | -| 255 | Target-owned built-in query operations | Moves a target's built-in query operations out of its adapter and into the target pack; Postgres gains `fullTextMatches`, `fullTextRank` and `fullTextHeadline` over `websearch_to_tsquery` with an allowlisted language literal | [ADR 255 - Target-owned built-in query operations.md](adrs/ADR%20255%20-%20Target-owned%20built-in%20query%20operations.md) | ## Migration System diff --git a/docs/architecture docs/adrs/ADR 203 - Trait-targeted operation arguments.md b/docs/architecture docs/adrs/ADR 203 - Trait-targeted operation arguments.md index 1cd8e7f2cdd3..9c5c3c8e44bc 100644 --- a/docs/architecture docs/adrs/ADR 203 - Trait-targeted operation arguments.md +++ b/docs/architecture docs/adrs/ADR 203 - Trait-targeted operation arguments.md @@ -2,7 +2,7 @@ ## Context -Adapters and extensions register query operations (e.g., `ilike`, `cosineDistance`) that attach to fields of a given shape. (Since [ADR 255](ADR%20255%20-%20Target-owned%20built-in%20query%20operations.md), a target registers its built-in operations too — `ilike` is contributed by the Postgres target, not its adapter.) Until now an operation declared its `self` argument as a specific `codecId` — `pgvector/vector@1` for `cosineDistance`, for example. The type and runtime machinery then surfaced that operation on every field whose codec matched that ID. +Adapters and extensions register query operations (e.g., `ilike`, `cosineDistance`) that attach to fields of a given shape. (Per [ADR 206](ADR%20206%20-%20Operations%20as%20TypeScript%20functions.md)'s amendment, a target registers its built-in operations too — `ilike` is contributed by the Postgres target, not its adapter.) Until now an operation declared its `self` argument as a specific `codecId` — `pgvector/vector@1` for `cosineDistance`, for example. The type and runtime machinery then surfaced that operation on every field whose codec matched that ID. Codec-ID targeting works when an operation is tied to one concrete codec. It breaks down when an operation is defined by a *capability* that multiple codecs share: diff --git a/docs/architecture docs/adrs/ADR 206 - Operations as TypeScript functions.md b/docs/architecture docs/adrs/ADR 206 - Operations as TypeScript functions.md index 90325d7ee8e9..40e2c67a82d9 100644 --- a/docs/architecture docs/adrs/ADR 206 - Operations as TypeScript functions.md +++ b/docs/architecture docs/adrs/ADR 206 - Operations as TypeScript functions.md @@ -37,7 +37,7 @@ The distinction between predicate operations (return a boolean, composable insid ## Interaction with other subsystems - **Operation arguments.** [ADR 203](ADR%20203%20-%20Trait-targeted%20operation%20arguments.md) introduced codec-identity and trait-set targeting for argument specs. The primitive survives — the self hint uses the same vocabulary — but it now applies only to the ORM column-helper dispatch. The SQL builder no longer reads argument specs; it calls the authored function directly. -- **Adapter SPI.** [ADR 016](ADR%20016%20-%20Adapter%20SPI%20for%20Lowering.md) described how adapters contribute lowering. The adapter runtime descriptor's `queryOperations` slot now yields a factory rather than a const array. The contract-assembly layer calls the factory with the contract's codec-types map. [ADR 255](ADR%20255%20-%20Target-owned%20built-in%20query%20operations.md) then moved a target's built-in operations off the adapter and onto the target descriptor's identical slot. +- **Adapter SPI.** [ADR 016](ADR%20016%20-%20Adapter%20SPI%20for%20Lowering.md) described how adapters contribute lowering. The adapter runtime descriptor's `queryOperations` slot now yields a factory rather than a const array. The contract-assembly layer calls the factory with the contract's codec-types map. The amendment below then moved a target's built-in operations off the adapter and onto the target descriptor's identical slot. - **Codec registry.** [ADR 030](ADR%20030%20-%20Result%20decoding%20%26%20codecs%20registry.md) defines codec metadata including traits. The ORM column helper continues to read traits from the registry to expand trait-targeted self hints. Codec-types flow from the same registry into the contract and onward into each operation factory. - **Extension compatibility.** [ADR 017](ADR%20017%20-%20Extension%20Compatibility%20Policy.md) is honoured: old declarative operation records are not retained, so the decision is a breaking change for extensions that ship their own operation contributions. The breakage is local — each extension rewrites its operation contribution at the factory boundary, without changes elsewhere in the authoring surface. @@ -75,6 +75,18 @@ Let authors continue to write the declarative record in most cases, and attach a Have `CodecExpression` and `TraitExpression` read the JS-value type from a globally augmented interface, so authors can write signatures without the `CT` type parameter. Rejected. The augmentation collapses a TypeScript project to a single contract. A library that works with two contracts in one program — for example a migration tool inspecting source and target — would see the registries overlap. +## Amendment: a target's built-in operations are contributed by its target pack + +A target's own query vocabulary lives in the target pack, not the adapter. [ADR 005](ADR%20005%20-%20Thin%20Core%20Fat%20Targets.md) puts dialect vocabulary in the target; [ADR 016](ADR%20016%20-%20Adapter%20SPI%20for%20Lowering.md) leaves the adapter responsible for rendering an AST and binding its parameters. Deciding that Postgres spells case-insensitive matching `ILIKE`, or that full-text search goes through `to_tsvector` and `websearch_to_tsquery`, is the first kind of decision and not the second. + +So `@internal/target-postgres` contributes `ilike` — which moved there — along with `fullTextMatches`, `fullTextRank` and `fullTextHeadline`, and `@internal/adapter-postgres` contributes no query operations at all; its `operation-types` export is gone rather than kept as a shim. Nothing in the framework had to change: `SqlStaticContributions.queryOperations` was already optional on every SQL component, `createSqlExecutionStack` already iterates the target, and `extractQueryOperationTypeImports` already reads `types.queryOperationTypes` from every descriptor. An adapter may still contribute a genuinely adapter-specific operation; Postgres simply has none. Extensions are unaffected. + +Emitted Postgres `contract.d.ts` files follow, importing `QueryOperationTypes` from `@internal/target-postgres/operation-types` under the alias `PgTargetQueryOps`. `contract.json` does not change and no contract hash moves; an application re-emits its types and keeps working. + +The full-text operations take the search string as a bound `pg/text@1` parameter and an options object whose members — the text-search configuration, `ts_rank`'s normalization bitmask, `ts_headline`'s markers and word counts — Postgres will not accept as parameters and which therefore reach the SQL as literals. Each is validated before a statement exists, against an allowlist for the configuration and a range or character rule for the rest, and anything else throws `RUNTIME.ARGUMENT_INVALID`. `websearch_to_tsquery` is the only query parser used: it accepts what a search box collects and raises no syntax error on arbitrary input. + +Anchors: [`query-operations.ts`](../../../packages/3-targets/3-targets/postgres/src/core/query-operations.ts) and [`full-text-options.ts`](../../../packages/3-targets/3-targets/postgres/src/core/full-text-options.ts) for the operations and their option checks; [`descriptor-meta.ts`](../../../packages/3-targets/3-targets/postgres/src/core/descriptor-meta.ts) for the import spec the emitter writes. + ## Open questions - Where exactly the factory boundary sits in the adapter SPI. The adapter runtime descriptor exposes a `queryOperations` slot whose shape is `() => readonly SqlOperationDescriptor[]`; today each adapter's thunk calls its `QueryOperations()` factory internally with an unconstrained `CT`. Threading the contract's concrete codec-types map through the slot remains an open design question. diff --git a/docs/architecture docs/adrs/ADR 236 - Target-contributed model attributes.md b/docs/architecture docs/adrs/ADR 236 - Target-contributed model attributes.md index e8bbc11d8a91..f2e61b72080b 100644 --- a/docs/architecture docs/adrs/ADR 236 - Target-contributed model attributes.md +++ b/docs/architecture docs/adrs/ADR 236 - Target-contributed model attributes.md @@ -72,7 +72,7 @@ A registry of `AuthoringModelAttributeDescriptor`s. Each descriptor: - **claims a bare `@@` attribute name** (`attribute: 'rls'`); - **supplies a factory for the declarative parameter spec** — a `ModelAttributeSpecFactory`, called with the declaring model's context and returning a spec built with the same `modelAttribute(...)` constructors as every other declarative attribute ([ADR 231](ADR%20231%20-%20Declarative%20attribute%20specifications.md)) — so parsing, validation, and printing come for free from the generic machinery. A spec that needs nothing from the context, like `@@rls`, returns a hoisted module constant so its identity is stable across calls; -- **supplies a `lower` function** that turns the parsed attribute into a pack entity keyed into the namespace's `entries`. Since [ADR 255](ADR%20255%20-%20Target-owned%20built-in%20query%20operations.md) a lowering may instead return `{ index }`, which the family interpreter files onto the declaring model's table through the same path `@@index` uses — the Postgres `@@fullTextIndex` attribute is the first to do so. +- **supplies a `lower` function** that turns the parsed attribute into a pack entity keyed into the namespace's `entries`. A lowering may instead return `{ index }`; see the amendment below. The factory indirection is uniform across every registered attribute spec, so one entry shape serves both this channel and the family built-ins that share the registry. @@ -99,6 +99,16 @@ The field expresses exactly one constraint — *one* ref parameter's model must - Both SPIs are durable public framework surface with a single consumer (`@@rls`). The shapes are the narrowest that serve it; a second consumer may force widening (e.g. multiple `requiresModelAttribute` pairs), which is additive but still a surface change. - An argument-less attribute's `lower` receives an empty parse (`Record`); the descriptor machinery's generality is unused until an attribute with parameters arrives. +## Amendment: a contributed attribute may produce a table index + +A lowering returns either the entity it always could or `{ index }`, an opaque payload the family narrows. The SQL interpreter checks it with `isAuthoredIndexInput` and pushes it onto the same `indexNodes` list `@@index` fills, so index naming, index-type registration and the name-xor-map rules are shared rather than reimplemented. The framework declares only the arm: an index's *shape* belongs to the family, because a Mongo index and a SQL index agree on nothing but the word. + +Two smaller additions serve the same case. A descriptor may declare itself `repeatable`, which skips the duplicate-attribute diagnostic, since a model may want several such indexes. And the lowering context resolves a field of the declaring model to its storage name and to the codec it stores through — `fieldStorageName` and `fieldCodecId` — so a lowering that renders storage-level text never guesses past `@map` or a naming convention, and can refuse a field whose values it cannot express. + +Postgres's `@@fullTextIndex` is the first attribute to use all three. It renders `to_tsvector('', "")` from the resolved column and the same language allowlist the query operations check, and refuses a field that is not stored through a textual codec. Postgres uses such an index only for a query whose expression is the same function over the same configuration literal and the same column — it compares parsed expressions, not text, so qualifying the column or not makes no difference. Sharing one renderer between the attribute, the TypeScript helper and the operations keeps the *rendering* from diverging, but it cannot make the two agree on the configuration: an author who passes one language to the index and another to the operation gets no error, just a sequential scan. + +Anchors: the `{ index }` arm and `repeatable` in [`interpreter.ts`](../../../packages/2-sql/2-authoring/contract-psl/src/interpreter.ts); the attribute in [`authoring.ts`](../../../packages/3-targets/3-targets/postgres/src/core/authoring.ts); the one place its expression is rendered in [`full-text-index-expression.ts`](../../../packages/3-targets/3-targets/postgres/src/core/full-text-index-expression.ts); and [`full-text-index-usage.test.ts`](../../../test/integration/test/sql-builder/full-text-index-usage.test.ts), which proves with `EXPLAIN` against a real server that Postgres chooses the index for the SQL the lanes lower. + ## Alternatives considered **A procedural interpreter hook.** The target registers a callback the interpreter invokes per model, free to inspect and validate anything. Rejected for the same reasons ADR 231 rejects procedural attribute parsing: a hook can do anything, so nothing about it is statically inspectable — the printer, the language server, and the validator each need the *declarative* facts (which attributes exist, what parameters they take, what they require) that a callback hides. Every hook also re-implements parameter parsing and error wording, where descriptors get both generically with uniform diagnostics. And one-per-name descriptor keys make collisions between packs a load-time error instead of a silent override. diff --git a/docs/architecture docs/adrs/ADR 255 - Target-owned built-in query operations.md b/docs/architecture docs/adrs/ADR 255 - Target-owned built-in query operations.md deleted file mode 100644 index fec183223e38..000000000000 --- a/docs/architecture docs/adrs/ADR 255 - Target-owned built-in query operations.md +++ /dev/null @@ -1,78 +0,0 @@ -# ADR 255 — Target-owned built-in query operations - -**Status:** Accepted - -**Related:** [ADR 005 — Thin core, fat targets](ADR%20005%20-%20Thin%20Core%20Fat%20Targets.md) draws the line between what a target knows and what an adapter does. [ADR 016 — Adapter SPI for Lowering](ADR%20016%20-%20Adapter%20SPI%20for%20Lowering.md) makes the adapter responsible for turning an AST into a statement. [ADR 206 — Operations as TypeScript functions](ADR%20206%20-%20Operations%20as%20TypeScript%20functions.md) defines how an operation is authored. [ADR 251 — Target-owned Postgres list framing](ADR%20251%20-%20Target-owned%20Postgres%20list%20framing.md) is the precedent for moving Postgres semantics out of the adapter. - ---- - -## Context - -Postgres has always shipped one built-in query operation, `ilike`, and it lived in `@internal/adapter-postgres`. The adapter was the only Postgres component with a `queryOperations` slot at the time, so that is where it went. - -That placement says the wrong thing about ownership. `ILIKE` is not a lowering decision. It is part of the Postgres query language, known before anything is executed and true no matter which driver or adapter carries the statement to the server. The adapter's job, per ADR 016, is to render an AST and bind its parameters; deciding that Postgres spells case-insensitive matching `ILIKE` is the target's job, per ADR 005. - -The placement also leaks into generated code. Every emitted Postgres `contract.d.ts` named `@internal/adapter-postgres/operation-types` in an import, so an application's contract types depended on the adapter package for vocabulary the target defines. - -Adding full-text search made the mismatch concrete. `to_tsvector`, `websearch_to_tsquery`, `ts_rank` and `ts_headline` are Postgres functions with Postgres semantics — including the set of text-search configurations a server ships with. None of that is adapter knowledge. - -## Decision - -Built-in query operations for a target live in the target package. For Postgres that is `@internal/target-postgres`, which now contributes `ilike`, `fullTextMatches`, `fullTextRank` and `fullTextHeadline`. `@internal/adapter-postgres` contributes no query operations at all; its `operation-types` export and the `queryOperations` slot on its runtime descriptor are removed rather than kept as forwarding shims. - -Nothing in the framework had to change to allow this. `SqlStaticContributions.queryOperations` is already optional on every SQL component, `createSqlExecutionStack` already iterates the target alongside the adapter and the extensions, and `extractQueryOperationTypeImports` already reads `types.queryOperationTypes` from every descriptor in the stack. The target simply fills slots it had left empty. - -Extensions are unaffected. An extension pack still contributes its own operations the same way; the change is only about where a *target's built-in* vocabulary lives. Adapters keep the ability to contribute operations — a genuinely adapter-specific operation is still legal — but Postgres no longer has one. - -The three full-text operations follow ADR 206: each is a TypeScript function whose signature is its type-level surface. They dispatch on `self: { traits: ['textual'] }`, so they appear on any textual column, exactly as `ilike` does. The search string is bound as a `pg/text@1` parameter. The language is a second, optional argument defaulting to `'english'`, and it is written into the SQL as an inline literal rather than a parameter, because Postgres will not accept a parameter in the configuration position of `to_tsvector`. An inline literal has to be trustworthy, so the language is checked against the configurations a stock PostgreSQL server ships with, and anything else throws `RUNTIME.ARGUMENT_INVALID` before a statement is built. - -`websearch_to_tsquery` is the only query parser used. It accepts the syntax an application's users already type — quoted phrases, `-word` to exclude, `or` between terms — and it does not raise a syntax error on arbitrary input, which `to_tsquery` does. - -## Consequences - -Emitted Postgres `contract.d.ts` files change: they import `QueryOperationTypes` from `@internal/target-postgres/operation-types` under the alias `PgTargetQueryOps` instead of from the adapter under `PgAdapterQueryOps`. `contract.json` does not change, and no contract hash moves. An application regenerates its contract types and keeps working. - -An extension or application that imported `@internal/adapter-postgres/operation-types` directly must import `@internal/target-postgres/operation-types` instead. There is no compatibility re-export, per `no-backward-compatibility.mdc`. - -Full-text search needs no new codec, no capability key and no extension. `tsvector` and `tsquery` never leave the server — they are constructed and consumed inside a single expression — so nothing has to cross the wire in a shape the codec registry does not already know. - -Performance is the application's responsibility, because the operation does not create indexes. `fullTextMatches` renders `to_tsvector('', "")`, so a GIN index that is to answer the predicate has to be the same `to_tsvector` over the same configuration literal and the same column — Postgres compares parsed expressions, not text, so qualifying the column or not makes no difference: - -```prisma -@@fullTextIndex([text], name: "message_text_search") -``` - -An index whose expression differs — a different language, or a `tsvector` column maintained by a trigger — will not be used, and nothing says so: the query simply falls back to a sequential scan, with no error and no warning. That silent failure is the reason the attribute exists. - -Because the index and the predicate have to agree on the function, the configuration and the column, the target contributes the index as well as the operations: `@@fullTextIndex([text], name: …)` renders it from the resolved storage column and the same language allowlist, so an author never writes `to_tsvector` by hand and the two cannot drift apart. This needed no new IR — the attribute lowers to the `IndexNode` `@@index(expression:)` already produces — but it did need the framework to let a contributed model attribute return an index instead of a namespaced entity, and to let a descriptor declare itself repeatable. `@@index(expression:)` stays for expressions the attribute does not cover. - -The set of accepted languages is a hand-maintained list. A server with a custom text-search configuration installed cannot name it. That is the price of keeping the language out of the parameter list; widening it later means deciding how Prisma learns what a given server has configured, which is a question this decision does not answer. - -## Implementation anchors - -- The operations and the language list: [`query-operations.ts`](../../../packages/3-targets/3-targets/postgres/src/core/query-operations.ts). -- The index attribute and the one place its expression is rendered: [`authoring.ts`](../../../packages/3-targets/3-targets/postgres/src/core/authoring.ts), [`full-text-index-expression.ts`](../../../packages/3-targets/3-targets/postgres/src/core/full-text-index-expression.ts). -- That Postgres really does choose the index for the SQL the lanes lower, proved with `EXPLAIN` against a real server, including the controls that fail: [`full-text-index-usage.test.ts`](../../../test/integration/test/sql-builder/full-text-index-usage.test.ts). -- Their type-level surface, re-exported as the package's `./operation-types` entry: [`operation-types.ts`](../../../packages/3-targets/3-targets/postgres/src/types/operation-types.ts). -- The runtime target descriptor that contributes them: [`runtime.ts`](../../../packages/3-targets/3-targets/postgres/src/exports/runtime.ts). -- The import spec the emitter writes into `contract.d.ts`: [`descriptor-meta.ts`](../../../packages/3-targets/3-targets/postgres/src/core/descriptor-meta.ts). -- The contributor loop that registers every component's operations: [`sql-context.ts`](../../../packages/2-sql/5-runtime/src/sql-context.ts). -- The control-plane collection of type imports: [`control-stack.ts`](../../../packages/1-framework/1-core/framework-components/src/control/control-stack.ts). - -## Alternatives considered - -### Leave the operations in the adapter and add full-text search there - -Rejected. It keeps `ILIKE` and `to_tsvector` — plain Postgres language — inside the component whose stated job is rendering and transport, and it keeps every generated contract depending on the adapter package for vocabulary the target defines. ADR 251 already moved Postgres list semantics out of the adapter for the same reason. - -### Ship full-text search as an extension pack - -Rejected. An extension exists for things a server may or may not have: `pgvector`, `postgis`, ParadeDB's `bm25`. Full-text search is in core PostgreSQL and has been for many releases. Requiring an install step for it would misrepresent what an application has to do. - -### Accept any string as the language - -Rejected. The language is interpolated into the SQL rather than bound, so an unchecked string is a SQL-injection hole on any path where the value is not a compile-time constant. The allowlist is the smallest thing that makes the inline literal safe. - -### Use `to_tsquery` or `plainto_tsquery` - -Rejected. `to_tsquery` raises a syntax error on ordinary user input, which turns a search box into a source of failed queries. `plainto_tsquery` is safe but throws away the operators users expect — quoted phrases and negation. `websearch_to_tsquery` is forgiving and supports both. diff --git a/docs/architecture docs/subsystems/2. Contract Emitter & Types.md b/docs/architecture docs/subsystems/2. Contract Emitter & Types.md index d877d23c351e..5b271f282796 100644 --- a/docs/architecture docs/subsystems/2. Contract Emitter & Types.md +++ b/docs/architecture docs/subsystems/2. Contract Emitter & Types.md @@ -218,7 +218,7 @@ Minimal excerpt (SQL): ```typescript // ⚠️ GENERATED FILE - DO NOT EDIT import type { CodecTypes as PgTypes } from '@internal/target-postgres/codec-types'; -import type { QueryOperationTypes as PgOps } from '@internal/target-postgres/operation-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@internal/target-postgres/operation-types'; import type { ContractWithTypeMaps, TypeMaps as TypeMapsType } from '@internal/sql-contract/types'; import type { @@ -232,8 +232,18 @@ export type StorageHash = StorageHashBase<'…'>; export type ProfileHash = ProfileHashBase<'…'>; export type CodecTypes = PgTypes; -export type OperationTypes = PgOps; -export type TypeMaps = TypeMapsType; +export type LaneCodecTypes = CodecTypes; +export type QueryOperationTypes = PgTargetQueryOps; +export type AggregateTypes = { /* … per-aggregate codec and trait maps … */ }; +export type TypeMaps = TypeMapsType< + CodecTypes, + QueryOperationTypes, + FieldOutputTypes, + FieldInputTypes, + StorageColumnTypes, + StorageColumnInputTypes, + AggregateTypes +>; type ContractBase = Omit< ContractType<{ readonly storageHash: StorageHash; readonly namespaces: { readonly public: { readonly tables: { /* … storage tables with columns, PKs, FKs, indexes … */ } } } }>, diff --git a/packages/2-sql/2-authoring/contract-ts/src/contract-dsl.ts b/packages/2-sql/2-authoring/contract-ts/src/contract-dsl.ts index ef7f0699a106..4a99e99ee293 100644 --- a/packages/2-sql/2-authoring/contract-ts/src/contract-dsl.ts +++ b/packages/2-sql/2-authoring/contract-ts/src/contract-dsl.ts @@ -878,9 +878,17 @@ export type UniqueConstraint string; + readonly render: (columns: readonly DeferredIndexColumn[]) => string; }; /** Opaque SQL, either written out or rendered at lowering. */ diff --git a/packages/2-sql/2-authoring/contract-ts/src/contract-lowering.ts b/packages/2-sql/2-authoring/contract-ts/src/contract-lowering.ts index 221ecd134255..a7ca575c794a 100644 --- a/packages/2-sql/2-authoring/contract-ts/src/contract-lowering.ts +++ b/packages/2-sql/2-authoring/contract-ts/src/contract-lowering.ts @@ -31,6 +31,8 @@ import { applyNaming, type ContractInput, type ContractModelBuilder, + type DeferredIndexColumn, + type DeferredIndexExpression, type FieldStateOf, type ForeignKeyConstraint, type IdConstraint, @@ -816,6 +818,30 @@ function resolveForeignKeyNodes( return [...relationForeignKeys, ...sqlForeignKeys]; } +/** + * Resolves a deferred index expression's field refs the way the field-tuple form + * resolves its columns, and pairs each with the codec the column stores through + * so a renderer can refuse a column it cannot express. + */ +function resolveDeferredColumns( + spec: Pick, + expression: DeferredIndexExpression, + fieldCodecIds: Readonly>, +): readonly DeferredIndexColumn[] { + const fieldNames = expression.fields.map((ref) => ref.fieldName); + const columnNames = mapFieldNamesToColumnNames(spec.modelName, fieldNames, spec.fieldToColumn); + return fieldNames.map((fieldName, position) => { + const name = columnNames[position]; + const codecId = fieldCodecIds[fieldName]; + if (name === undefined || codecId === undefined) { + throw new InternalError( + `Deferred index expression on "${spec.modelName}" resolved no column for field "${fieldName}"`, + ); + } + return { name, codecId }; + }); +} + function resolveModelNode( spec: RuntimeModelSpec, allSpecs: ReadonlyMap, @@ -824,6 +850,8 @@ function resolveModelNode( extensions?: Record>, ): ModelNode { const fields: FieldNode[] = []; + /** Filled by the field loop below, read by a deferred index expression. */ + const fieldCodecIds: Record = {}; for (const [fieldName, fieldBuilder] of Object.entries(spec.fieldBuilders)) { const fieldState = fieldBuilder.build(); @@ -838,6 +866,7 @@ function resolveModelNode( if (!columnName) { throw new InternalError(`Column name resolution failed for "${spec.modelName}.${fieldName}"`); } + fieldCodecIds[fieldName] = descriptor.codecId; const enumHandle = 'typeRef' in fieldState && isEnumTypeHandle(fieldState.typeRef) @@ -885,11 +914,7 @@ function resolveModelNode( typeof index.expression === 'string' ? index.expression : index.expression.render( - mapFieldNamesToColumnNames( - spec.modelName, - index.expression.fields.map((ref) => ref.fieldName), - spec.fieldToColumn, - ), + resolveDeferredColumns(spec, index.expression, fieldCodecIds), ), } : { diff --git a/packages/2-sql/2-authoring/contract-ts/src/exports/contract-builder.ts b/packages/2-sql/2-authoring/contract-ts/src/exports/contract-builder.ts index 88f016945320..e073434daa18 100644 --- a/packages/2-sql/2-authoring/contract-ts/src/exports/contract-builder.ts +++ b/packages/2-sql/2-authoring/contract-ts/src/exports/contract-builder.ts @@ -33,6 +33,7 @@ export type { export type { CheckKind, ColumnRef, + DeferredIndexColumn, DeferredIndexExpression, IndexConstraint, IndexExpressionInput, diff --git a/packages/2-sql/2-authoring/contract-ts/test/contract-builder.deferred-index-expression.test.ts b/packages/2-sql/2-authoring/contract-ts/test/contract-builder.deferred-index-expression.test.ts index 9b7497c6600a..a83221d9102f 100644 --- a/packages/2-sql/2-authoring/contract-ts/test/contract-builder.deferred-index-expression.test.ts +++ b/packages/2-sql/2-authoring/contract-ts/test/contract-builder.deferred-index-expression.test.ts @@ -9,6 +9,7 @@ import type { FamilyPackRef, TargetPackRef } from '@internal/framework-component import { describe, expect, it } from 'vitest'; import { createTestSqlNamespace } from '../../../1-core/contract/test/test-support'; import { type ContractInput, defineContract, field, model } from '../src/contract-builder'; +import type { DeferredIndexColumn } from '../src/contract-dsl'; import { columnDescriptor } from './helpers/column-descriptor'; import { unboundTables } from './unbound-tables'; @@ -31,7 +32,8 @@ const postgresTargetPack: TargetPackRef<'sql', 'postgres'> = { defaultNamespaceId: 'public', }; -const render = (columnNames: readonly string[]) => `to_tsvector('english', "${columnNames[0]}")`; +const render = (columns: readonly DeferredIndexColumn[]) => + `to_tsvector('english', "${columns[0]?.name}")`; function messageIndexes(options: { readonly mappedColumn?: string; diff --git a/packages/3-extensions/postgres/src/contract/full-text-index.ts b/packages/3-extensions/postgres/src/contract/full-text-index.ts index 556ff21e8fea..b9a594365628 100644 --- a/packages/3-extensions/postgres/src/contract/full-text-index.ts +++ b/packages/3-extensions/postgres/src/contract/full-text-index.ts @@ -2,18 +2,34 @@ import type { ColumnRef, IndexConstraint } from '@internal/sql-contract-ts/contr import type { FullTextSearchLanguage } from '@internal/target-postgres/operation-types'; import { DEFAULT_FULL_TEXT_SEARCH_LANGUAGE, + isFullTextIndexableCodec, renderFullTextIndexExpression, } from '@internal/target-postgres/sql-utils'; import { invariant } from '@internal/utils/assertions'; +import { postgresError } from '../errors'; -type FullTextIndexOptions = { +type FullTextIndexOptionsBase = { readonly language?: FullTextSearchLanguage; /** The SQL predicate restricting rows included in a partial index. */ readonly where?: string; -} & ( - | { readonly name: string; readonly map?: never } - | { readonly map: string; readonly name?: never } -); +}; + +/** + * The wire-named form. `Name` stays literal so the model's `sql()` stage sees the + * index's name and refuses a duplicate, exactly as it does for `constraints.index`. + */ +type FullTextIndexNameOptions = FullTextIndexOptionsBase & { + readonly name: Name; + readonly map?: never; +}; + +/** The exact-named form: `map` is adopted verbatim and carries no wire name. */ +type FullTextIndexMapOptions = FullTextIndexOptionsBase & { + readonly map: string; + readonly name?: never; +}; + +type FullTextIndexOptions = FullTextIndexNameOptions | FullTextIndexMapOptions; /** * A GIN index over the `to_tsvector` expression `fullTextMatches`, @@ -22,26 +38,50 @@ type FullTextIndexOptions = { * * The expression is rendered at lowering, once the column's storage name is * known, so a `.column()` override or a column naming convention is honoured - * and the index cannot stop matching the predicate. + * rather than guessed. Pass the same `language` here and to the operation: a + * mismatch is not an error, the query simply stops using the index. */ +export function fullTextIndex( + column: ColumnRef, + options: FullTextIndexNameOptions, +): IndexConstraint; +export function fullTextIndex( + column: ColumnRef, + options: FullTextIndexMapOptions, +): IndexConstraint; export function fullTextIndex( column: ColumnRef, options: FullTextIndexOptions, -): IndexConstraint { +): IndexConstraint { const language = options.language ?? DEFAULT_FULL_TEXT_SEARCH_LANGUAGE; return { kind: 'index', expression: { fields: [column], - render: (columnNames: readonly string[]) => { - const columnName = columnNames[0]; - // Lowering resolves one name per field it was given, or raises + render: (columns) => { + const resolved = columns[0]; + // Lowering resolves one column per field it was given, or raises // `CONTRACT.FIELD_UNKNOWN`; this helper hands it exactly one. invariant( - columnName !== undefined, - `fullTextIndex resolved no column name for field "${column.fieldName}"`, + resolved !== undefined, + `fullTextIndex resolved no column for field "${column.fieldName}"`, ); - return renderFullTextIndexExpression(language, columnName); + if (!isFullTextIndexableCodec(resolved.codecId)) { + throw postgresError( + 'CONTRACT.INDEX_INVALID', + `fullTextIndex indexes a text column, but "${column.fieldName}" is stored as \`${resolved.codecId}\`.`, + { + why: 'to_tsvector takes text; Postgres rejects the CREATE INDEX for any other column type.', + fix: 'Index a text, varchar, char or enum column, or drop the index.', + meta: { + helper: 'fullTextIndex', + fieldName: column.fieldName, + codecId: resolved.codecId, + }, + }, + ); + } + return renderFullTextIndexExpression(language, resolved.name); }, }, type: 'gin', diff --git a/packages/3-extensions/postgres/src/errors.ts b/packages/3-extensions/postgres/src/errors.ts index 1254dc871b8d..8b4b4dbfdb7c 100644 --- a/packages/3-extensions/postgres/src/errors.ts +++ b/packages/3-extensions/postgres/src/errors.ts @@ -3,6 +3,7 @@ import { structuredError } from '@internal/utils/structured-error'; export type PostgresErrorCode = | 'CONTRACT.ENUM_INVALID' + | 'CONTRACT.INDEX_INVALID' | 'CONTRACT.POLICY_INVALID' | 'RUNTIME.BINDING_INVALID' | 'RUNTIME.BINDING_MISSING' diff --git a/packages/3-extensions/postgres/test/contract-builder/full-text-index.test-d.ts b/packages/3-extensions/postgres/test/contract-builder/full-text-index.test-d.ts new file mode 100644 index 000000000000..27015642d1f4 --- /dev/null +++ b/packages/3-extensions/postgres/test/contract-builder/full-text-index.test-d.ts @@ -0,0 +1,46 @@ +/** + * `fullTextIndex` keeps its `name` literal, so the model's `sql()` stage can see + * the index's name and refuse a duplicate exactly as it does for + * `constraints.index`. A `map:` index carries no wire name and so never collides. + */ +import type { ColumnRef } from '@internal/sql-contract-ts/contract-builder'; +import { expectTypeOf, test } from 'vitest'; +import { field, fullTextIndex, model } from '../../src/exports/contract-builder'; + +const intColumn = { codecId: 'pg/int4@1', nativeType: 'int4' } as const; +const textColumn = { codecId: 'pg/text@1', nativeType: 'text' } as const; + +const fields = { id: field.column(intColumn).id(), text: field.column(textColumn) }; + +test('the name stays literal rather than widening to string', () => { + const index = fullTextIndex<'message_search'>( + { kind: 'columnRef', fieldName: 'text' }, + { name: 'message_search' }, + ); + expectTypeOf(index.name).toEqualTypeOf<'message_search' | undefined>(); +}); + +test('a map: index carries no wire name', () => { + const index = fullTextIndex({ kind: 'columnRef', fieldName: 'text' }, { map: 'message_search' }); + expectTypeOf(index.name).toEqualTypeOf(); +}); + +/** + * Duplicate-name detection does not currently fire for indexes from either + * helper: `constraints.index` is reachable only inside `sql(callback)`, which + * widens the returned tuple, and `IndexConstraint.name` is optional, so + * `NamedConstraintLiteralName` sees `Name | undefined` rather than a literal. + * Keeping `Name` literal here is the half this helper owns; the day the check + * starts biting, it bites this helper too. + */ +test('two indexes with distinct names are accepted in the object form', () => { + const text: ColumnRef<'text'> = { kind: 'columnRef', fieldName: 'text' }; + + model('Message', { fields }).sql({ + table: 'message', + indexes: [ + fullTextIndex(text, { name: 'message_search' }), + fullTextIndex(text, { language: 'german', name: 'message_search_de' }), + ], + }); +}); diff --git a/packages/3-extensions/postgres/test/contract-builder/full-text-index.test.ts b/packages/3-extensions/postgres/test/contract-builder/full-text-index.test.ts index f764c4d4103b..1eba80269a6f 100644 --- a/packages/3-extensions/postgres/test/contract-builder/full-text-index.test.ts +++ b/packages/3-extensions/postgres/test/contract-builder/full-text-index.test.ts @@ -137,6 +137,36 @@ describe('fullTextIndex, the TypeScript twin of @@fullTextIndex', () => { }); }); + it('refuses a column that is not stored through a textual codec', () => { + expect(() => + defineContract({ + models: { + Message: model('Message', { + fields: { id: field.column(intColumn).id(), views: field.column(intColumn) }, + }).sql(({ cols }) => ({ + table: 'message', + indexes: [fullTextIndex(cols.views, { name: 'message_views_search' })], + })), + }, + }), + ).toThrow(expect.objectContaining({ code: 'CONTRACT.INDEX_INVALID' })); + }); + + it('names the field and its codec when it refuses one', () => { + expect(() => + defineContract({ + models: { + Message: model('Message', { + fields: { id: field.column(intColumn).id(), views: field.column(intColumn) }, + }).sql(({ cols }) => ({ + table: 'message', + indexes: [fullTextIndex(cols.views, { name: 'message_views_search' })], + })), + }, + }), + ).toThrow(/views.*pg\/int4@1/); + }); + it('renders a non-default language', () => { const contract = defineContract({ models: { diff --git a/packages/3-targets/3-targets/postgres/README.md b/packages/3-targets/3-targets/postgres/README.md index 2dc3aff1a64a..550441a9e0c6 100644 --- a/packages/3-targets/3-targets/postgres/README.md +++ b/packages/3-targets/3-targets/postgres/README.md @@ -150,7 +150,7 @@ const snippets = db.sql.public.message .build(); ``` -Postgres computes `to_tsvector` per row unless an index covers the predicate's expression — the same `to_tsvector`, the same configuration literal and the same column, which it compares as parsed expressions rather than as text. `@@fullTextIndex`, contributed by this package, renders that expression from the field and the language, so the index and the predicate cannot drift: +Postgres computes `to_tsvector` per row unless an index covers the predicate's expression — the same `to_tsvector`, the same configuration literal and the same column, which it compares as parsed expressions rather than as text. `@@fullTextIndex`, contributed by this package, renders that expression from the field and the language, so you never write it by hand: ```prisma @@fullTextIndex([text], name: "message_text_search") diff --git a/packages/3-targets/3-targets/postgres/src/core/authoring.ts b/packages/3-targets/3-targets/postgres/src/core/authoring.ts index e9ff62e0ab2b..556d64128bc6 100644 --- a/packages/3-targets/3-targets/postgres/src/core/authoring.ts +++ b/packages/3-targets/3-targets/postgres/src/core/authoring.ts @@ -47,9 +47,11 @@ import { PG_TIMESTAMPTZ_STRING_CODEC_ID, PG_TIMESTAMPTZ_TEMPORAL_CODEC_ID, } from './codec-ids'; -import { codecDescriptors } from './codecs'; import { postgresError } from './errors'; -import { renderFullTextIndexExpression } from './full-text-index-expression'; +import { + isFullTextIndexableCodec, + renderFullTextIndexExpression, +} from './full-text-index-expression'; import { postgresNowGeneratorIds } from './now-generators'; import { PostgresNativeEnum } from './postgres-native-enum'; import { PostgresRlsEnablement, type PostgresRlsEnablementInput } from './postgres-rls-enablement'; @@ -712,25 +714,6 @@ const postgresRlsSpecFactory: ModelAttributeSpecFactory = () => postgresRlsSpec; const [firstLanguage, ...remainingLanguages] = POSTGRES_TEXT_SEARCH_LANGUAGES; -/** - * Read from the codec descriptors themselves rather than a second list of ids, so the attribute - * accepts exactly the columns the `textual` operations dispatch on. - */ -/** Widens each descriptor's trait tuple, so membership is a plain string test. */ -function traitsOf(descriptor: { readonly traits: readonly string[] }): readonly string[] { - return descriptor.traits; -} - -const TEXTUAL_CODEC_IDS: ReadonlySet = new Set( - codecDescriptors - .filter((descriptor) => traitsOf(descriptor).includes('textual')) - .map((descriptor) => descriptor.codecId), -); - -function isTextualCodec(codecId: string): boolean { - return TEXTUAL_CODEC_IDS.has(codecId); -} - const postgresFullTextIndexSpec = modelAttribute('fullTextIndex', { documentation: 'Indexes one text column for full-text search, rendering the expression `fullTextMatches`, `fullTextRank` and `fullTextHeadline` lower to.', @@ -845,7 +828,7 @@ export const postgresAuthoringModelAttributes = { const codecId = ctx.fieldCodecId(fieldName); // A relation field parses as a field reference but stores no value, so it // reaches here with neither a column nor a codec. - if (columnName === undefined || codecId === undefined || !isTextualCodec(codecId)) { + if (columnName === undefined || codecId === undefined || !isFullTextIndexableCodec(codecId)) { ctx.diagnostics?.push({ code: PSL_FULL_TEXT_INDEX_TEXT_FIELD, message: `\`@@fullTextIndex\` indexes a text column, but "${ctx.modelName}.${fieldName}" is ${codecId === undefined ? 'not a stored scalar field' : `stored as \`${codecId}\``}.`, diff --git a/packages/3-targets/3-targets/postgres/src/core/full-text-index-expression.ts b/packages/3-targets/3-targets/postgres/src/core/full-text-index-expression.ts index 940b3debba81..490ec093e7d7 100644 --- a/packages/3-targets/3-targets/postgres/src/core/full-text-index-expression.ts +++ b/packages/3-targets/3-targets/postgres/src/core/full-text-index-expression.ts @@ -1,3 +1,4 @@ +import { codecDescriptors } from './codecs'; import { quoteIdentifier } from './sql-utils'; import type { FullTextSearchLanguage } from './text-search-languages'; @@ -14,3 +15,23 @@ export function renderFullTextIndexExpression( ): string { return `to_tsvector('${language}', ${quoteIdentifier(columnName)})`; } + +/** Widens a descriptor's trait tuple, so membership is a plain string test. */ +function traitsOf(descriptor: { readonly traits: readonly string[] }): readonly string[] { + return descriptor.traits; +} + +const TEXTUAL_CODEC_IDS: ReadonlySet = new Set( + codecDescriptors + .filter((descriptor) => traitsOf(descriptor).includes('textual')) + .map((descriptor) => descriptor.codecId), +); + +/** + * Whether a column stored through this codec can be indexed for full-text search. + * Read from the codec descriptors themselves, so both authoring surfaces accept + * exactly the columns the `textual` operations dispatch on. + */ +export function isFullTextIndexableCodec(codecId: string): boolean { + return TEXTUAL_CODEC_IDS.has(codecId); +} diff --git a/packages/3-targets/3-targets/postgres/src/exports/sql-utils.ts b/packages/3-targets/3-targets/postgres/src/exports/sql-utils.ts index ee5c4723e3d2..b396690f1218 100644 --- a/packages/3-targets/3-targets/postgres/src/exports/sql-utils.ts +++ b/packages/3-targets/3-targets/postgres/src/exports/sql-utils.ts @@ -1,4 +1,7 @@ -export { renderFullTextIndexExpression } from '../core/full-text-index-expression'; +export { + isFullTextIndexableCodec, + renderFullTextIndexExpression, +} from '../core/full-text-index-expression'; export { escapeLiteral, qualifyName, diff --git a/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts b/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts index 18077fde1335..7b6fc5c68322 100644 --- a/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts +++ b/packages/3-targets/3-targets/postgres/test/psl-full-text-index.test.ts @@ -1,6 +1,7 @@ /** * `@@fullTextIndex` renders the same expression the full-text operations - * lower to, so the index and the predicate cannot drift. It is the documented + * lower to, so neither is hand-written. Passing a different language to each + * still leaves the index unused; only the rendering is shared. It is the documented * way to index a text column; `@@index(expression:)` stays available for * anything this attribute does not cover. */ diff --git a/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md b/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md index c498812f703f..be8f82310ff0 100644 --- a/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md +++ b/upgrade-instructions/pending/postgres-full-text-search/app/instructions.md @@ -4,9 +4,12 @@ changes: summary: | Emitted Postgres `contract.d.ts` files import `QueryOperationTypes` from the target package instead of the adapter. Run `prisma contract emit` once; an un-emitted contract names a - subpath that no longer exists and stops type-checking. + subpath that no longer exists and stops type-checking. Application source that imported that + subpath directly changes the same way. detection: - glob: "**/contract.d.ts" + # Covers the emitted `contract.d.ts` and hand-written source alike: both + # name the subpath, and both stop compiling until they are changed. + glob: "**/*.{ts,tsx,mts}" contains: - "/adapter/operation-types" --- From 8a78862f89887f295aaacf72071c61442fa5145a Mon Sep 17 00:00:00 2001 From: willbot Date: Tue, 22 Sep 2026 08:32:06 +0200 Subject: [PATCH 36/36] docs(adr): name the target as the owner of ilike in ADR 203 and reconcile ADR 206 on the factory boundary A review summary on #30348 flagged that ADR 203 still called the Postgres ilike descriptor an adapter contribution and that ADR 206 described the factory slot as adapter-only while its Decision claimed the runtime binds the codec-types map. Both now describe the contributor SPI as target, adapter and extension, and ADR 206 says plainly that the runtime calls the slot with no type argument today. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- ...R 203 - Trait-targeted operation arguments.md | 16 ++++++++-------- ...R 206 - Operations as TypeScript functions.md | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/architecture docs/adrs/ADR 203 - Trait-targeted operation arguments.md b/docs/architecture docs/adrs/ADR 203 - Trait-targeted operation arguments.md index 9c5c3c8e44bc..26a394bb52be 100644 --- a/docs/architecture docs/adrs/ADR 203 - Trait-targeted operation arguments.md +++ b/docs/architecture docs/adrs/ADR 203 - Trait-targeted operation arguments.md @@ -21,10 +21,10 @@ Extend operation argument specs with an optional `traits` field alongside `codec ## Grounding example -Adapter-provided operations declare their arguments as trait-targeted where appropriate. The Postgres `ilike` descriptor names no specific textual codec — just the `textual` trait on its self argument: +Operations contributed by a target, adapter or extension declare their arguments as trait-targeted where appropriate. The Postgres target's `ilike` descriptor names no specific textual codec — just the `textual` trait on its self argument: ```typescript -// Adapter descriptor (runtime shape) +// Postgres target descriptor (runtime shape) { method: 'ilike', args: [ @@ -52,7 +52,7 @@ readonly ilike: { }; ``` -From this single descriptor, every textual field in the contract gains the operation. A non-textual field does not. An adapter that does not register the operation never exposes it, regardless of what codecs are on the target. +From this single descriptor, every textual field in the contract gains the operation. A non-textual field does not. A target, adapter or extension that does not register the operation never exposes it, regardless of what codecs are on the target. ## Design principles @@ -60,7 +60,7 @@ From this single descriptor, every textual field in the contract gains the opera 2. **Traits are a closed union at the type level, an open set at runtime.** `CodecTrait` is a union so type matching stays structural and narrowing works; `ParamSpec.traits` is `readonly string[]` at runtime so registries can carry forward trait values they don't statically know about. 3. **Return targeting stays exact.** Predicate detection and result decoding depend on knowing the concrete return codec. `ReturnSpec` enforces this separately, so loosening `ParamSpec.codecId` to optional does not weaken return-type guarantees. 4. **Registration does the expansion work.** Operation lookup is on the hot path — it happens for every field access on an ORM model accessor. Trait resolution runs once per operation at registration time so field access remains a single map lookup. -5. **Same descriptor, different reachability per contract.** Contracts see different operation sets because their adapters register different operations — not because core branches on target. This preserves the thin-core discipline from [ADR 005](ADR%20005%20-%20Thin%20Core%20Fat%20Targets.md). +5. **Same descriptor, different reachability per contract.** Contracts see different operation sets because their targets, adapters and extensions register different operations — not because core branches on target. This preserves the thin-core discipline from [ADR 005](ADR%20005%20-%20Thin%20Core%20Fat%20Targets.md). ## How matching works @@ -89,7 +89,7 @@ The ORM client surfaces this distinction by returning an `AnyExpression` (compos ## Interaction with other subsystems - **Codec registry** ([ADR 030](ADR%20030%20-%20Result%20decoding%20%26%20codecs%20registry.md)). Traits are codec metadata, owned by the codec registry. Operation matching reads traits from there; no new source of truth is introduced. -- **Adapter SPI** ([ADR 016](ADR%20016%20-%20Adapter%20SPI%20for%20Lowering.md)). Adapter runtime descriptors expose `queryOperations()` alongside the existing lowering surface. Contract emission picks up `types.queryOperationTypes` from descriptor meta, and trait-targeted operations flow through the same pipeline as codec-ID operations. +- **Adapter SPI** ([ADR 016](ADR%20016%20-%20Adapter%20SPI%20for%20Lowering.md)). Target, adapter and extension runtime descriptors expose `queryOperations()`; for adapters it sits alongside the existing lowering surface. Contract emission picks up `types.queryOperationTypes` from descriptor meta, and trait-targeted operations flow through the same pipeline as codec-ID operations. - **Contract extension encoding** ([ADR 105](ADR%20105%20-%20Contract%20extension%20encoding.md)) and [ADR 106](ADR%20106%20-%20Canonicalization%20for%20extensions.md). Trait-targeted argument specs serialize with `traits` as a string at the type level and as a string array at runtime. Canonicalization treats the `traits` field as opaque to the extension owner. - **Extension compatibility** ([ADR 017](ADR%20017%20-%20Extension%20Compatibility%20Policy.md)). Trait-targeting is additive. Existing codec-ID-targeted operations continue to work without changes. @@ -104,8 +104,8 @@ The ORM client surfaces this distinction by returning an `AnyExpression` (compos ### Positive -- Adapter-specific operations that apply to a capability (rather than one codec) can be registered once and automatically attach to every matching codec — including codecs added later by downstream extensions. -- Operations are reachable only on contracts whose adapter registered them. Capability-based operators no longer need runtime guards to reject calls on unsupported targets; the operation is absent from the type surface. +- Target-, adapter- or extension-specific operations that apply to a capability (rather than one codec) can be registered once and automatically attach to every matching codec — including codecs added later by downstream extensions. +- Operations are reachable only on contracts whose target, adapter or extension registered them. Capability-based operators no longer need runtime guards to reject calls on unsupported targets; the operation is absent from the type surface. - Boolean-returning extension operations are predicates by construction, composable with `and`/`or`/`not` without special-casing per operation. ### Trade-offs @@ -137,7 +137,7 @@ Doubles the surface — adapters, runtime registries, and type-level matchers al ## Open questions - Whether trait-targeted arguments should support OR-composition of required traits. Today `traits` is a single string at the type level and a conjunction at runtime. A more expressive combinator can be added later without breaking the current shape. -- How the emitter pipeline should validate that every adapter-declared `QueryOperationTypes` entry has a corresponding runtime descriptor registered. The two are wired through descriptor meta but not cross-checked at emission time. +- How the emitter pipeline should validate that every contributor-declared `QueryOperationTypes` entry has a corresponding runtime descriptor registered. The two are wired through descriptor meta but not cross-checked at emission time. ## Decision record diff --git a/docs/architecture docs/adrs/ADR 206 - Operations as TypeScript functions.md b/docs/architecture docs/adrs/ADR 206 - Operations as TypeScript functions.md index 40e2c67a82d9..86d66dd80c24 100644 --- a/docs/architecture docs/adrs/ADR 206 - Operations as TypeScript functions.md +++ b/docs/architecture docs/adrs/ADR 206 - Operations as TypeScript functions.md @@ -12,7 +12,7 @@ Authoring an operation also duplicates information. The runtime descriptor carri Operations are authored as TypeScript functions. The function's signature is the type-level surface. The function's body is the runtime — it receives user arguments (values or expressions), wraps them into parameter references with the appropriate codec via the `toExpr(value, codecId?)` helper, and returns an AST expression node produced by `buildOperation({ method, self, args, returns, lowering })`. Each parameter type is written either as `CodecExpression` when the argument is bound to an exact codec, or as `TraitExpression` when the argument is gated by capability traits; both union an `Expression` of the matching shape, a raw JS value from the codec-types map, and `null` when `Nullable` is true. Alongside the function each operation carries an `SqlOperationDescriptor` with three fields: `method`, an optional `self` dispatch hint naming either the codec identity or the trait set its first argument targets, and the `impl` function. The return codec, the lowering template, and the codecs of subsequent arguments live inside the AST node the function constructs, not on the descriptor. -Because both `CodecExpression` and `TraitExpression` take the contract's codec-types map as a type parameter, each adapter and extension exposes its operation contributions behind a factory generic over that map — `QueryOperationTypes` at the type level and a matching `QueryOperations()` function at the runtime level. The contract-assembly layer calls the factory once with the contract's concrete codec-types map. Every signature that reaches the SQL builder or the ORM client is already concrete; there is no lane-level projection step that rewrites authored types into contract-bound types. +Because both `CodecExpression` and `TraitExpression` take the contract's codec-types map as a type parameter, each target, adapter and extension exposes its operation contributions behind a factory generic over that map — `QueryOperationTypes` at the type level and a matching `QueryOperations()` function at the runtime level. The contract-assembly layer calls the factory once with the contract's concrete codec-types map. Every signature that reaches the SQL builder or the ORM client is already concrete; there is no lane-level projection step that rewrites authored types into contract-bound types. ## Design principles @@ -20,7 +20,7 @@ Because both `CodecExpression` and `TraitExpression` take the contract's codec-t 2. **Dispatch metadata is the minimum.** `SqlOperationDescriptor` carries `method`, an optional `self` hint, and the `impl` function. The return codec, the lowering spec, and the argument wrapping all live inside the function's body or on the AST node the function builds. 3. **`self` is the single source of truth for column-helper reachability.** The same hint is read by the ORM at runtime to index operations by codec and by the type system to decide which operations appear on a field. Because the two planes consume the same value, they cannot disagree. 4. **Argument wrapping belongs to the operation.** The dispatch layer does not know the codec of any argument and does not need to. An operation whose second argument is an exact textual codec calls `toExpr(arg, 'pg/text@1')` to wrap it; an operation whose argument is a raw numeric dimension is responsible for embedding it as a literal in the AST node. -5. **The codec-types map is bound at factory-call time.** Each adapter and extension exposes its operations behind a `QueryOperationTypes` factory generic over the contract's codec-types map. The contract-assembly layer instantiates the factory with the contract's concrete map. Authored signatures reach the SQL builder and ORM client already specialised to that contract; no mapped-type signature projection at the lane boundary is needed. +5. **The codec-types map is bound at factory-call time.** Each target, adapter and extension exposes its operations behind a `QueryOperationTypes` factory generic over the contract's codec-types map. The contract-assembly layer instantiates the factory with the contract's concrete map. Authored signatures reach the SQL builder and ORM client already specialised to that contract; no mapped-type signature projection at the lane boundary is needed. ## How matching works @@ -89,8 +89,8 @@ Anchors: [`query-operations.ts`](../../../packages/3-targets/3-targets/postgres/ ## Open questions -- Where exactly the factory boundary sits in the adapter SPI. The adapter runtime descriptor exposes a `queryOperations` slot whose shape is `() => readonly SqlOperationDescriptor[]`; today each adapter's thunk calls its `QueryOperations()` factory internally with an unconstrained `CT`. Threading the contract's concrete codec-types map through the slot remains an open design question. +- Where exactly the factory boundary sits in the contributor SPI. Target, adapter and extension runtime descriptors expose a `queryOperations` slot whose shape is `() => SqlOperationDescriptors`; today each contributor's thunk (the Postgres target's included) calls its `QueryOperations()` factory internally with an unconstrained `CT`, and the runtime's `createSqlExecutionStack` calls the slot with no type argument, so the binding described under Decision is nominal at runtime and concrete only in the emitted `contract.d.ts`, where the emitter instantiates each `QueryOperationTypes` alias with the contract's `CodecTypes`. Threading the contract's concrete codec-types map through the runtime slot remains an open design question. ## Decision record -Operations are authored as TypeScript functions whose parameters use `CodecExpression` or `TraitExpression`, accompanied by an `SqlOperationDescriptor` whose `self` field names the codec or trait the first argument targets. Adapters and extensions expose operation contributions behind a `QueryOperationTypes` factory which the contract-assembly layer instantiates once. The SQL builder surface flows each authored `impl` through unchanged; the ORM column helper reads the `self` hint to decide reachability. The framework validates only the `self` hint and dispatches by `method`; the runtime costs of argument wrapping (via `toExpr`), return-codec attachment, and lowering are paid by the authored function itself (via `buildOperation`). +Operations are authored as TypeScript functions whose parameters use `CodecExpression` or `TraitExpression`, accompanied by an `SqlOperationDescriptor` whose `self` field names the codec or trait the first argument targets. Targets, adapters and extensions expose operation contributions behind a `QueryOperationTypes` factory which the contract-assembly layer instantiates once. The SQL builder surface flows each authored `impl` through unchanged; the ORM column helper reads the `self` hint to decide reachability. The framework validates only the `self` hint and dispatches by `method`; the runtime costs of argument wrapping (via `toExpr`), return-codec attachment, and lowering are paid by the authored function itself (via `buildOperation`).