본문으로 건너뛰기
cccskills
무료GitHub에 공개

prisma-driver-adapter-implementation

Required reference for Prisma ORM 7 SQL driver adapter work. Use when implementing or modifying adapters, adding database drivers, or touching SqlDriverAdapter, Transaction, savepoint, result mapping, or DriverAdapterError behavior. Covers current transaction lifecycle, optional savepoint hooks, original database-error preservation, and verification.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

연동 도구PostgreSQL
설치 방법 보기

포함된 파일(1)

  • SKILL.md11.1 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

Prisma SQL Driver Adapter Implementation

Use this guide with the exact @prisma/driver-adapter-utils version installed by the target Prisma release. Driver adapters are a protocol boundary: type-compatible code can still corrupt values, leak connections, or break transactions.

When to Apply

  • Implementing SqlDriverAdapterFactory, SqlMigrationAwareDriverAdapterFactory, SqlDriverAdapter, or Transaction
  • Adding nested-transaction/savepoint support
  • Mapping driver values, column metadata, bind arguments, or database errors
  • Debugging P2039, transaction leaks, shadow-database failures, or adapter-specific query behavior

Contract snapshot

interface SqlDriverAdapterFactory extends AdapterInfo {
  connect(): Promise<SqlDriverAdapter>
}

interface SqlMigrationAwareDriverAdapterFactory extends SqlDriverAdapterFactory {
  connectToShadowDb(): Promise<SqlDriverAdapter>
}

interface SqlDriverAdapter extends AdapterInfo {
  queryRaw(query: SqlQuery): Promise<SqlResultSet>
  executeRaw(query: SqlQuery): Promise<number>
  executeScript(script: string): Promise<void>
  startTransaction(isolationLevel?: IsolationLevel): Promise<Transaction>
  getConnectionInfo?(): ConnectionInfo
  dispose(): Promise<void>
}

interface Transaction extends AdapterInfo {
  readonly options: { usePhantomQuery: boolean }
  queryRaw(query: SqlQuery): Promise<SqlResultSet>
  executeRaw(query: SqlQuery): Promise<number>
  commit(): Promise<void>
  rollback(): Promise<void>
  createSavepoint?(name: string): Promise<void>
  rollbackToSavepoint?(name: string): Promise<void>
  releaseSavepoint?(name: string): Promise<void>
}

IsolationLevel currently includes READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SNAPSHOT, and SERIALIZABLE; validate what the concrete database supports.

Priority rules

PriorityRuleImpact
CRITICALOne dedicated connection per transactionPrevents interleaving and leaks
CRITICALcommit/rollback are lifecycle cleanup hooksPrevents duplicate COMMIT/ROLLBACK
CRITICALSavepoints live on Transaction, not adapter-global depthMakes nested scopes connection-local
CRITICALPreserve original database error code/messageEnables useful P2039 fallback
HIGHMap arguments and result metadata exactlyPrevents silent value corruption
HIGHShadow databases are isolated and always cleaned upMakes Migrate safe
HIGHDispose only resources the adapter ownsPrevents shutting down caller-owned pools

Query implementation

SqlQuery contains sql, args, and parallel argTypes. Map each argument using both value and ArgType; do not discard type/arity information. Execute in the driver's array/tuple row mode so column order is stable.

class ExampleQueryable {
  readonly provider = 'postgres' as const
  readonly adapterName = '@acme/adapter-example'

  constructor(protected readonly connection: DriverConnection) {}

  async queryRaw(query: SqlQuery): Promise<SqlResultSet> {
    try {
      const result = await this.connection.query({
        text: query.sql,
        values: query.args.map((value, index) =>
          mapArg(value, query.argTypes[index]),
        ),
        rowMode: 'array',
      })

      return {
        columnNames: result.fields.map((field) => field.name),
        columnTypes: result.fields.map(mapColumnType),
        rows: result.rows,
      }
    } catch (error) {
      throwAdapterError(error)
    }
  }

  async executeRaw(query: SqlQuery): Promise<number> {
    try {
      const result = await this.connection.execute(
        query.sql,
        query.args.map((value, index) => mapArg(value, query.argTypes[index])),
      )
      return result.rowsAffected ?? 0
    } catch (error) {
      throwAdapterError(error)
    }
  }
}

Result mapping

