diff --git a/dev-packages/e2e-tests/test-applications/node-prisma-8/init.sql b/dev-packages/e2e-tests/test-applications/node-prisma-8/init.sql index 655d447ca485..ac93565c65b2 100644 --- a/dev-packages/e2e-tests/test-applications/node-prisma-8/init.sql +++ b/dev-packages/e2e-tests/test-applications/node-prisma-8/init.sql @@ -34,31 +34,31 @@ CREATE TABLE prisma_contract.marker ( meta jsonb DEFAULT '{}'::jsonb NOT NULL, invariants text[] DEFAULT '{}'::text[] NOT NULL ); -CREATE TABLE public."user" ( +CREATE TABLE public."User" ( email text NOT NULL, id integer NOT NULL, name text ); -CREATE SEQUENCE public.user_id_seq +CREATE SEQUENCE public."User_id_seq" AS integer START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; -ALTER SEQUENCE public.user_id_seq OWNED BY public."user".id; +ALTER SEQUENCE public."User_id_seq" OWNED BY public."User".id; ALTER TABLE ONLY prisma_contract.ledger ALTER COLUMN id SET DEFAULT nextval('prisma_contract.ledger_id_seq'::regclass); -ALTER TABLE ONLY public."user" ALTER COLUMN id SET DEFAULT nextval('public.user_id_seq'::regclass); -INSERT INTO prisma_contract.contract VALUES ('f4e1954fd8bed87828d13c3f1a02164dc9796ef1af76ed6f98184c01263169c5', '2026-09-09 09:15:28.369559+00', '{"meta": {}, "roots": {"user": {"model": "User", "namespace": "public"}}, "domain": {"namespaces": {"public": {"models": {"User": {"fields": {"id": {"type": {"kind": "scalar", "codecId": "pg/int4@1"}, "nullable": false}, "name": {"type": {"kind": "scalar", "codecId": "pg/text@1"}, "nullable": true}, "email": {"type": {"kind": "scalar", "codecId": "pg/text@1"}, "nullable": false}}, "storage": {"table": "user", "fields": {"id": {"column": "id"}, "name": {"column": "name"}, "email": {"column": "email"}}, "namespaceId": "public"}, "relations": {}}}}}}, "target": "postgres", "storage": {"namespaces": {"public": {"id": "public", "entries": {"table": {"user": {"columns": {"id": {"codecId": "pg/int4@1", "default": {"kind": "function", "expression": "autoincrement()"}, "nullable": false, "nativeType": "int4"}, "name": {"codecId": "pg/text@1", "nullable": true, "nativeType": "text"}, "email": {"codecId": "pg/text@1", "nullable": false, "nativeType": "text"}}, "indexes": [], "uniques": [{"columns": ["email"]}], "primaryKey": {"columns": ["id"]}, "foreignKeys": []}}}}}, "storageHash": "f4e1954fd8bed87828d13c3f1a02164dc9796ef1af76ed6f98184c01263169c5"}, "extensions": {}, "profileHash": "3916f444a8a17ad749191acf9e08dad97d1a327b88c2f1d45d12f240296aa8b2", "capabilities": {"sql": {"enums": true, "lateral": true, "returning": true, "scalarList": true, "checkConstraint": true, "defaultInInsert": true}, "postgres": {"limit": true, "jsonAgg": true, "lateral": true, "orderBy": true, "returning": true, "distinctOn": true}}, "targetFamily": "sql"}'); -INSERT INTO prisma_contract.ledger VALUES (1, '2026-09-09 09:15:28.369559+00', 'app', '', 'f4e1954fd8bed87828d13c3f1a02164dc9796ef1af76ed6f98184c01263169c5', '', NULL, 'f4e1954fd8bed87828d13c3f1a02164dc9796ef1af76ed6f98184c01263169c5', NULL, '[{"id": "table.user", "label": "Create table \"user\"", "target": {"id": "postgres", "details": {"name": "user", "schema": "public", "objectType": "table"}}, "execute": [{"sql": "CREATE TABLE \"public\".\"user\" (\n \"email\" text NOT NULL,\n \"id\" SERIAL NOT NULL,\n \"name\" text,\n PRIMARY KEY (\"id\")\n)", "params": [], "description": "create table \"user\""}], "summary": "Creates table \"user\"", "precheck": [{"sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", "params": ["\"public\".\"user\""], "description": "ensure table \"user\" does not exist"}], "postcheck": [{"sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", "params": ["\"public\".\"user\""], "description": "verify table \"user\" exists"}], "operationClass": "additive"}, {"id": "unique.user.user_email_key", "label": "Add unique constraint on \"user\" (email)", "target": {"id": "postgres", "details": {"name": "user_email_key", "table": "user", "schema": "public", "objectType": "unique"}}, "execute": [{"sql": "ALTER TABLE \"public\".\"user\" ADD CONSTRAINT \"user_email_key\" UNIQUE (\"email\")", "description": "add unique constraint \"user_email_key\""}], "precheck": [{"sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", "params": ["user_email_key", "public", "\"public\".\"user\""], "description": "ensure constraint \"user_email_key\" does not exist"}], "postcheck": [{"sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", "params": ["user_email_key", "public", "\"public\".\"user\""], "description": "verify constraint \"user_email_key\" exists"}], "operationClass": "additive"}]'); -INSERT INTO prisma_contract.marker VALUES ('app', 'f4e1954fd8bed87828d13c3f1a02164dc9796ef1af76ed6f98184c01263169c5', '3916f444a8a17ad749191acf9e08dad97d1a327b88c2f1d45d12f240296aa8b2', NULL, NULL, '2026-09-09 09:15:28.369559+00', NULL, '{}', '{}'); +ALTER TABLE ONLY public."User" ALTER COLUMN id SET DEFAULT nextval('public."User_id_seq"'::regclass); +INSERT INTO prisma_contract.contract VALUES ('a62d15a094e80be7b342d75e0538935972b9699c76dabb5339940dd50d17a889', '2026-10-08 14:56:22.624077+00', '{"meta": {}, "roots": {"User": {"model": "User", "namespace": "public"}}, "domain": {"namespaces": {"public": {"models": {"User": {"fields": {"id": {"many": false, "type": {"kind": "scalar", "codecId": "pg/int4@1"}, "nullable": false}, "name": {"many": false, "type": {"kind": "scalar", "codecId": "pg/text@1"}, "nullable": true}, "email": {"many": false, "type": {"kind": "scalar", "codecId": "pg/text@1"}, "nullable": false}}, "storage": {"table": "User", "fields": {"id": {"column": "id"}, "name": {"column": "name"}, "email": {"column": "email"}}, "namespaceId": "public"}, "relations": {}}}}}}, "target": "postgres", "storage": {"namespaces": {"public": {"id": "public", "entries": {"table": {"User": {"columns": {"id": {"many": false, "codecId": "pg/int4@1", "default": {"kind": "function", "expression": "autoincrement()"}, "dataType": "pg/int4", "nullable": false}, "name": {"many": false, "codecId": "pg/text@1", "dataType": "pg/text", "nullable": true}, "email": {"many": false, "codecId": "pg/text@1", "dataType": "pg/text", "nullable": false}}, "indexes": [], "uniques": [{"columns": ["email"]}], "primaryKey": {"columns": ["id"]}, "foreignKeys": []}}}}}, "storageHash": "a62d15a094e80be7b342d75e0538935972b9699c76dabb5339940dd50d17a889"}, "extensions": {}, "profileHash": "3916f444a8a17ad749191acf9e08dad97d1a327b88c2f1d45d12f240296aa8b2", "capabilities": {"sql": {"enums": true, "lockOf": true, "lateral": true, "forShare": true, "forUpdate": true, "returning": true, "lockNowait": true, "scalarList": true, "lockSkipLocked": true, "checkConstraint": true, "defaultInInsert": true, "insertOnConflictSkip": true, "insertOnConflictWithoutTarget": true}, "postgres": {"limit": true, "jsonAgg": true, "lateral": true, "orderBy": true, "returning": true, "distinctOn": true, "forKeyShare": true, "forNoKeyUpdate": true}}, "targetFamily": "sql"}'); +INSERT INTO prisma_contract.ledger VALUES (1, '2026-10-08 14:56:22.624077+00', 'app', '', 'a62d15a094e80be7b342d75e0538935972b9699c76dabb5339940dd50d17a889', '', NULL, 'a62d15a094e80be7b342d75e0538935972b9699c76dabb5339940dd50d17a889', NULL, '[{"id": "table.User", "label": "Create table \"User\"", "target": {"id": "postgres", "details": {"name": "User", "schema": "public", "objectType": "table"}}, "execute": [{"sql": "CREATE TABLE \"public\".\"User\" (\n \"email\" text NOT NULL,\n \"id\" SERIAL NOT NULL,\n \"name\" text,\n PRIMARY KEY (\"id\")\n)", "params": [], "description": "create table \"User\""}], "summary": "Creates table \"User\"", "precheck": [{"sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", "params": ["\"public\".\"User\""], "description": "ensure table \"User\" does not exist"}], "postcheck": [{"sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", "params": ["\"public\".\"User\""], "description": "verify table \"User\" exists"}], "operationClass": "additive"}, {"id": "unique.User.User_email_key", "label": "Add unique constraint on \"User\" (email)", "target": {"id": "postgres", "details": {"name": "User_email_key", "table": "User", "schema": "public", "objectType": "unique"}}, "execute": [{"sql": "ALTER TABLE \"public\".\"User\" ADD CONSTRAINT \"User_email_key\" UNIQUE (\"email\")", "description": "add unique constraint \"User_email_key\""}], "precheck": [{"sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", "params": ["User_email_key", "public", "\"public\".\"User\""], "description": "ensure constraint \"User_email_key\" does not exist"}], "postcheck": [{"sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", "params": ["User_email_key", "public", "\"public\".\"User\""], "description": "verify constraint \"User_email_key\" exists"}], "operationClass": "additive"}]'); +INSERT INTO prisma_contract.marker VALUES ('app', 'a62d15a094e80be7b342d75e0538935972b9699c76dabb5339940dd50d17a889', '3916f444a8a17ad749191acf9e08dad97d1a327b88c2f1d45d12f240296aa8b2', NULL, NULL, '2026-10-08 14:56:22.624077+00', NULL, '{}', '{}'); ALTER TABLE ONLY prisma_contract.contract ADD CONSTRAINT contract_pkey PRIMARY KEY (core_hash); ALTER TABLE ONLY prisma_contract.ledger ADD CONSTRAINT ledger_pkey PRIMARY KEY (id); ALTER TABLE ONLY prisma_contract.marker ADD CONSTRAINT marker_pkey PRIMARY KEY (space); -ALTER TABLE ONLY public."user" - ADD CONSTRAINT user_email_key UNIQUE (email); -ALTER TABLE ONLY public."user" - ADD CONSTRAINT user_pkey PRIMARY KEY (id); +ALTER TABLE ONLY public."User" + ADD CONSTRAINT "User_email_key" UNIQUE (email); +ALTER TABLE ONLY public."User" + ADD CONSTRAINT "User_pkey" PRIMARY KEY (id); diff --git a/dev-packages/e2e-tests/test-applications/node-prisma-8/package.json b/dev-packages/e2e-tests/test-applications/node-prisma-8/package.json index a6e8bb692e57..6b42d3ee2e7c 100644 --- a/dev-packages/e2e-tests/test-applications/node-prisma-8/package.json +++ b/dev-packages/e2e-tests/test-applications/node-prisma-8/package.json @@ -12,7 +12,7 @@ "test:assert": "pnpm test" }, "dependencies": { - "@prisma/orm-postgres": "8.0.0-rc.8", + "@prisma/orm-postgres": "8.0.0-rc.17", "@sentry/node": "file:../../packed/sentry-node-packed.tgz", "@types/express": "^4.17.21", "@types/node": "^20.19.0", diff --git a/dev-packages/e2e-tests/test-applications/node-prisma-8/src/prisma/contract.d.ts b/dev-packages/e2e-tests/test-applications/node-prisma-8/src/prisma/contract.d.ts index 010a73846882..ecfad3dac136 100644 --- a/dev-packages/e2e-tests/test-applications/node-prisma-8/src/prisma/contract.d.ts +++ b/dev-packages/e2e-tests/test-applications/node-prisma-8/src/prisma/contract.d.ts @@ -1,26 +1,14 @@ // ⚠️ 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, - CodecTypes as PgTypes, - Interval, - JsonValue, - Numeric, - Time, - TimeString, - Timestamp, - TimestampString, - Timestamptz, - TimestamptzString, - Timetz, - VarBit, - Varchar, -} from '@prisma/orm-postgres/target/codec-types'; +import type { CodecTypes as PgTypes } from '@prisma/orm-postgres/target/codec-types'; +import type { QueryOperationTypes as PgTargetQueryOps } from '@prisma/orm-postgres/target/operation-types'; -import type { ContractWithTypeMaps, TypeMaps as TypeMapsType } from '@prisma/orm-postgres/family-contract/types'; +import type { + ContractWithTypeMaps, + RelationKeys, + TypeMaps as TypeMapsType, +} from '@prisma/orm-postgres/family-contract/types'; import type { Contract as ContractType, ExecutionHashBase, @@ -29,13 +17,13 @@ import type { StorageHashBase, } from '@prisma/orm-postgres/contract/types'; -export type StorageHash = StorageHashBase<'f4e1954fd8bed87828d13c3f1a02164dc9796ef1af76ed6f98184c01263169c5'>; +export type StorageHash = StorageHashBase<'a62d15a094e80be7b342d75e0538935972b9699c76dabb5339940dd50d17a889'>; export type ExecutionHash = ExecutionHashBase; export type ProfileHash = ProfileHashBase<'3916f444a8a17ad749191acf9e08dad97d1a327b88c2f1d45d12f240296aa8b2'>; export type CodecTypes = PgTypes; export type LaneCodecTypes = CodecTypes; -export type QueryOperationTypes = PgAdapterQueryOps; +export type QueryOperationTypes = PgTargetQueryOps; export type AggregateTypes = { readonly avg: { readonly byCodec: { @@ -113,6 +101,10 @@ export type AggregateTypes = { readonly output: 'pg/timestamp-temporal@1'; readonly nullable: true; }; + readonly 'pg/timestamptz-date@1': { + readonly output: 'pg/timestamptz-date@1'; + readonly nullable: true; + }; readonly 'pg/timestamptz-string@1': { readonly output: 'pg/timestamptz-string@1'; readonly nullable: true; @@ -169,6 +161,10 @@ export type AggregateTypes = { readonly output: 'pg/timestamp-temporal@1'; readonly nullable: true; }; + readonly 'pg/timestamptz-date@1': { + readonly output: 'pg/timestamptz-date@1'; + readonly nullable: true; + }; readonly 'pg/timestamptz-string@1': { readonly output: 'pg/timestamptz-string@1'; readonly nullable: true; @@ -236,8 +232,8 @@ type DefaultLiteralValue = CodecId extends keyo export type FieldOutputTypes = { readonly public: { readonly User: { - readonly id: CodecTypes['pg/int4@1']['output']; readonly email: CodecTypes['pg/text@1']['output']; + readonly id: CodecTypes['pg/int4@1']['output']; readonly name: CodecTypes['pg/text@1']['output'] | null; }; }; @@ -245,15 +241,15 @@ export type FieldOutputTypes = { export type FieldInputTypes = { readonly public: { readonly User: { - readonly id: CodecTypes['pg/int4@1']['input']; readonly email: CodecTypes['pg/text@1']['input']; + readonly id: CodecTypes['pg/int4@1']['input']; readonly name: CodecTypes['pg/text@1']['input'] | null; }; }; }; export type StorageColumnTypes = { readonly public: { - readonly user: { + readonly User: { readonly email: CodecTypes['pg/text@1']['output']; readonly id: CodecTypes['pg/int4@1']['output']; readonly name: CodecTypes['pg/text@1']['output'] | null; @@ -262,13 +258,29 @@ export type StorageColumnTypes = { }; export type StorageColumnInputTypes = { readonly public: { - readonly user: { + readonly User: { readonly email: CodecTypes['pg/text@1']['input']; readonly id: CodecTypes['pg/int4@1']['input']; readonly name: CodecTypes['pg/text@1']['input'] | null; }; }; }; + +export namespace Models { + export type public_User = { + email: CodecTypes['pg/text@1']['output']; + id: CodecTypes['pg/int4@1']['output']; + name: CodecTypes['pg/text@1']['output'] | null; + readonly [RelationKeys]?: never; + }; +} + +export declare const models: { + public: { + User: Models.public_User; + }; +}; + export type TypeMaps = TypeMapsType< CodecTypes, QueryOperationTypes, @@ -287,26 +299,29 @@ type ContractBase = Omit< readonly kind: 'postgres-schema'; readonly entries: { readonly table: { - readonly user: { + readonly User: { columns: { + readonly email: { + readonly dataType: 'pg/text'; + readonly codecId: 'pg/text@1'; + readonly nullable: false; + readonly many: false; + }; readonly id: { - readonly nativeType: 'int4'; + readonly dataType: 'pg/int4'; readonly codecId: 'pg/int4@1'; readonly nullable: false; readonly default: { readonly kind: 'function'; readonly expression: 'autoincrement()'; }; - }; - readonly email: { - readonly nativeType: 'text'; - readonly codecId: 'pg/text@1'; - readonly nullable: false; + readonly many: false; }; readonly name: { - readonly nativeType: 'text'; + readonly dataType: 'pg/text'; readonly codecId: 'pg/text@1'; readonly nullable: true; + readonly many: false; }; }; primaryKey: { readonly columns: readonly ['id'] }; @@ -325,7 +340,7 @@ type ContractBase = Omit< readonly target: 'postgres'; readonly targetFamily: 'sql'; readonly roots: { - readonly user: { readonly namespace: 'public' & NamespaceId; readonly model: 'User' }; + readonly User: { readonly namespace: 'public' & NamespaceId; readonly model: 'User' }; }; readonly domain: { readonly namespaces: { @@ -333,14 +348,14 @@ type ContractBase = Omit< readonly models: { readonly User: { readonly fields: { - readonly id: { - readonly nullable: false; - readonly type: { readonly kind: 'scalar'; readonly codecId: 'pg/int4@1' }; - }; readonly email: { readonly nullable: false; readonly type: { readonly kind: 'scalar'; readonly codecId: 'pg/text@1' }; }; + readonly id: { + readonly nullable: false; + readonly type: { readonly kind: 'scalar'; readonly codecId: 'pg/int4@1' }; + }; readonly name: { readonly nullable: true; readonly type: { readonly kind: 'scalar'; readonly codecId: 'pg/text@1' }; @@ -348,11 +363,11 @@ type ContractBase = Omit< }; readonly relations: Record; readonly storage: { - readonly table: 'user'; + readonly table: 'User'; readonly namespaceId: 'public'; readonly fields: { - readonly id: { readonly column: 'id' }; readonly email: { readonly column: 'email' }; + readonly id: { readonly column: 'id' }; readonly name: { readonly column: 'name' }; }; }; @@ -364,6 +379,8 @@ type ContractBase = Omit< readonly capabilities: { readonly postgres: { readonly distinctOn: true; + readonly forKeyShare: true; + readonly forNoKeyUpdate: true; readonly jsonAgg: true; readonly lateral: true; readonly limit: true; @@ -374,7 +391,14 @@ type ContractBase = Omit< readonly checkConstraint: true; readonly defaultInInsert: true; readonly enums: true; + readonly forShare: true; + readonly forUpdate: true; + readonly insertOnConflictSkip: true; + readonly insertOnConflictWithoutTarget: true; readonly lateral: true; + readonly lockNowait: true; + readonly lockOf: true; + readonly lockSkipLocked: true; readonly returning: true; readonly scalarList: true; }; diff --git a/dev-packages/e2e-tests/test-applications/node-prisma-8/src/prisma/contract.json b/dev-packages/e2e-tests/test-applications/node-prisma-8/src/prisma/contract.json index 3b9090e28776..51b72b543a0b 100644 --- a/dev-packages/e2e-tests/test-applications/node-prisma-8/src/prisma/contract.json +++ b/dev-packages/e2e-tests/test-applications/node-prisma-8/src/prisma/contract.json @@ -4,7 +4,7 @@ "target": "postgres", "profileHash": "3916f444a8a17ad749191acf9e08dad97d1a327b88c2f1d45d12f240296aa8b2", "roots": { - "user": { + "User": { "model": "User", "namespace": "public" } @@ -51,7 +51,7 @@ } }, "namespaceId": "public", - "table": "user" + "table": "User" } } } @@ -63,25 +63,25 @@ "public": { "entries": { "table": { - "user": { + "User": { "columns": { "email": { "codecId": "pg/text@1", - "nativeType": "text", + "dataType": "pg/text", "nullable": false }, "id": { "codecId": "pg/int4@1", + "dataType": "pg/int4", "default": { "expression": "autoincrement()", "kind": "function" }, - "nativeType": "int4", "nullable": false }, "name": { "codecId": "pg/text@1", - "nativeType": "text", + "dataType": "pg/text", "nullable": true } }, @@ -102,11 +102,13 @@ "kind": "postgres-schema" } }, - "storageHash": "f4e1954fd8bed87828d13c3f1a02164dc9796ef1af76ed6f98184c01263169c5" + "storageHash": "a62d15a094e80be7b342d75e0538935972b9699c76dabb5339940dd50d17a889" }, "capabilities": { "postgres": { "distinctOn": true, + "forKeyShare": true, + "forNoKeyUpdate": true, "jsonAgg": true, "lateral": true, "limit": true, @@ -117,7 +119,14 @@ "checkConstraint": true, "defaultInInsert": true, "enums": true, + "forShare": true, + "forUpdate": true, + "insertOnConflictSkip": true, + "insertOnConflictWithoutTarget": true, "lateral": true, + "lockNowait": true, + "lockOf": true, + "lockSkipLocked": true, "returning": true, "scalarList": true } diff --git a/dev-packages/e2e-tests/test-applications/node-prisma-8/tests/prisma.test.ts b/dev-packages/e2e-tests/test-applications/node-prisma-8/tests/prisma.test.ts index 81cc629a2ff8..4f581ff6d9ca 100644 --- a/dev-packages/e2e-tests/test-applications/node-prisma-8/tests/prisma.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-prisma-8/tests/prisma.test.ts @@ -43,7 +43,7 @@ test('Prisma 8 ORM calls emit operation spans with the pg queries nested underne 'sentry.origin': { value: 'auto.db.prisma', type: 'string' }, 'sentry.op': { value: 'db', type: 'string' }, 'db.operation.name': { value: span.attributes['method']?.value, type: 'string' }, - 'db.collection.name': { value: 'user', type: 'string' }, + 'db.collection.name': { value: 'User', type: 'string' }, model: { value: 'User', type: 'string' }, name: { value: `User.${span.attributes['method']?.value}`, type: 'string' }, }); @@ -62,11 +62,11 @@ test('Prisma 8 ORM calls emit operation spans with the pg queries nested underne .map(span => span.attributes['db.query.text']?.value); }; expect(queriesUnder('create')).toEqual( - expect.arrayContaining([expect.stringMatching(/^INSERT INTO "public"\."user" /)]), + expect.arrayContaining([expect.stringMatching(/^INSERT INTO "public"\."User" /)]), ); - expect(queriesUnder('all')).toEqual([expect.stringMatching(/^SELECT .* FROM "public"\."user"$/)]); + expect(queriesUnder('all')).toEqual([expect.stringMatching(/^SELECT .* FROM "public"\."User"$/)]); expect(queriesUnder('delete')).toEqual( - expect.arrayContaining([expect.stringMatching(/^DELETE FROM "public"\."user" /)]), + expect.arrayContaining([expect.stringMatching(/^DELETE FROM "public"\."User" /)]), ); const dbSpans = spans.filter(span => getSpanOp(span) === 'db' && span.attributes['db.query.text']?.value); diff --git a/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v8/prisma/contract.json b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v8/prisma/contract.json index 3b9090e28776..51b72b543a0b 100644 --- a/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v8/prisma/contract.json +++ b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v8/prisma/contract.json @@ -4,7 +4,7 @@ "target": "postgres", "profileHash": "3916f444a8a17ad749191acf9e08dad97d1a327b88c2f1d45d12f240296aa8b2", "roots": { - "user": { + "User": { "model": "User", "namespace": "public" } @@ -51,7 +51,7 @@ } }, "namespaceId": "public", - "table": "user" + "table": "User" } } } @@ -63,25 +63,25 @@ "public": { "entries": { "table": { - "user": { + "User": { "columns": { "email": { "codecId": "pg/text@1", - "nativeType": "text", + "dataType": "pg/text", "nullable": false }, "id": { "codecId": "pg/int4@1", + "dataType": "pg/int4", "default": { "expression": "autoincrement()", "kind": "function" }, - "nativeType": "int4", "nullable": false }, "name": { "codecId": "pg/text@1", - "nativeType": "text", + "dataType": "pg/text", "nullable": true } }, @@ -102,11 +102,13 @@ "kind": "postgres-schema" } }, - "storageHash": "f4e1954fd8bed87828d13c3f1a02164dc9796ef1af76ed6f98184c01263169c5" + "storageHash": "a62d15a094e80be7b342d75e0538935972b9699c76dabb5339940dd50d17a889" }, "capabilities": { "postgres": { "distinctOn": true, + "forKeyShare": true, + "forNoKeyUpdate": true, "jsonAgg": true, "lateral": true, "limit": true, @@ -117,7 +119,14 @@ "checkConstraint": true, "defaultInInsert": true, "enums": true, + "forShare": true, + "forUpdate": true, + "insertOnConflictSkip": true, + "insertOnConflictWithoutTarget": true, "lateral": true, + "lockNowait": true, + "lockOf": true, + "lockSkipLocked": true, "returning": true, "scalarList": true } diff --git a/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v8/prisma/init.sql b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v8/prisma/init.sql index 655d447ca485..ac93565c65b2 100644 --- a/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v8/prisma/init.sql +++ b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v8/prisma/init.sql @@ -34,31 +34,31 @@ CREATE TABLE prisma_contract.marker ( meta jsonb DEFAULT '{}'::jsonb NOT NULL, invariants text[] DEFAULT '{}'::text[] NOT NULL ); -CREATE TABLE public."user" ( +CREATE TABLE public."User" ( email text NOT NULL, id integer NOT NULL, name text ); -CREATE SEQUENCE public.user_id_seq +CREATE SEQUENCE public."User_id_seq" AS integer START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; -ALTER SEQUENCE public.user_id_seq OWNED BY public."user".id; +ALTER SEQUENCE public."User_id_seq" OWNED BY public."User".id; ALTER TABLE ONLY prisma_contract.ledger ALTER COLUMN id SET DEFAULT nextval('prisma_contract.ledger_id_seq'::regclass); -ALTER TABLE ONLY public."user" ALTER COLUMN id SET DEFAULT nextval('public.user_id_seq'::regclass); -INSERT INTO prisma_contract.contract VALUES ('f4e1954fd8bed87828d13c3f1a02164dc9796ef1af76ed6f98184c01263169c5', '2026-09-09 09:15:28.369559+00', '{"meta": {}, "roots": {"user": {"model": "User", "namespace": "public"}}, "domain": {"namespaces": {"public": {"models": {"User": {"fields": {"id": {"type": {"kind": "scalar", "codecId": "pg/int4@1"}, "nullable": false}, "name": {"type": {"kind": "scalar", "codecId": "pg/text@1"}, "nullable": true}, "email": {"type": {"kind": "scalar", "codecId": "pg/text@1"}, "nullable": false}}, "storage": {"table": "user", "fields": {"id": {"column": "id"}, "name": {"column": "name"}, "email": {"column": "email"}}, "namespaceId": "public"}, "relations": {}}}}}}, "target": "postgres", "storage": {"namespaces": {"public": {"id": "public", "entries": {"table": {"user": {"columns": {"id": {"codecId": "pg/int4@1", "default": {"kind": "function", "expression": "autoincrement()"}, "nullable": false, "nativeType": "int4"}, "name": {"codecId": "pg/text@1", "nullable": true, "nativeType": "text"}, "email": {"codecId": "pg/text@1", "nullable": false, "nativeType": "text"}}, "indexes": [], "uniques": [{"columns": ["email"]}], "primaryKey": {"columns": ["id"]}, "foreignKeys": []}}}}}, "storageHash": "f4e1954fd8bed87828d13c3f1a02164dc9796ef1af76ed6f98184c01263169c5"}, "extensions": {}, "profileHash": "3916f444a8a17ad749191acf9e08dad97d1a327b88c2f1d45d12f240296aa8b2", "capabilities": {"sql": {"enums": true, "lateral": true, "returning": true, "scalarList": true, "checkConstraint": true, "defaultInInsert": true}, "postgres": {"limit": true, "jsonAgg": true, "lateral": true, "orderBy": true, "returning": true, "distinctOn": true}}, "targetFamily": "sql"}'); -INSERT INTO prisma_contract.ledger VALUES (1, '2026-09-09 09:15:28.369559+00', 'app', '', 'f4e1954fd8bed87828d13c3f1a02164dc9796ef1af76ed6f98184c01263169c5', '', NULL, 'f4e1954fd8bed87828d13c3f1a02164dc9796ef1af76ed6f98184c01263169c5', NULL, '[{"id": "table.user", "label": "Create table \"user\"", "target": {"id": "postgres", "details": {"name": "user", "schema": "public", "objectType": "table"}}, "execute": [{"sql": "CREATE TABLE \"public\".\"user\" (\n \"email\" text NOT NULL,\n \"id\" SERIAL NOT NULL,\n \"name\" text,\n PRIMARY KEY (\"id\")\n)", "params": [], "description": "create table \"user\""}], "summary": "Creates table \"user\"", "precheck": [{"sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", "params": ["\"public\".\"user\""], "description": "ensure table \"user\" does not exist"}], "postcheck": [{"sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", "params": ["\"public\".\"user\""], "description": "verify table \"user\" exists"}], "operationClass": "additive"}, {"id": "unique.user.user_email_key", "label": "Add unique constraint on \"user\" (email)", "target": {"id": "postgres", "details": {"name": "user_email_key", "table": "user", "schema": "public", "objectType": "unique"}}, "execute": [{"sql": "ALTER TABLE \"public\".\"user\" ADD CONSTRAINT \"user_email_key\" UNIQUE (\"email\")", "description": "add unique constraint \"user_email_key\""}], "precheck": [{"sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", "params": ["user_email_key", "public", "\"public\".\"user\""], "description": "ensure constraint \"user_email_key\" does not exist"}], "postcheck": [{"sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", "params": ["user_email_key", "public", "\"public\".\"user\""], "description": "verify constraint \"user_email_key\" exists"}], "operationClass": "additive"}]'); -INSERT INTO prisma_contract.marker VALUES ('app', 'f4e1954fd8bed87828d13c3f1a02164dc9796ef1af76ed6f98184c01263169c5', '3916f444a8a17ad749191acf9e08dad97d1a327b88c2f1d45d12f240296aa8b2', NULL, NULL, '2026-09-09 09:15:28.369559+00', NULL, '{}', '{}'); +ALTER TABLE ONLY public."User" ALTER COLUMN id SET DEFAULT nextval('public."User_id_seq"'::regclass); +INSERT INTO prisma_contract.contract VALUES ('a62d15a094e80be7b342d75e0538935972b9699c76dabb5339940dd50d17a889', '2026-10-08 14:56:22.624077+00', '{"meta": {}, "roots": {"User": {"model": "User", "namespace": "public"}}, "domain": {"namespaces": {"public": {"models": {"User": {"fields": {"id": {"many": false, "type": {"kind": "scalar", "codecId": "pg/int4@1"}, "nullable": false}, "name": {"many": false, "type": {"kind": "scalar", "codecId": "pg/text@1"}, "nullable": true}, "email": {"many": false, "type": {"kind": "scalar", "codecId": "pg/text@1"}, "nullable": false}}, "storage": {"table": "User", "fields": {"id": {"column": "id"}, "name": {"column": "name"}, "email": {"column": "email"}}, "namespaceId": "public"}, "relations": {}}}}}}, "target": "postgres", "storage": {"namespaces": {"public": {"id": "public", "entries": {"table": {"User": {"columns": {"id": {"many": false, "codecId": "pg/int4@1", "default": {"kind": "function", "expression": "autoincrement()"}, "dataType": "pg/int4", "nullable": false}, "name": {"many": false, "codecId": "pg/text@1", "dataType": "pg/text", "nullable": true}, "email": {"many": false, "codecId": "pg/text@1", "dataType": "pg/text", "nullable": false}}, "indexes": [], "uniques": [{"columns": ["email"]}], "primaryKey": {"columns": ["id"]}, "foreignKeys": []}}}}}, "storageHash": "a62d15a094e80be7b342d75e0538935972b9699c76dabb5339940dd50d17a889"}, "extensions": {}, "profileHash": "3916f444a8a17ad749191acf9e08dad97d1a327b88c2f1d45d12f240296aa8b2", "capabilities": {"sql": {"enums": true, "lockOf": true, "lateral": true, "forShare": true, "forUpdate": true, "returning": true, "lockNowait": true, "scalarList": true, "lockSkipLocked": true, "checkConstraint": true, "defaultInInsert": true, "insertOnConflictSkip": true, "insertOnConflictWithoutTarget": true}, "postgres": {"limit": true, "jsonAgg": true, "lateral": true, "orderBy": true, "returning": true, "distinctOn": true, "forKeyShare": true, "forNoKeyUpdate": true}}, "targetFamily": "sql"}'); +INSERT INTO prisma_contract.ledger VALUES (1, '2026-10-08 14:56:22.624077+00', 'app', '', 'a62d15a094e80be7b342d75e0538935972b9699c76dabb5339940dd50d17a889', '', NULL, 'a62d15a094e80be7b342d75e0538935972b9699c76dabb5339940dd50d17a889', NULL, '[{"id": "table.User", "label": "Create table \"User\"", "target": {"id": "postgres", "details": {"name": "User", "schema": "public", "objectType": "table"}}, "execute": [{"sql": "CREATE TABLE \"public\".\"User\" (\n \"email\" text NOT NULL,\n \"id\" SERIAL NOT NULL,\n \"name\" text,\n PRIMARY KEY (\"id\")\n)", "params": [], "description": "create table \"User\""}], "summary": "Creates table \"User\"", "precheck": [{"sql": "SELECT (to_regclass($1)) IS NULL AS \"result\"", "params": ["\"public\".\"User\""], "description": "ensure table \"User\" does not exist"}], "postcheck": [{"sql": "SELECT (to_regclass($1)) IS NOT NULL AS \"result\"", "params": ["\"public\".\"User\""], "description": "verify table \"User\" exists"}], "operationClass": "additive"}, {"id": "unique.User.User_email_key", "label": "Add unique constraint on \"User\" (email)", "target": {"id": "postgres", "details": {"name": "User_email_key", "table": "User", "schema": "public", "objectType": "unique"}}, "execute": [{"sql": "ALTER TABLE \"public\".\"User\" ADD CONSTRAINT \"User_email_key\" UNIQUE (\"email\")", "description": "add unique constraint \"User_email_key\""}], "precheck": [{"sql": "SELECT NOT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", "params": ["User_email_key", "public", "\"public\".\"User\""], "description": "ensure constraint \"User_email_key\" does not exist"}], "postcheck": [{"sql": "SELECT EXISTS (SELECT 1 AS \"one\" FROM \"pg_constraint\" AS \"c\" INNER JOIN \"pg_namespace\" AS \"n\" ON \"n\".\"oid\" = \"c\".\"connamespace\" WHERE (\"c\".\"conname\" = $1 AND \"n\".\"nspname\" = $2 AND \"c\".\"conrelid\" = to_regclass($3))) AS \"result\"", "params": ["User_email_key", "public", "\"public\".\"User\""], "description": "verify constraint \"User_email_key\" exists"}], "operationClass": "additive"}]'); +INSERT INTO prisma_contract.marker VALUES ('app', 'a62d15a094e80be7b342d75e0538935972b9699c76dabb5339940dd50d17a889', '3916f444a8a17ad749191acf9e08dad97d1a327b88c2f1d45d12f240296aa8b2', NULL, NULL, '2026-10-08 14:56:22.624077+00', NULL, '{}', '{}'); ALTER TABLE ONLY prisma_contract.contract ADD CONSTRAINT contract_pkey PRIMARY KEY (core_hash); ALTER TABLE ONLY prisma_contract.ledger ADD CONSTRAINT ledger_pkey PRIMARY KEY (id); ALTER TABLE ONLY prisma_contract.marker ADD CONSTRAINT marker_pkey PRIMARY KEY (space); -ALTER TABLE ONLY public."user" - ADD CONSTRAINT user_email_key UNIQUE (email); -ALTER TABLE ONLY public."user" - ADD CONSTRAINT user_pkey PRIMARY KEY (id); +ALTER TABLE ONLY public."User" + ADD CONSTRAINT "User_email_key" UNIQUE (email); +ALTER TABLE ONLY public."User" + ADD CONSTRAINT "User_pkey" PRIMARY KEY (id); diff --git a/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v8/test.ts b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v8/test.ts index e27358581b28..d7adfe06da27 100644 --- a/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v8/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/prisma-orm-v8/test.ts @@ -18,7 +18,7 @@ function getQuerySpans(container: SerializedStreamedSpanContainer): SerializedSt item => item.attributes['sentry.origin']?.value === 'auto.db.postgres' && item.attributes['db.query.text']?.value, ); expect(querySpans.map(span => span.name)).toEqual( - expect.arrayContaining(['INSERT "public"."user"', 'SELECT "public"."user"', 'DELETE "public"."user"']), + expect.arrayContaining(['INSERT "public"."User"', 'SELECT "public"."User"', 'DELETE "public"."User"']), ); querySpans.forEach(span => { expect(span.attributes['sentry.op']?.value).toBe('db'); @@ -67,7 +67,7 @@ describe('Prisma ORM v8 Tests', () => { 'sentry.origin': { value: 'auto.db.prisma', type: 'string' }, 'sentry.op': { value: 'db', type: 'string' }, 'db.operation.name': { value: method, type: 'string' }, - 'db.collection.name': { value: 'user', type: 'string' }, + 'db.collection.name': { value: 'User', type: 'string' }, model: { value: 'User', type: 'string' }, name: { value: `User.${method}`, type: 'string' }, }); @@ -80,13 +80,13 @@ describe('Prisma ORM v8 Tests', () => { .map(span => span.attributes['db.query.text']?.value); }; expect(queriesByOperation('create')).toEqual( - expect.arrayContaining([expect.stringMatching(/^INSERT INTO "public"\."user" /)]), + expect.arrayContaining([expect.stringMatching(/^INSERT INTO "public"\."User" /)]), ); expect(queriesByOperation('all')).toEqual([ - expect.stringMatching(/^SELECT .* FROM "public"\."user"$/), + expect.stringMatching(/^SELECT .* FROM "public"\."User"$/), ]); expect(queriesByOperation('delete')).toEqual( - expect.arrayContaining([expect.stringMatching(/^DELETE FROM "public"\."user" /)]), + expect.arrayContaining([expect.stringMatching(/^DELETE FROM "public"\."User" /)]), ); expect(querySpans.filter(span => span.parent_span_id === segment.span_id)).toEqual([]); }, @@ -126,7 +126,7 @@ describe('Prisma ORM v8 Tests', () => { }, { additionalDependencies: { - '@prisma/orm-postgres': '8.0.0-rc.8', + '@prisma/orm-postgres': '8.0.0-rc.17', }, copyPaths: ['prisma'], }, diff --git a/packages/server-utils/src/orchestrion/config/prisma.ts b/packages/server-utils/src/orchestrion/config/prisma.ts index 73d6b1a77607..281a97bfba43 100644 --- a/packages/server-utils/src/orchestrion/config/prisma.ts +++ b/packages/server-utils/src/orchestrion/config/prisma.ts @@ -2,12 +2,11 @@ import type { InstrumentationConfig } from '../apmTypes'; import { getModuleNames } from './module-names'; // Prisma 8 has no tracing surface, so its ORM terminals are wrapped directly. Apps install -// `@prisma/orm-postgres`, but `CollectionImpl` lives in the transitive `@prisma/orm-family-sql`. +// `@prisma/orm-postgres`, but `CollectionBase` lives in the transitive `@prisma/orm-family-sql`. const MODULE_NAME = '@prisma/orm-family-sql'; const ORM_CLIENT_FILE = 'dist/orm-client.mjs'; -// The range matcher admits every `8.0.0-rc.*`, not just rc.8 and later; the terminals were verified on rc.8. -const VERSION_RANGE = '>=8.0.0-rc.8 <9'; +const VERSION_RANGE = '>=8.0.0-rc.15 <9'; export const PRISMA_ASYNC_TERMINALS = [ 'aggregate', @@ -31,7 +30,7 @@ function terminalConfig(methodName: PrismaTerminal, kind: 'Async' | 'Sync'): Ins return { channelName: methodName, module: { name: MODULE_NAME, versionRange: VERSION_RANGE, filePath: ORM_CLIENT_FILE }, - functionQuery: { className: 'CollectionImpl', methodName, kind }, + functionQuery: { className: 'CollectionBase', methodName, kind }, }; }