Skip to content

Commit 0894418

Browse files
committed
Merge branch 'beta.16' of github.com:drizzle-team/drizzle-orm into beta.16
2 parents ce6c5e0 + a2ee747 commit 0894418

File tree

40 files changed

+794
-656
lines changed

40 files changed

+794
-656
lines changed

drizzle-kit/src/dialects/cockroach/introspect.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ export const fromDatabase = async (
509509
FROM
510510
pg_attribute attr
511511
LEFT JOIN pg_class cls ON cls.oid = attr.attrelid
512-
LEFT JOIN crdb_internal.table_columns tc ON tc.descriptor_id = attrelid AND tc.column_name = attname
512+
LEFT JOIN information_schema.columns tc ON tc.table_schema = cls.relnamespace::regnamespace::text AND tc.table_name = cls.relname AND tc.column_name = attname
513513
LEFT JOIN pg_type typ ON typ.oid = attr.atttypid
514514
WHERE
515515
${filterByTableAndViewIds ? ` attrelid in ${filterByTableAndViewIds}` : 'false'}

drizzle-kit/src/dialects/utils.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ export const filterMigrationsSchema = (
178178
columns: { table: string; schema?: string }[];
179179
pks: { table: string; schema?: string }[];
180180
tables: { name: string; schema?: string }[];
181+
defaults?: { table: string; schema?: string }[]; // for mssql only
181182
},
182183
migrations: {
183184
schema: string;
@@ -197,6 +198,13 @@ export const filterMigrationsSchema = (
197198
!(pk.table === migrationsTable && (pk.schema ? pk.schema === migrationsSchema : true))
198199
);
199200

201+
// mssql only
202+
if (interim.defaults) {
203+
interim.defaults = interim.defaults.filter((def) =>
204+
!(def.table === migrationsTable && (def.schema ? def.schema === migrationsSchema : true))
205+
);
206+
}
207+
200208
if (interim.schemas) {
201209
let tablesInMigrationSchema = interim.tables.filter((table) => table.schema === migrationsSchema);
202210
if (!tablesInMigrationSchema.length) {

drizzle-kit/tests/postgres/pg-columns.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ test('alter text type to enum type', async () => {
323323

324324
// https://github.com/drizzle-team/drizzle-orm/issues/3589
325325
// After discussion it was decided to postpone this feature
326-
test.skipIf(Date.now() < +new Date('2026-02-10'))('alter integer type to text type with fk constraints', async () => {
326+
test.skipIf(Date.now() < +new Date('2026-02-25'))('alter integer type to text type with fk constraints', async () => {
327327
const users1 = pgTable('users', {
328328
id: serial().primaryKey(),
329329
});

drizzle-kit/tests/postgres/pg-enums.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2460,7 +2460,7 @@ test('drop enum', async () => {
24602460

24612461
// https://github.com/drizzle-team/drizzle-orm/issues/4982
24622462
// enhancement
2463-
test.skipIf(Date.now() < +new Date('2026-02-10'))(
2463+
test.skipIf(Date.now() < +new Date('2026-02-25'))(
24642464
'alter enum values; enum value is column default; table with data',
24652465
async () => {
24662466
enum AppStatus1 {

drizzle-kit/tests/postgres/pg-tables.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1500,7 +1500,7 @@ test('push with pscale_extensions schema', async () => {
15001500
});
15011501

15021502
// https://github.com/drizzle-team/drizzle-orm/issues/5329
1503-
test.skipIf(Date.now() < +new Date('2026-02-10'))(
1503+
test.skipIf(Date.now() < +new Date('2026-02-25'))(
15041504
'push empty schema with `schemaFilter` set to `["public"]`',
15051505
async () => {
15061506
await db.query(`CREATE SCHEMA "cron";`);

drizzle-kit/tests/postgres/pg-views.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2105,7 +2105,7 @@ test('.as in view select', async () => {
21052105

21062106
// https://github.com/drizzle-team/drizzle-orm/issues/4181
21072107
// casing bug
2108-
test.skipIf(Date.now() < +new Date('2026-02-10'))('create view with snake_case', async () => {
2108+
test.skipIf(Date.now() < +new Date('2026-02-25'))('create view with snake_case', async () => {
21092109
const test = pgTable('test', {
21102110
testId: serial().primaryKey(),
21112111
testName: text().notNull(),
@@ -2142,7 +2142,7 @@ test.skipIf(Date.now() < +new Date('2026-02-10'))('create view with snake_case',
21422142

21432143
// https://github.com/drizzle-team/drizzle-orm/issues/4181
21442144
// casing bug
2145-
test.skipIf(Date.now() < +new Date('2026-02-10'))('create view with camelCase', async () => {
2145+
test.skipIf(Date.now() < +new Date('2026-02-25'))('create view with camelCase', async () => {
21462146
const test = pgTable('test', {
21472147
test_id: serial().primaryKey(),
21482148
test_name: text().notNull(),

drizzle-kit/tests/postgres/pull.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,7 @@ test('introspect view #3', async () => {
720720
// https://github.com/drizzle-team/drizzle-orm/issues/4262
721721
// postopone
722722
// Need to write discussion/guide on this and add ts comment in typescript file
723-
test.skipIf(Date.now() < +new Date('2026-02-10'))('introspect view #4', async () => {
723+
test.skipIf(Date.now() < +new Date('2026-02-25'))('introspect view #4', async () => {
724724
const table = pgTable('table', {
725725
column1: text().notNull(),
726726
column2: text(),
@@ -742,7 +742,7 @@ test.skipIf(Date.now() < +new Date('2026-02-10'))('introspect view #4', async ()
742742
// https://github.com/drizzle-team/drizzle-orm/issues/4262
743743
// postopone
744744
// Need to write discussion/guide on this and add ts comment in typescript file
745-
test.skipIf(Date.now() < +new Date('2026-02-10'))('introspect view #5', async () => {
745+
test.skipIf(Date.now() < +new Date('2026-02-25'))('introspect view #5', async () => {
746746
const applications = pgTable('applications', {
747747
applicationId: serial('application_id').primaryKey(),
748748
studentId: integer('student_id').references(() => students.studentId),
@@ -1423,7 +1423,7 @@ test('introspect view with table filter', async () => {
14231423
// this does not look like a bug
14241424
// sequences are separete entities
14251425
// entity filter for sequences ??
1426-
test.skipIf(Date.now() < +new Date('2026-02-10'))('introspect sequences with table filter', async () => {
1426+
test.skipIf(Date.now() < +new Date('2026-02-25'))('introspect sequences with table filter', async () => {
14271427
// can filter sequences with select pg_get_serial_sequence('"schema_name"."table_name"', 'column_name')
14281428

14291429
// const seq1 = pgSequence('seq1');

drizzle-orm/src/bun-sqlite/migrator.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export function migrate<TSchema extends Record<string, unknown>, TRelations exte
3333
folderMillis: d.timestamp,
3434
hash: '',
3535
bps: true,
36+
name: d.name,
3637
}));
3738

3839
return db.dialect.migrate(migrations, db.session, {

drizzle-orm/src/cockroach-core/dialect.ts

Lines changed: 54 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -44,59 +44,9 @@ interface UpgradeResult {
4444
currentVersion?: number;
4545
}
4646

47-
/**
48-
* Detects the current version of the migrations table schema and upgrades it if needed.
49-
*
50-
* Version 0: Original schema (id, hash, created_at)
51-
* Version 1: Extended schema (id, hash, created_at, name, applied_at, version)
52-
*/
53-
async function upgradeIfNeeded(
54-
migrationsSchema: string,
55-
migrationsTable: string,
56-
session: CockroachSession,
57-
localMigrations: MigrationMeta[],
58-
): Promise<UpgradeResult> {
59-
// Check if the table exists at all
60-
const tableExists = await session.all<{ exists: boolean }>(
61-
sql`SELECT EXISTS (
62-
SELECT FROM information_schema.tables
63-
WHERE table_schema = ${migrationsSchema}
64-
AND table_name = ${migrationsTable}
65-
)`,
66-
);
67-
68-
if (!tableExists[0]?.exists) {
69-
return { newDb: true };
70-
}
71-
72-
// Table exists, check if there are any rows
73-
const rows = await session.all<{ id: number; hash: string; created_at: string; version: number | undefined }>(
74-
sql`SELECT * FROM ${sql.identifier(migrationsSchema)}.${sql.identifier(migrationsTable)} ORDER BY id ASC LIMIT 1`,
75-
);
76-
77-
let prevVersion;
78-
79-
if (rows.length === 0) {
80-
// Empty table - check if it has a version column
81-
const hasVersionColumn = await session.all<{ exists: boolean }>(
82-
sql`SELECT EXISTS (
83-
SELECT FROM information_schema.columns
84-
WHERE table_schema = ${migrationsSchema}
85-
AND table_name = ${migrationsTable}
86-
AND column_name = 'version'
87-
)`,
88-
);
89-
90-
prevVersion = hasVersionColumn[0]?.exists ? 1 : 0;
91-
} else {
92-
prevVersion = rows[0]?.version ?? 0;
93-
}
94-
95-
if (prevVersion < CURRENT_MIGRATION_TABLE_VERSION) {
96-
await runUpgrades(migrationsSchema, migrationsTable, session, prevVersion, localMigrations);
97-
}
98-
99-
return { prevVersion, currentVersion: CURRENT_MIGRATION_TABLE_VERSION };
47+
function getVersion(columns: string[]) {
48+
if (columns.includes('name')) return 1;
49+
return 0;
10050
}
10151

10252
/**
@@ -116,11 +66,9 @@ const upgradeFunctions: Record<
11666
* Upgrade from version 0 to version 1:
11767
* 1. Add `name` column (text)
11868
* 2. Add `applied_at` column (timestamp with time zone, defaults to now())
119-
* 3. Add `version` column (integer)
120-
* 4. Backfill `name` for existing rows by matching `created_at` (millis) to local migration folder timestamps
121-
* 5. If multiple migrations share the same second, use hash matching as a tiebreaker
122-
* Not implemented for now -> 6. If hash matching fails, fall back to serial id ordering
123-
* 7. Set `version` to 1 on all rows
69+
* 3. Backfill `name` for existing rows by matching `created_at` (millis) to local migration folder timestamps
70+
* 4. If multiple migrations share the same second, use hash matching as a tiebreaker
71+
* Not implemented for now -> 5. If hash matching fails, fall back to serial id ordering
12472
*/
12573
0: async (migrationsSchema, migrationsTable, session, localMigrations) => {
12674
const table = sql`${sql.identifier(migrationsSchema)}.${sql.identifier(migrationsTable)}`;
@@ -130,7 +78,6 @@ const upgradeFunctions: Record<
13078
await session.execute(
13179
sql`ALTER TABLE ${table} ADD COLUMN IF NOT EXISTS "applied_at" timestamp with time zone DEFAULT now()`,
13280
);
133-
await session.execute(sql`ALTER TABLE ${table} ADD COLUMN IF NOT EXISTS "version" integer`);
13481

13582
// 2. Read all existing DB migrations
13683
// Sort them by ids asc (order how they were applied)
@@ -175,31 +122,67 @@ const upgradeFunctions: Record<
175122
}
176123

177124
await session.execute(
178-
sql`UPDATE ${table} SET name = ${
179-
matched?.name ?? null
180-
}, version = ${1}, applied_at = NULL WHERE id = ${dbRow.id}`,
125+
sql`UPDATE ${table} SET name = ${matched?.name ?? null}, applied_at = NULL WHERE id = ${dbRow.id}`,
181126
);
182127
}
183128
},
184129
};
185130

186131
/**
187-
* Runs all upgrade functions sequentially from `fromVersion` to CURRENT_MIGRATION_TABLE_VERSION.
132+
* Detects the current version of the migrations table schema and upgrades it if needed.
133+
*
134+
* Version 0: Original schema (id, hash, created_at)
135+
* Version 1: Extended schema (id, hash, created_at, name, applied_at)
188136
*/
189-
async function runUpgrades(
137+
async function upgradeIfNeeded(
190138
migrationsSchema: string,
191139
migrationsTable: string,
192140
session: CockroachSession,
193-
fromVersion: number,
194141
localMigrations: MigrationMeta[],
195-
): Promise<void> {
196-
for (let v = fromVersion; v < CURRENT_MIGRATION_TABLE_VERSION; v++) {
142+
): Promise<UpgradeResult> {
143+
// Check if the table exists at all
144+
const tableExists = await session.all<{ exists: boolean }>(
145+
sql`SELECT EXISTS (
146+
SELECT FROM information_schema.tables
147+
WHERE table_schema = ${migrationsSchema}
148+
AND table_name = ${migrationsTable}
149+
)`,
150+
);
151+
152+
if (!tableExists[0]?.exists) {
153+
return { newDb: true };
154+
}
155+
156+
// Table exists, check table shape
157+
const rows = await session.all<{ schema: string; table_name: string; column_name: string; type: string }>(
158+
sql`SELECT
159+
n.nspname AS "schema",
160+
c.relname AS "table_name",
161+
a.attname AS "column_name",
162+
pg_catalog.format_type(a.atttypid, a.atttypmod) AS "type"
163+
FROM
164+
pg_catalog.pg_attribute a
165+
JOIN pg_catalog.pg_class c ON c.oid = a.attrelid
166+
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
167+
WHERE
168+
a.attnum > 0
169+
AND NOT a.attisdropped
170+
AND n.nspname = ${migrationsSchema}
171+
AND c.relname = ${migrationsTable}
172+
ORDER BY a.attnum;`,
173+
);
174+
175+
let version = getVersion(rows.map((r) => r.column_name));
176+
177+
for (let v = version; v < CURRENT_MIGRATION_TABLE_VERSION; v++) {
197178
const upgradeFn = upgradeFunctions[v];
198179
if (!upgradeFn) {
199180
throw new Error(`No upgrade path from migration table version ${v} to ${v + 1}`);
200181
}
201182
await upgradeFn(migrationsSchema, migrationsTable, session, localMigrations);
202183
}
184+
185+
return { prevVersion: version, currentVersion: CURRENT_MIGRATION_TABLE_VERSION };
203186
}
204187

205188
export class CockroachDialect {
@@ -233,8 +216,7 @@ export class CockroachDialect {
233216
hash text NOT NULL,
234217
created_at bigint,
235218
name text,
236-
applied_at timestamp with time zone DEFAULT now(),
237-
version int4
219+
applied_at timestamp with time zone DEFAULT now()
238220
)
239221
`;
240222

@@ -263,8 +245,8 @@ export class CockroachDialect {
263245
await session.execute(
264246
sql`insert into ${sql.identifier(migrationsSchema)}.${
265247
sql.identifier(migrationsTable)
266-
} ("hash", "created_at", "name", "version")
267-
values (${migration.hash}, ${migration.folderMillis}, ${migration.name}, ${CURRENT_MIGRATION_TABLE_VERSION})`,
248+
} ("hash", "created_at", "name")
249+
values (${migration.hash}, ${migration.folderMillis}, ${migration.name})`,
268250
);
269251

270252
return;
@@ -279,7 +261,7 @@ export class CockroachDialect {
279261
await tx.execute(
280262
sql`insert into ${sql.identifier(migrationsSchema)}.${
281263
sql.identifier(migrationsTable)
282-
} ("hash", "created_at") values(${migration.hash}, ${migration.folderMillis})`,
264+
} ("hash", "created_at", "name") values(${migration.hash}, ${migration.folderMillis}, ${migration.name})`,
283265
);
284266
}
285267
});

drizzle-orm/src/d1/migrator.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { readMigrationFiles } from '~/migrator.ts';
33
import { getMigrationsToRun } from '~/migrator.utils.ts';
44
import type { AnyRelations } from '~/relations.ts';
55
import { sql } from '~/sql/sql.ts';
6-
import { CURRENT_MIGRATION_TABLE_VERSION, upgradeAsyncIfNeeded } from '~/up-migrations/sqlite.ts';
6+
import { upgradeAsyncIfNeeded } from '~/up-migrations/sqlite.ts';
77
import type { DrizzleD1Database } from './driver.ts';
88

99
export async function migrate<TSchema extends Record<string, unknown>, TRelations extends AnyRelations>(
@@ -18,12 +18,11 @@ export async function migrate<TSchema extends Record<string, unknown>, TRelation
1818
if (newDb) {
1919
const migrationTableCreate = sql`
2020
CREATE TABLE IF NOT EXISTS ${sql.identifier(migrationsTable)} (
21-
id SERIAL PRIMARY KEY,
21+
id INTEGER PRIMARY KEY,
2222
hash text NOT NULL,
2323
created_at numeric,
2424
name text,
25-
version integer,
26-
applied_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
25+
applied_at TEXT
2726
)
2827
`;
2928
await db.session.run(migrationTableCreate);
@@ -49,7 +48,9 @@ export async function migrate<TSchema extends Record<string, unknown>, TRelation
4948
await db.run(
5049
sql`INSERT INTO ${
5150
sql.identifier(migrationsTable)
52-
} ("hash", "created_at", "name", "version") VALUES(${migration.hash}, '${migration.folderMillis}', ${migration.name}, ${CURRENT_MIGRATION_TABLE_VERSION})`
51+
} ("hash", "created_at", "name", "applied_at") values(${migration.hash}, ${migration.folderMillis}, ${migration.name}, ${
52+
new Date().toISOString()
53+
})`
5354
.inlineParams(),
5455
);
5556
return;
@@ -66,7 +67,9 @@ export async function migrate<TSchema extends Record<string, unknown>, TRelation
6667
db.run(
6768
sql`INSERT INTO ${
6869
sql.identifier(migrationsTable)
69-
} ("hash", "created_at", "name", "version") VALUES(${migration.hash}, '${migration.folderMillis}', ${migration.name}, ${CURRENT_MIGRATION_TABLE_VERSION})`
70+
} ("hash", "created_at", "name", "applied_at") values(${migration.hash}, ${migration.folderMillis}, ${migration.name}, ${
71+
new Date().toISOString()
72+
})`
7073
.inlineParams(),
7174
),
7275
);

0 commit comments

Comments
 (0)