Return columnNames, columnTypes, and rows with identical lengths/order. Map driver metadata to ColumnTypeEnum deliberately:

  • signed integer widths to Int32/Int64; preserve 64-bit values without JS number truncation
  • decimal/numeric to Numeric using the representation expected by Prisma
  • binary to Uint8Array/Bytes
  • date-only, time-only, and timestamp to Date, Time, and DateTime
  • UUID, JSON, enum, arrays, and provider-specific unknown values to their explicit types
  • unsupported native types to DriverAdapterError({ kind: 'UnsupportedNativeDataType', type })

Test null, empty arrays, array element types, big integers, decimals, byte arrays, JSON, dates, and user-defined/unknown native types.

Script execution

executeScript must execute a migration script as the provider expects. Prefer the driver's native multi-statement/script facility or a real SQL parser. Naively splitting on ; breaks functions, triggers, quoted strings, and dialect-specific blocks.

Transaction protocol

startTransaction must acquire one dedicated connection, start the database transaction, apply the requested isolation level, and return a Transaction bound to that same connection. If setup fails, release it immediately.

async startTransaction(level?: IsolationLevel): Promise<Transaction> {
  const connection = await this.pool.acquire()
  try {
    const tx = new ExampleTransaction(connection, () => connection.release())
    await tx.executeRaw({ sql: 'BEGIN', args: [], argTypes: [] })
    if (level) {
      await tx.executeRaw({
        sql: `SET TRANSACTION ISOLATION LEVEL ${validateLevel(level)}`,
        args: [],
        argTypes: [],
      })
    }
    return tx
  } catch (error) {
    connection.release(error)
    throwAdapterError(error)
  }
}

Commit and rollback

Prisma coordinates the SQL COMMIT/ROLLBACK through executeRaw. The transaction object's commit() and rollback() methods are lifecycle hooks: detach listeners and release the dedicated connection exactly once. They must not issue a second SQL commit/rollback.

class ExampleTransaction extends ExampleQueryable implements Transaction {
  readonly options = { usePhantomQuery: false }
  #closed = false

  constructor(connection: DriverConnection, private readonly release: () => void) {
    super(connection)
  }

  async commit() { this.finish() }
  async rollback() { this.finish() }

  private finish() {
    if (this.#closed) return
    this.#closed = true
    this.release()
  }

  async createSavepoint(name: string) {
    await this.control(`SAVEPOINT ${safeSavepoint(name)}`)
  }

  async rollbackToSavepoint(name: string) {
    await this.control(`ROLLBACK TO SAVEPOINT ${safeSavepoint(name)}`)
  }

  async releaseSavepoint(name: string) {
    await this.control(`RELEASE SAVEPOINT ${safeSavepoint(name)}`)
  }

  private async control(sql: string) {
    await this.executeRaw({ sql, args: [], argTypes: [] })
  }
}

Implement the optional savepoint methods only where the provider supports them. Validate/quote savepoint identifiers. For providers whose savepoints are intentionally no-ops, document and test that limitation.

Never keep transaction depth on the shared adapter. Parallel transactions make adapter-global depth incorrect; nested state belongs to the returned transaction connection and Prisma's savepoint calls.

Error mapping

Wrap recognized driver failures in DriverAdapterError. Map known conditions to MappedError kinds such as constraint violations, authentication/reachability, missing table/column/database, timeouts, closed transactions, invalid input, value range, and write conflicts.

For database errors, preserve originalCode and originalMessage even when falling back to the provider-specific raw variant:

import {
  DriverAdapterError,
  type Error as DriverAdapterErrorObject,
  type MappedError,
} from '@prisma/driver-adapter-utils'

function convertDriverError(error: DatabaseError): DriverAdapterErrorObject {
  return {
    originalCode: String(error.code),
    originalMessage: error.message,
    ...mapKnownOrRaw(error),
  }
}

function mapKnownOrRaw(error: DatabaseError): MappedError {
  if (error.code === '23505') {
    return { kind: 'UniqueConstraintViolation', constraint: parsedConstraint(error) }
  }
  return {
    kind: 'postgres',
    code: String(error.code ?? 'N/A'),
    severity: error.severity ?? 'N/A',
    message: error.message,
    detail: error.detail,
    column: error.column,
    hint: error.hint,
  }
}

function throwAdapterError(error: unknown): never {
  if (!isDatabaseError(error)) throw error
  throw new DriverAdapterError(convertDriverError(error))
}

Prisma uses preserved original details when an unmapped driver error becomes P2039. Do not replace every unknown exception with a fabricated GenericJs id; rethrow genuinely unexpected non-driver errors so programming bugs remain visible.

Factory, ownership, and shadow database

