Getting Started
Database Drivers
Schema Integrations
Seed Generators
Utilities and Testing
The following files were used as context for generating this wiki page:
The system project structure is defined by two primary concerns: the generation of database migration SQL via drizzle-kit and the runtime query construction via drizzle-orm. These components act as the translation layer between high-level schema definitions and low-level SQL dialects, ensuring that schema changes are reliably persisted and queries are correctly formed for the target database.
The drizzle-kit subsystem, specifically sqlgenerator.ts, serves as the bridge between declarative JSON state representation and imperative SQL execution. It handles the serialization of schema modifications into actionable migration statements, abstracting dialect-specific syntax quirks away from the core migration logic. This design allows for a unified interface that supports various RDBMS engines (PostgreSQL, MySQL, SQLite, SingleStore) by dispatching conversion tasks to specialized strategy classes.
In contrast, drizzle-orm represents the runtime component responsible for dynamic SQL construction. The PgDialect class centralizes the logic for mapping TypeScript schema objects into valid PostgreSQL statements. It solves the problem of runtime query building by maintaining state (such as column casing) and implementing builders that traverse table and relation definitions to generate optimized SQL, including complex operations like CTEs, joins, and relational data fetches.
The sqlgenerator.ts uses a strategy-based dispatch mechanism to convert JSON migration operations into raw SQL. Every conversion is encapsulated in a class inheriting from the Convertor abstract class, which forces each handler to implement a can() check and a convert() logic.
can(statement: JsonStatement, dialect: Dialect): boolean: Determines if the specific handler is qualified to process the migration statement for a target dialect.convert(...): Transforms the JSON statement into a string or string[] representing the SQL query.This decoupling prevents deep conditional nesting in the main logic, allowing for easy expansion as new dialects or SQL features are supported.
Sources: drizzle-kit/src/sqlgenerator.ts:151-161
sqlgenerator.tsThe entry point for generating SQL is the fromJson function, which processes an array of statements through the registered convertors. The execution follows a filtering pattern to select the correct handler for each statement.
fromJson accepts a list of JsonStatement[] and the target Dialect.flatMap.convertors.filter finds the matching strategy handler.convertor.convert is executed to generate the SQL.Sources: drizzle-kit/src/sqlgenerator.ts:4122-4144
Note
The convertor selection relies on the filter result containing exactly one element. If no handler matches (filtered.length === 0), the statement is ignored (returns an empty string).
Sources: drizzle-kit/src/sqlgenerator.ts:4130-4138
In drizzle-orm, the PgDialect class manages the state required for generating PostgreSQL-specific queries. It acts as a factory and container for dialect configuration, particularly casing strategies.
casing: A CasingCache instance that ensures table and column names conform to specified naming conventions (e.g., snake_case or camelCase) consistently across query generation.escapeName/escapeParam/escapeString: Low-level utilities that implement strict identifier and value escaping, protecting generated SQL from injection and syntax errors.Sources: drizzle-orm/src/pg-core/dialect.ts:63-71, 114-124
The dialect uses specialized internal builders to construct complex SQL. For a standard SELECT operation, the path is:
buildSelection: Assembles columns, handling aliasing and casing.buildFromTable: Identifies the source table or subquery.buildJoins: Iteratively constructs JOIN clauses.buildWithCTE: Handles common table expressions.SQL object via the select template string.Sources: drizzle-orm/src/pg-core/dialect.ts:341-448
Sources: drizzle-kit/src/sqlgenerator.ts:4122-4144
Sources: drizzle-kit/src/sqlgenerator.ts:151, drizzle-orm/src/pg-core/dialect.ts:63
The PgDialect incorporates safety guards during query construction. For instance, in buildSelectQuery, the builder verifies that all referenced columns actually exist within the current table scope.
if (is(f.field, Column) && getTableName(f.field.table) !== tableAlias && !isJoined) {
throw new Error(`Your field references a column "${tableName}"."${f.field.name}", but the table is not part of the query!`);
}If this condition is met, the system prevents a malformed SQL query from being generated by throwing a runtime Error early in the builder pipeline.
Sources: drizzle-orm/src/pg-core/dialect.ts:360-383
When a user updates a sequence in PostgreSQL, the system triggers the AlterPgSequenceConvertor. This demonstrates the lifecycle of a migration command:
// Example of how the migration system dispatches an alter sequence command
const statement: JsonAlterSequenceStatement = {
type: 'alter_sequence',
name: 'my_seq',
values: { increment: 5 }
};
const convertor = new AlterPgSequenceConvertor();
const sql = convertor.convert(statement);
// returns: "ALTER SEQUENCE "my_seq" INCREMENT BY 5;"This demonstrates how high-level configuration is converted into exact SQL syntax using the metadata provided in the JsonAlterSequenceStatement type.
Sources: drizzle-kit/src/sqlgenerator.ts:1355-1373