ORM
- [BREAKING] Fixed
postgres-jstransparent parsers set bydrizzle()constructors breaking driver's own serializers fortimestamptz,timestamp,date,time,json,jsonbtypes (fixes #3171, #4426, #5789) paramsInErrors
❗ Any existing workarounds with manualJSON.stringify(jsonValue)in raw sql or raw driver calls must be removed to prevent double stringification of JSON params; For array-type JSON params insqlusesql.param(jsonArrayValue)to avoid it being parsed as value list instead of param. - [BREAKING] Restricted
undefinedvalue passed to fields in relational queries'where- now throws an error upon encounteringundefinedin filters, addedEmptyFiltersymbol (import { EmptyFilter } from 'drizzle-orm/relations') that can be used as an explicit replacement ofundefinedwhere possibly absent filter is desired by design rather than possible bug (fixes #5636)
Example:db.query.users.findMany({ where: { isActive: params.isActive ?? EmptyFilter } })
- [BREAKING] Relation filters without conditions (
{}, or containing only empty conditions) are now skipped like any other empty filter instead of generatingexists (...)check of relation's presence - usetrueto filter by relation's presence,false- by its absence
Example:// Previously: `where exists (select * from "posts" ...)`, now: no filter db.query.users.findMany({ where: { posts: {} } }) // Users with at least one post db.query.users.findMany({ where: { posts: true } })
- [BREAKING] Updated
postgrescodecs: now generic codecs contain only in-json codecs (mirroringmysql), contents of drivers' codecs remain unchanged - [BREAKING] Switched
pgbyteain-json codecs fromencode(..., 'base64')casts to decodingto_json's native hex output - [BREAKING] Made nested select join nullification consider
SQLfield data during nullification - [BREAKING] Fixed
sqliteignoring.$defaultFn(...)on insert when.default(...)is present - [BREAKING] Untied
bun-sql/mysql,mysql2,singlestorecolumn mapping from connection config, removed forcedbigintparams on their respective configs, replaced with more stablecastcodecs - [BREAKING] Reworked
cockroachcolumn builders to mirrorpg- now both have same.array('[][]...')syntax - [BREAKING] Moved
Viewexports fromdrizzle-orm/sql/sqltodrizzle-orm/view - [BREAKING]
getTableUniqueNameno longer prefixes aliased views or tables with theirschema - [BREAKING]
getTableUniqueNameno longer setspublic.prefix for entities withoutschema - [BREAKING] Updated
Viewclass: switched toTable-like object config for type template, typedschemaproperty - [BREAKING] Updated
withReplicas(indirectly fixes #4185):- Now every query goes to primary db by default
- To query replica, explicitly call
db.$replica
- [BREAKING] Added
withCastCodecs = falseswitch togetSQL(),withCastCodecs = trueswitch totoSQL()of non-relational query builders - nowdb.select(...).from(...).getSQL()emits query without cast codecs by default - [BREAKING] Reworked
sqlite-proxy:- Added
rowMode: 'array' | 'object'switch for'all' | 'get'execute methods - Dropped
{ rows: Result[] }callback result wrapping - now expected direct return of expected data - Replaced
callback,batchCallbackwithSqliteProxyExecutorsobject - must providerun,all,gethandlers & optionalbatchhandler - Dropped
valuesexecute method due to it being duplicate of array-modeall - Added
TRunResulttype inferrence based on return type ofrunexecutor, updatedSqliteRemoteDatabasetemplate withTRunResultargument - Added per-item
rowMode: 'array' | 'object'tobatch,batchis expected to mirror executors' return types per query
- Added
- [BREAKING] Fixed runtime-type expected result mismatch for
get(data | undefinedin runtime,data[]in types) (fixes #5461, #3394) - [BREAKING] Fixed
sqlitedb.get(sql)return type lacking| undefinedfor queries without returned rows - [BREAKING] Omitted query
paramsfromDrizzleQueryErrorby default, addedparamsInErrorsoption todrizzleconstructor to enable queryparamsinDrizzleQueryError(fixes #5939)
Example:const db = drizzle({ connection: 'postgres://...', paramsInErrors: true })
- [BREAKING] For
mysql,postgres,cockroach,mssqlset RQBv2 to new query build strategy to fix slow query plans (fixes #5245)
Can be opted out of per query viastrategyswitch:db.query.findMany({ strategy: 'basic' })
When used, may break direct references to relations in raw SQL syntaxwhere,orderBy:// posts with the most comments first db.query.posts.findMany({ with: { author: true, comments: true }, orderBy: (t, { sql }) => sql`json_array_length("comments"."r") desc, ${t.id}`, // "comments" becomes unreachable due to query nesting limit: 2, }); // posts of verified authors db.query.posts.findMany({ with: { author: true }, where: { RAW: (t, { sql }) => sql`("author"."r"->>'verified')::boolean` }, // "author" becomes unreachable due to query nesting });
- [BREAKING] Moved
StringChunk,commonStringChunksexports fromdrizzle-orm/sql/sqltodrizzle-orm/sql/common-chunks(still exported fromdrizzle-orm/sql) - [BREAKING] Switched RQBv2 build functions to chunk collection: each accepts optional trailing
collectTo: SQLChunk[]array to push chunks to and returns chunk arrays instead ofSQL
❗ Chunk arrays embedded intosqldirectly are rendered as value lists - wrap them innew SQL(chunks)to use them as query partsrelationsFilterToSQL(...).sql:SQL | undefined->SQLChunk[] | undefined, addedcollectToparameterrelationsOrderToSQL(...):SQL | undefined->SQLChunk[] | undefined, addedcollectToparameterrelationsOrderEntriesToSQL(...): replacedparts: SQL[]parameter withcollectTo: SQLChunk[],start?: number;RelationsOrderSource'sfrom,filtersare nowSQLChunk[],SQLChunk[][]relationExtrasToSQL(...).sql:SQL | undefined->SQLChunk[] | undefined, addedcollectToparameterrelationToSQL(...):{ filter?: SQL; joinCondition?: SQL }->{ filter: SQLChunk[]; joinCondition?: SQLChunk[] }, addedfilterTo,joinConditionToparametersgetTableAsAliasSQL(...):SQL->SQLChunk[], addedcollectToparameter
- [BREAKING] Relational queries are now cached by caches with
allstrategy (global: true), opt out per query viawithCache: false - [BREAKING] Replaced
DBQueryConfigWithCommenttype withDBQueryConfigRoot- config of root relational query containing all root-only options (strategy,comment,withCache); dialects' relational query builders accept it with options they don't support omitted - Updated RQB filters to allow branded types in shortcut-form
eqfilter (fixes #5298) - Fixed
$onUpdateFnbeing executed without need (fixes #5780) - Fixed
$onUpdateFnpotentially overriding explicitnulls - Fixed
zodschema generator returningunknown-templated coerced types (fixes #5659) - Fixed
mysql2constructor setting param in potentially undefined mistyped config (fixes #5972) - Fixed non-jit mapper nullification triggering on single null column (fixes #1603)
- Preserved qualifiers for column chunks of
sqlfields in selection when non-current table's column is referenced (fixes #5734) - Optimized query building, mapper generation
- Allowed empty returns in callback-style
orderBy,extras,RAWof relational queries - Removed unused
_field inRelationsHelperStatic - Fixed naming:
isReversedtoisFilterReversedinRelation objects,arraysdb.executemodes (db.all,db.getinsqlite) (bypasses #4464)- Fixed jit mapper nullifying nested selection objects with columns from different tables
- Fixed selection group nullification not triggering on objects with deeply nested fields (joined view or subquery)
- Fixed
geometry,geography&boxarray types data getting reduced to one item due to wrong delimiter used duringpgArrayconstruction\parsing - Added delimiter customization to
makePgArray,parsePgArrayutilities - Optional explicit column lists for
db.insert(workaround for #5001, #5309)- Usage:
db.insert(users, 'name', 'email').values([{ name: 'First', email: 'first@example.com' }, { name: 'Second', email: 'second@example.com' }])
- Usage:
- Transaction snapshot support for
pgdialect - Fixed
pgtransaction config related errors on empty but present config (fixes #1772) - Supported transaction config in effect
pgdrivers - Bump
tursodatabaselibrary versions - Supported transaction configs for
tursodatabasedrivers - Fixed
mysqltransaction options being joined on wrong separator - Supported
isolationLevelinbun-sql/mysqltransactions - Removed transaction config from
effect-sqlite,effect-mysqldue to lack of support in drivers - Explicit error throws on unsupported transaction configs
- Partial transaction config support for
libsql,tidbdrivers - Improved error messages on unknown fields in RQBv2 selection (fixes #5367)
- Fixed
op-sqlitetransaction being handled as synchronous - Fixed broken
op-sqlitequery executors (fixes #5936) - Bumped
op-sqliteto v17 (fixes #5928) - Fixed
expo-sqlitenot finalizing prepared statements - Added
expo-sqlite/asyncfor async querying (fixes #5240) - Added local
sha256hash function as a fallback for cache query hashing in environments withoutglobalThis.cryptoavailable - Fixed dynamic query builders blocking query builder's variable reassignment after applying nullable joins by defaulting to
not-nullbehavior on not yet joined column groups in selection (fixes #4232) - Fixed
byteanot being included inpgtable creation callback format column list - Moved
SQL.usedTablescalculation from constructor to getter - Fixed false relation name collision error and relational filter misrouting for relation names shadowing
Object.prototypeproperties likeconstructor(fixes #6076) - Updated
neon-httpmigrator to automatically rollback failed migrations - Bump
effectto4.0.0(fixes #6162, #6403, #6412) - Improved hash for query name generation & query cache key
- Bump
typeboxto1.2.0(fixes #5981) - Fixed internal type errors in built code
- Updated
mssql,cockroach,singlestoresessions to new format - Added missing
lateral(apply),crossjoins,insert ... select,db.$counttomssql - Added explicit error on attempt to insert multiple default-only rows in
mssql - Fixed
blobcolumns on React Native drivers: writes no longer requireBuffer,op-sqliteandexpo-sqlitereads normalized toUint8Array. Useblob(...).$type<UInt8Array>()to override column's type - Fixed cast codecs being applied to selection fields of inner queries in
pg,mysql - Fixed double space following
order byin set operation queries - Fixed
MSSQL,MySQL,SingleStoreserialtypes returning different types based on column's value - Fixed
sqlitegeneratingView,Subqueryqueries withcastonnumericcolumns - Codec system for
sqlite,cockroach,mssql,singlestore - Migrated
mssql,cockroachto RQBv2 - Removed redundant
limit 1from relationalwhere,coalescefor json arrays insqlitein RQBv2 - Removed RQBv1
schemafromDrizzleConfig - Fixed
mysql2not usingcodecsfrom config over driver's default when provided - Added delimiter customization to
makeCockroachArray,parseCockroachArrayutilities, mirroring theirpgcounterparts - Fixed
cockroachgeometryarrays being unwritable due to wrong delimiter - Fixed
cockroacharray parser dropping backslashes from string values - Fixed
cockroachint4[]being parsed tostring[] - Added
mappercaching for queries reused without.prepare() - Fixed table extra config not rejecting unsuitable for field values (fixes #6140)
- Fixed subquery derived from
.$dynamic()query builder being unusable with.from,.*Join(fixes #4069) - Fixed
Placeholdervaluefield described asdeclare protected: TValueinstead ofdeclared protected value: TValue; Setnamefield toprotectedand markedgetSQLas@deprecatedto prevent field from bleeding into relational filters' autocomplete - Fixed
Subquery.getSQL()(fixes #2174) - Fixed relational queries not supporting
Subquerytype fields inViews - Fixed
aliasfunction returning materialized views typed as regular views - Added typed
isAlias: booleantype config property toView,Tableto identify if it was aliased - Added
isTableAlias,getTableSchemautils, supportedViewingetTableNameutil - Supported
Subqueryas relational entity in RQBv2:Subquerymust have flat selection, same asView- Every used
Subquerywill be invoked only once inWITHsection on root level of relational query, every reference will use it's alias - Same query can't have reference multiple
Subqueryinstances with same alias
- Fixed excessive memory consumption on
mysql,mssql,singlestoreiterators - Fixed
mysql2iterators leaving connection un-drained & deadlocked on errors - Fixed
mysql2iterators hanging when connection is dropped mid-stream - Fixed
ExtraConfigColumn.getSQL()recursing into stack overflow (fixes #6050) - Fixed
sqlitedropping| undefinedfrom.get()return type ofdb.update(table).set(...).returning() - Fixed
sqlitedropping| undefinedfrom.get()return type ofdb.insert(table).values(...).returning()with.onConflictDoNothing()or.onConflictSet({ where: ... })present,db.insert(table).select(...).returning()(fixes #6107) - Fixed select codecs leaking into builders passed as sql operator argument
- Fixed
undefined=null,bigint= mimicstring, different data view type collisions inhashQuery(fixes #5842) - Fixed concurrent query + cache invalidation run (fixes #5828)
- Fixed cached query invalidation for:
- tables in nested SQL & subqueries
- aliased and
tableCreator-prefixed tables - tables defined on schemas
- joined & aliased tables of query builders embedded into raw
sql - tables used in filters, selected fields, order clause, set operators, CTE-s
- Added
getCacheKey(table)util returning the name query cache tracks a table by (schema.name, ornamefor tables without schema; aliases resolve to their original tables) - Fixed
orderByof set operations dropping table qualifiers in passedsqlobjects (e.g.desc(column)) - Supported
DSQLadapters forpostgres-js(@aws/aurora-dsql-postgresjs-connector) -drizzle-orm/postgres-js/dsql,node-postgres(@aws/aurora-dsql-node-postgres-connector) -drizzle-orm/node-postgres/dsql - Fixed param codecs getting applied to inlined params
- Reworked
db.executetypes (fixes #661):- Plain
db.execute(sql)- returns union every possible response type by driver db.execute<never>(sql)- returns rowless response type (i.e.insertwithoutreturning)db.execute<ReturnedObject>- driver response with rows typed asReturnedObject[]
- Plain
- Fixed
db.execute<IReturnedObject>(sql)type template rejecting interfaces - Typed
effectdrivers' rawdb.execute,db.run(fixes #6382) - Fixed RQBv2 query config lacking type errors with
typescript@6and above (fixes #5644, #6383) - Fixed
mysqldatecolumn being affected by server's timezone (fixes #1442) - Fixed
effect-mysql,bun-sql/mysqldrivers losingtimefraction - Fixed
SQLiteBigIntattempting to useBufferin encoder withoutBufferpresent in environment (fixes #2043) - Fixed
durable-sqlitedb.get(sql)throwing on queries returning zero or more than one row instead of returningundefinedor the first row - Fixed
node-postgrestransaction crashing process if connection is dropped mid-transaction (fixes #6437) - Fixed
node-postgrestransaction leaking the pool client onBEGINerror (fixes #6341) - Fixed failed transaction
rollbackerror replacing the original error that triggered it - Added ordering by relations to RQBv2:
// Select users sorted by last post db.query.users.findMany({ orderBy: { posts: { createdAt: 'desc(max)' } } }) // Select users sorted by post count db.query.users.findMany({ orderBy: { posts: 'asc(count)' } }) // Select admin posts first, sort rest by creation date db.query.posts.findMany({ orderBy: { author: { isAdmin: 'desc' }, createdAt: 'desc' } })
- Added cache support to RQBv2 via
withCacheswitch:true- cache queryfalse- never cache queryundefined- cache only withallcache strategy
db.query.users.findMany({ with: { posts: true }, withCache: true })
- Fixed
instanceofnot working reliably fordrizzleclasses in monorepos with multiple library instances - Fixed
aws-data-api/pg:- Array params throwing
Unknown typeerror - now sent aspgarray literals - Object params throwing
Unknown typeerror - now sent as JSON withJSONtype hint - Multidimensional arrays in results being returned as raw
ArrayValueobjects char(n)params being truncated to a single character by::charcastinetvalues gaining full-width netmask (/32,/128) in resultstime({ withTimezone: true })values losing their offset: params were cast to::time, results were converted to UTC by Data API
- Array params throwing
- Fixed
pgtime({ withTimezone: true })columns usingtimecodecs instead oftimetzones - Fixed [BUG]: inArray/notInArray empty arrays do not work with SQL Server
- Fixed [BUG]: node-postgres pool client is not released when transaction BEGIN rejects
- Fixed Batch insert crashes with RangeError when row-count × column-count exceeds ~8 k rows × 15 cols (~120 k params)
- Fixed [BUG]: Composition of not and or/and yields compile error
- Fixed [BUG]: Negative limit not working in SQLite
- Fixed [BUG]: Pooled transaction() leaks the pool client when BEGIN fails (node-postgres / neon-serverless / vercel-postgres)
- Fixed [BUG]: node-postgres transaction() leaks the client on a rejected BEGIN and returns broken clients to the pool. node-postgres: transaction() runs BEGIN before try/finally, leaking the pool client when BEGIN fails
Kit:
- FINALLY incremental snapshots. Drizzle kit now stores initial snapshots and all subsequent are stored as structured diffs + metadata for migrations commutativity checks on different branches
- Added support for custom PGLite options (fixes #2995, #4476 and #3222)
- Fixed
defineConfigallowing fields from every config variant simultaneously - Fixed [BUG]: SQLite push glues the table's FOREIGN KEY clause onto a generated-column ALTER ADD, breaking all inserts
- Fixed [BUG]: SQLite push table recreate silently drops UNIQUE from a column that also has a plain index
- Fixed [BUG]:drizzle-kit generates DROP COLUMN before DROP INDEX causing PostgreSQL error 42704
- Fixed [BUG]: false positve detection of schema changes for default values
- Fixed [BUG]: drizzle-kit pull rewrites "character" inside public enum type names to "char"
- Fixed [BUG]: drizzle-kit pull error when there are comments in a view definition
- Fixed [BUG]: Invalid schema default value generated for sequence-based primary keys in Postgres
- Fixed Small typo in drizzle-kit/src/index.ts
- Fixed [BUG]: drizzle-kit pull reports index_duplicate for valid MSSQL index names reused across tables
- Fixed [BUG]: drizzle-kit pull generates many() instead of one() for one-to-one relations (unique FK columns)
- Fixed [BUG]: AWS Data API Postgres - incompatibility with latest @aws-sdk/client-rds-data (3.932.0)
- Fixed [BUG]: Composition of not and or/and yields compile error
- Fixed [BUG]: snakeCase.table converts Korean column names to empty identifiers
- Fixed [BUG]: Property decimal does not exist on type, when using pgTable in drizzle orm
- Fixed Bug: drizzle-kit pull for SQLite Generates Constraints from Comments in Schema
- Fixed [BUG]: drizzle-kit pull fails with column_unsupported_unique for unique indexes on text/mediumtext/longtext columns
- Fixed [BUG]: drizzle-kit CLI pull/introspect schemaFilters parameter is ignored
- Fixed [BUG]: Changing a view to materialized view doesn't generate correct migration
- Fixed [BUG]: SQLite incorrectly scaffolds boolean column with drizzle-kit pull
- Fixed [BUG]: Introspection fails if SQLite database has a references without column name
- Fixed [BUG]: SQLite pull drops or merges CHECK constraints depending on DDL formatting
- Fixed [BUG]: SQLite pull reads a partial index's WHERE off the table's DDL, losing real predicates and inventing false ones
- Fixed [BUG]: SQLite pull crashes on any expression index, because .on() doesn't filter the keys the line above it does
- Fixed [BUG]: drizzle-kit pull generates a many-to-many whose junction table is one of its own endpoints, and drops the one-relations the foreign keys describe
- Fixed [BUG]: drizzle-kit push tries to DROP Neon system roles despite provider: "neon"
- Fixed [BUG]: drizzle-kit pull generates invalid through relations for composite foreign keys
- Fixed [BUG]: drizzle-kit pull: schema and relations disagree on camelCase for acronym columns (CallID → callId vs callID)
- Fixed [BUG]: drizzle-kit pull drops single-column PK/FK constraint names from schema.ts (kept nameExplicit in snapshot) — pull→generate demands rename-or-create hints for every legacy-named constraint + [BUG]: Drizzle Kit introspection creates different foreign key names than migration
- Updates in pull relations logic. TS file generates junction tables only when there are no extra columns in this junction table. Fixed [BUG]: drizzle-kit pull treats domain tables with exactly two foreign keys as junction tables
- Fixed [BUG]: drizzle-kit pull fails with a confusing error if the database can't be reached
- Fixed [BUG]: drizzle-kit generate drops column alterations when a column with the same name is renamed in another table
- Updates in
pullcommand - migration.sql is no longer has comments when runningpull --init - Fixed
drizzle-ormnot being listed as peer dependency - Fixed dev dependencies being listed as production