Getting Started
Database Drivers
Schema Integrations
Seed Generators
Utilities and Testing
The following files were used as context for generating this wiki page:
The "Query Builder Core" subsystem serves as the foundational abstraction layer that decouples Drizzle's expressive DSL from the myriad of underlying database drivers and execution runtimes. By providing standardized interfaces for statement preparation, query execution, and transactional lifecycle management, it enables the Drizzle ORM to support diverse targets—including PostgreSQL (Neon, Postgres.js, Bun SQL), MySQL (PlanetScale, MySQL2), and SQLite (Better-SQLite3, LibSQL, OP-SQLite)—without exposing developers to the idiosyncratic differences of each driver’s API.
At its heart, the core resides in driver-specific classes that extend base session and query classes. These implementations manage database connections, provide methods for transactional scope creation, and act as a factory for specific prepared query objects. Each driver maps the generic Drizzle execution methods (like .execute(), .all(), or .get()) to the target driver’s specific command execution protocols.
The architecture emphasizes type-safe query composition and efficient execution. By abstracting the interaction into prepared query objects, Drizzle defers the actual SQL generation and parameter binding until the moment of execution, allowing for driver-level optimizations, logging, and caching strategies. This design decouples the "query intent" from "query execution," permitting centralized features like query caching, tracing, and result set mapping to operate consistently across disparate backend storage engines.
The base session classes are the primary orchestrators for driver-level interactions. They mandate the implementation of prepareQuery, which creates an instance of a prepared query subclass specifically tailored for the underlying driver. This factory pattern ensures that every dialect-specific detail—such as parameter placeholders, type parsing, or vendor-specific SQL extensions—is encapsulated within the prepared query instance rather than leaking into the main application logic.
Sources: drizzle-orm/src/mysql-core/session.ts:180-191
The execution flow for queries is centralized to leverage common cross-dialect features. The queryWithCache method, present in various prepared query implementations, serves as the main gateway for query dispatch. It checks the global cache configuration before invoking the driver's execution method. For mutation queries (INSERT, UPDATE, DELETE), this method orchestrates both the database execution and the necessary cache invalidation via the onMutate interface, ensuring data consistency across the application.
Note
During mutations, onMutate is called concurrently with the database query to allow the cache to invalidate specific table entries based on the queryMetadata tables.
Sources: drizzle-orm/src/mysql-core/session.ts:70-154, drizzle-orm/src/sqlite-core/session.ts:71-155
Transactional management follows a consistent lifecycle across drivers: creating a transaction instance, executing an initialization command (e.g., BEGIN), performing the user-provided transaction callback, and finalizing with a commit or rollback command. Nested transactions are typically supported via SAVEPOINT logic, where the transaction instance tracks a nestedIndex to generate unique savepoint names.
Sources: drizzle-orm/src/mysql2/session.ts:331-349, drizzle-orm/src/sqlite-core/session.ts:151-162
To ensure security and compatibility, all drivers utilize the fillPlaceholders utility. This mechanism maps the user-provided parameter values against the query string's expected placeholders. This ensures that the final SQL string sent to the driver is correctly formatted and that parameters are passed via the driver’s secure parameterized query interface, preventing SQL injection.
Sources: drizzle-orm/src/mysql2/session.ts:93-95, drizzle-orm/src/pg-core/session.ts:13-15
Result mapping is a critical step where raw rows are transformed into the expected entity shape using mapResultRow. This utility is invoked within the prepared query’s execution methods (execute or all). By relying on column-based metadata, Drizzle can reconstruct nested relational objects or alias complex SQL expressions into predictable JavaScript object shapes.
Sources: drizzle-orm/src/mysql2/session.ts:142-142, drizzle-orm/src/bun-sql/session.ts:74-74
Sources: drizzle-orm/src/gel-core/query-builders/query-builder.ts:128-135
Developers interact with the core primarily through the database instance, which delegates execution to the session.
// Example: Executing a query with the SQLite core API
const users = sqliteTable('users', { id: integer('id'), name: text('name') });
// db is an instance of BaseSQLiteDatabase
const allUsers = await db.select().from(users).all();
// Underlying execution chain:
// 1. db.select() -> SQLiteSelectBuilder
// 2. .from(users) -> sets table
// 3. .all() -> calls session.all()
// 4. session.prepareOneTimeQuery().all() -> maps to driver-specific executionSources: drizzle-orm/src/sqlite-core/db.ts:396-402, drizzle-orm/src/sqlite-core/session.ts:280-285