  • connect() returns a fresh usable adapter connection/pool wrapper.
  • Track whether the factory created the pool. dispose() closes owned pools and only detaches listeners from caller-owned pools unless an explicit option transfers ownership.
  • Implement SqlMigrationAwareDriverAdapterFactory only when connectToShadowDb() can create an isolated shadow database, connect to it, and drop it during disposal/failure cleanup.
  • Never point the shadow adapter at the primary database. Quote generated identifiers and use cryptographically unique names.
  • getConnectionInfo() should accurately report schemaName, maxBindValues when applicable, and supportsRelationJoins.

Verification checklist

  • Typecheck against the exact target @prisma/driver-adapter-utils version
  • queryRaw preserves column order, types, nulls, and precision
  • executeRaw reports affected rows correctly
  • executeScript handles provider-specific multi-statement syntax
  • Concurrent interactive transactions use distinct dedicated connections
  • Success commits and releases once; failure rolls back and releases once
  • Nested transaction tests exercise create/rollback/release savepoint hooks
  • Unsupported isolation levels fail as InvalidIsolationLevel
  • Known constraints map to structured errors
  • Unmapped database errors retain original code/message and surface useful P2039
  • Dispose ownership is tested for internal and external pools
  • Shadow database creation, use, failure cleanup, and disposal are isolated
  • Run Prisma Client integration/E2E tests, not only adapter unit tests

Source references

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Prisma ORM 7 CLI reference for existing Prisma 7 applications or explicitly selected Prisma 7 workflows. Covers prisma init, generate, migrate, db, dev, studio, and mcp. For setup, connection repair, or Prisma 8, use prisma-orm-setup; not the Prisma Platform CLI.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

prisma/skills712026년 10월 16일 업데이트

Prisma Client API reference covering model queries, filters, operators, and client methods. Use when writing database queries, using CRUD operations, filtering data, or configuring Prisma Client. Triggers on "prisma query", "findMany", "create", "update", "delete", "$transaction".

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

prisma/skills712026년 10월 16일 업데이트

Deploy and operate apps on Prisma Compute with the Prisma 8 CLI. Use whenever the user mentions Prisma Compute, deploying or hosting a Prisma app, `prisma deploy`, `prisma dev module.ts`, Prisma Composer apps (`module.ts`, `compute()`, the `composer` section of `prisma.config.ts`), preview stages, deploy on push (`prisma git connect`, `prisma/cloud-deploy-action`), `prisma service` logs, versions, rollback, or custom domains, `project env`, `PRISMA_SERVICE_TOKEN`, regions, 504s, sleeping instances, or `waitUntil`; also when a project still uses the removed `@prisma/cli app deploy`, `prisma.compute.ts`, `defineComputeConfig`, `compute:deploy`, or `build logs` surface.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

prisma/skills712026년 10월 16일 업데이트

Deprecated compatibility name for prisma-orm-setup. Use only when a user or existing integration explicitly invokes prisma-database-setup; otherwise select prisma-orm-setup.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

prisma/skills712026년 10월 16일 업데이트

Decision and migration guide for Prisma ORM MongoDB projects on v6, which have no upgrade path to v7. Use when a MongoDB project asks about upgrading Prisma, when "upgrade to prisma 7" comes up in a project with provider = "mongodb", or when evaluating a move to Prisma 8. Triggers on "upgrade prisma mongodb", "prisma 7 mongodb", "mongodb prisma migration", "prisma 8 mongodb".

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

prisma/skills712026년 10월 16일 업데이트

Set up Prisma ORM in an application, connect its database, or troubleshoot the connection of an existing Prisma 6, 7, or 8 app. Defaults new applications to Prisma ORM 8 and loads the package-owned prisma-8 skill; keeps existing Prisma 6/7 apps on their version with provider references for PostgreSQL, MySQL, SQLite, SQL Server, CockroachDB, MongoDB, and Prisma Postgres.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

prisma/skills712026년 10월 16일 업데이트

prisma의 스킬 모두 보기

이 스킬의 문제 신고