Getting Started
Database Drivers
Schema Integrations
Seed Generators
Utilities and Testing
The following files were used as context for generating this wiki page:
Column Types in Drizzle provide a robust, type-safe interface for mapping database schemas to TypeScript objects. By defining a set of core builders and runtime definitions, Drizzle ensures that every column in a table can be accurately queried, validated, and serialized to the underlying database dialect, whether it is PostgreSQL, MySQL, SQLite, Gel, or SingleStore.
The system is architected around a separation between the build phase and the runtime phase. Builder classes, such as those derived from PgColumnBuilder or SQLiteColumnBuilder, manage configurations—such as nullability, default values, and primary key constraints—during the schema definition phase. When a table is built, these builders transition into runtime column instances, which hold the logic for data transformation between the driver's raw output and the application's domain types.
Design decisions within this subsystem prioritize type inference and dialect-specific abstraction. Builders use generics to track data types (e.g., 'string', 'number', 'boolean'), while the column classes handle dialect-specific serialization quirks, such as different integer representations or JSON/Blob handling. This layered design allows Drizzle to expose a unified API surface while maintaining the performance and flexibility required for cross-dialect database management.
The PgColumnBuilder or SQLiteColumnBuilder classes (and their equivalents) are the roots for column definitions in their respective dialects. Their primary purpose is to collect configuration metadata before a table is fully realized. They implement the chainable API used in table definitions, such as .notNull(), .default(), and .primaryKey().
Internally, the config object acts as a state container. When you call .notNull(), the builder simply sets this.config.notNull = true and returns this cast to a specific type, ensuring the TypeScript compiler reflects this state change for subsequent chain calls.
Sources: drizzle-orm/src/pg-core/columns/common.ts:38-43, drizzle-orm/src/sqlite-core/columns/common.ts:6
While building interfaces share commonality, actual data type implementation is split by dialect. For example, PgNumericBuilder and SQLiteNumericBuilder both offer numeric column support but handle the mapping logic to their respective driver's outputs differently.
In the PgNumeric implementation, the mapFromDriverValue function is designed to handle unknown inputs, converting them to string if they are not already, ensuring consistent behavior despite database variability. Conversely, the SQLiteNumericNumber implementation specifically maps its inputs to number type, demonstrating how builders and runtime definitions tailor the interface based on the requested mode.
Sources: drizzle-orm/src/pg-core/columns/numeric.ts:40-67, drizzle-orm/src/sqlite-core/columns/numeric.ts:37-49, drizzle-orm/src/sqlite-core/columns/numeric.ts:80-94
Drizzle provides a customType function for each dialect to support proprietary or complex database types that are not explicitly covered by the core library. This subsystem allows developers to specify the underlying SQL data type via a dataType function and provide custom toDriver and fromDriver mapping functions.
When a column is defined via customType, the builder instance (e.g., SingleStoreCustomColumnBuilder or SQLiteCustomColumnBuilder) holds the configuration, while the resulting column class instance encapsulates the mapping logic. This architecture prevents core code from needing awareness of every possible niche database type while still providing seamless integration.
Sources: drizzle-orm/src/singlestore-core/columns/custom.ts:26-59, drizzle-orm/src/sqlite-core/columns/custom.ts:25-58
The transition from a definition to a concrete database object involves a specific initialization sequence. When a table is declared, the framework instantiates the builder classes. The build() method is then invoked, which consumes the config object from the builder and initializes the runtime column class.
For example, when constructing an array column in PostgreSQL:
PgArrayBuilder is initialized with a base builder..build(table).PgArrayBuilder instantiates the base column and passes it to the PgArray constructor.PgArray constructor sets the array-specific SQL type, such as integer[].Sources: drizzle-orm/src/pg-core/columns/common.ts:260-307
Drizzle Kit performs introspection to convert raw database schema data back into Drizzle ORM TypeScript code. This involves mapping raw column types back to Drizzle function calls.
The schemaToTypeScript function in the MySQL introspector, for instance, iterates over table columns, patches type strings using a lookup table (importsPatch), and then dispatches the result to a column() function. This function acts as a factory, matching the string type to a constructor for the correct builder, and generating the necessary .default() or .primaryKey() chain calls.
Sources: drizzle-kit/src/introspect-mysql.ts:133-195, drizzle-kit/src/introspect-mysql.ts:386-416
Note
When introspecting columns, the framework maps "int unsigned" types to standard integer builders and applies an { unsigned: true } parameter in the generated code.
Each column type contains logic to bridge the gap between driver data and application data. mapFromDriverValue and mapToDriverValue are the primary lifecycle hooks for this conversion.
For instance, the SQLiteBlobJson column type defines how it handles raw binary data:
override mapFromDriverValue(value: Buffer | Uint8Array | ArrayBuffer): T['data'] {
// ... decoding logic
return JSON.parse(buf.toString('utf8'));
}This is critical because SQLite doesn't have a native JSON type; it forces developers to store JSON objects in blob or text columns, and this mapping function abstracts that limitation entirely away from the developer.
Sources: drizzle-orm/src/sqlite-core/columns/blob.ts:100-114
Sources: drizzle-orm/src/column-builder.ts:185-317, drizzle-orm/src/pg-core/columns/numeric.ts:17-38