Skip to content

Commit fc31a5f

Browse files
AleksandrShermanOleksiiKH0240AlexBlokhAndriiShermanSukairo-02
authored
Beta.11 (#5262)
* updated tests * + * updated tests * [drizzle-kit] updated tests * [drizzle-kit] added tests * [drizzle-kit] added tests * [drizzle-kit] updated test * added tests * updated pull tests * + * [integration-tests] updated tests * corrected issue links * [drizzle kit] added test * [drizzle-kit] added test * [drizzle-kit] added tests * [feat-orm]: index logic Added ability to pass table column to index, uniqueIndex, using in outer const. Without using 3rd param in table * added tests * updated tests * [drizzle-kit] added tests * [fix+update]: mysql use/force/ignore index update + pg asc/nullsFirst index update Mysql: - Added ability to handle unique constraints in use/force/ignore indexes in select queries - Added tests Pg: - in drizzle-kit/drizzle.ts file updated logic regarding nullsFirst and asc/desc creation pg docs: https://www.postgresql.org/docs/current/sql-createindex.html * [update]: changelog * [drizzle-kit] added tests * [psql]: fixed broken tests in kit * [mysql]: fixed some an issue in kit * [sqlite]: isssue + fk introspect bugs fixed * [mssql]: index bug fix in kit * [cockroach]: fixed tests in kit * [sqlite]: fk introspect fix * [psql]: kit pk tests * [update]: changelog for drizzle-kit * [mssql]: kit fix * [drizzle-kit] added tests * [mssql-kit]: up to v2 * [kit]: psql + cockroach enum tests * [drizzle-kit] added tests * updated comments in tests * [update]: kit tests update * [update]: ignored ts error for deploy * [update-casing]: removed casing from Name class * [update]: isNull wrapped in () * [updates]: tests + bug fixes - Fixed "buildIndex" method in mysql for `use/force/ignore` indexes - Updated some integration tests * [update]: fixed int:sqlite tests * [update]: singlestore int test * [update]: singlestore test * [update]: changelog for kit + up of package.json versions of orm and kit * [update]: changelog + test * [drizzle-kit] added tests * [drizzle-kit] added test * updated test * [update-kit]: psql test * [update-kit]: fixed tests Added: - handling on column alters to serial in pg - suggestions for diff in mysql * [update-kit]: deprecated 'strict' flag * [update-kit]: test * [update-kit]: test * [update-kit]: mssql test * [update-kit]: fix * [update-kit]: added explain to every dialect * added tests * fixed prompt for column conflicts; added tests * [update-kit]: sqlite up fixes - Added tests on up (like pg and mysql had) - fixed some minor fixes * [fix-kit]: errors in mocks * [fix-kit]: mssql fixes * [fix-kit]: tests fix to deploy * [fix-kit] * [fix-kit] * [fix-kit] * [update]: versions + changelog for sqlite * [update]: comment * [update-kit]: fixed mssql + new tests * [fix-kit]: --explain handling * Update release notes * [sqlite-kit-fix]: introspect + explain * [update-kit]: fixed two issues * [fix-kit]: deepStrictEqual + fixed broken tests * [update-kit]: fixed issues * [update-kit]: added custom type for sqlite introspect + up all packages * [fix-kit]: defaults for text * added tests * [fix-kit]: fixed + postponed tests * [fix-kit]: sqlite def test * added tests * added tests * removed migration prefix from drizzle-kit * [update-kit]: handle custom migration schema and table in push + tests * [kit-fix]: tables tests * [kit-fix]: cli tests * [fix-kit] * [update-kit] * [update]: int tests removed skipIf in some tests * [update-kit]: changelog * [update-kit]: pg index issue fixed * [kit-fix]: pg + cockroach issue * [kit]: mssql issue * Fixed bun-sqlite rqbv2 mapper error on empty get response (fixes #5189) * Up all versions to 7 + orm changelog * changelog update * [update-kit]: tests on ignore migrations config schema/table + minor updates * [fix-kit]: fixed all fromDatabaseForDrizzle params * [fix-kit]: fixed broken tests * [kit-fix]: broken tests * added tests * added tests * [kit-fix]: mysql fixes * added tests * [kit-fix]: fixed issues 5224 and 5212 * [kit-fix]: fixed psql issue * [kit-fix]: entity filter update for pg * [kit]: removed .only * [kit-fix]: introspect fix for pk * [kit-fix]: returned entity filter logic back as it was * [kit-fix]: added some tests + tests on tsc relations * fixed test * orm timestamp batch + noop cache ignored from cache + mysql cyclic introspect * Separated date and int-exclusive column methods from common pg builder * added tests * upped versions + upped skipped tests dates + changelogs + extra tests * skipped tests * extra fix + test --------- Co-authored-by: OleksiiKH0240 <homenko0240@gmail.com> Co-authored-by: Alex Blokh <aleksandrblokh@gmail.com> Co-authored-by: AndriiSherman <andreysherman11@gmail.com> Co-authored-by: Sukairo-02 <sreka9056@gmail.com>
1 parent 8629189 commit fc31a5f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+1357
-452
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
## Bug fixes
2+
3+
- [[BUG]:drizzle-kit pull generates incorrect schema for functional/computed index](https://github.com/drizzle-team/drizzle-orm/issues/5224)
4+
- [[BUG]: drizzle-kit pull generates invalid code for MySQL datetime with DEFAULT CURRENT_TIMESTAMP ON UPDATE](https://github.com/drizzle-team/drizzle-orm/issues/5212)
5+
- [[BUG]: Drizzle-kit - push tries to delete non-public schemas by default (pscale_extensions)](https://github.com/drizzle-team/drizzle-orm/issues/5190)
6+
- [[BUG]: JSON.stringify cannot serialize BigInt](https://github.com/drizzle-team/drizzle-orm/issues/5227)
7+
8+
- Commutativity for `MySQL` `now(N)` and `CURRENT_TIMESTAMP(N)`
9+
10+
**MySQL pull command**:
11+
- Creation of a primary key when a column had only `UNIQUE` and `NOT NULL`
12+
- `varbinary()` config was ignored in a ts schema file
13+
- Foreign key column duplication when constraint names matched across multiple databases
14+
- Inconsistent casing between `schema.ts` and `relations.ts`
15+
- Cyclic references are generated as inline `.references((): AnyMySqlColumn => ...)` to avoid type errors for single-column references
16+
17+
**Common**:
18+
- Relation name collisions with column names during introspection. If a relation name collides with a column name - the relation is renamed to `<name>Relation`
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
- Defaulted `PgTimestampString` timezone offset to be `+00` when value gets returned as `Date` instance
2+
- `Pg`: Cache is now used only when explicitly defined. In recent `beta` versions caching was still applied even when no cache was configured
3+
- Separated date and int-exclusive column methods from common `pg builder` (separeted .defaultNow(), .generatedAlwaysAsIdentity(), .generatedByDefaultAsIdentity())

drizzle-arktype/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "drizzle-arktype",
3-
"version": "1.0.0-beta.10",
3+
"version": "1.0.0-beta.11",
44
"description": "Generate arktype schemas from Drizzle ORM schemas",
55
"type": "module",
66
"scripts": {

drizzle-kit/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "drizzle-kit",
3-
"version": "1.0.0-beta.10",
3+
"version": "1.0.0-beta.11",
44
"homepage": "https://orm.drizzle.team",
55
"keywords": [
66
"drizzle",

drizzle-kit/src/cli/commands/pull-common.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { toCamelCase } from 'drizzle-orm/casing';
12
import { plural, singular } from 'pluralize';
23
import { paramNameFor } from '../../dialects/postgres/typescript';
34
import { assertUnreachable } from '../../utils';
@@ -8,7 +9,7 @@ const withCasing = (value: string, casing: Casing) => {
89
return value;
910
}
1011
if (casing === 'camel') {
11-
return value.camelCase();
12+
return toCamelCase(value);
1213
}
1314

1415
assertUnreachable(casing);
@@ -29,15 +30,21 @@ export type SchemaForPull = {
2930
name: string;
3031
entityType: 'fks';
3132
}[];
33+
columns?: { name: string }[];
3234
// both unique constraints and unique indexes
3335
uniques: {
3436
columns: string[];
3537
}[];
3638
}[];
3739

40+
function prepareNameFor(name: string, tableColumns: string[]) {
41+
return tableColumns.includes(name) ? `${name}Relation` : name;
42+
}
43+
3844
export const relationsToTypeScript = (
3945
schema: SchemaForPull,
4046
casing: Casing,
47+
schemaPath?: string, // for tests purposes
4148
) => {
4249
const imports: string[] = [];
4350
const tableRelations: Record<
@@ -61,6 +68,7 @@ export const relationsToTypeScript = (
6168
// Process all foreign keys as before.
6269
schema.forEach((table) => {
6370
const fks = Object.values(table.foreignKeys);
71+
const tableColumns = table.columns?.map((it) => withCasing(it.name, casing)) ?? [];
6472

6573
if (fks.length === 2) {
6674
const [fk1, fk2] = fks;
@@ -84,7 +92,7 @@ export const relationsToTypeScript = (
8492
}
8593

8694
tableRelations[toTable1].push({
87-
name: plural(toTable2),
95+
name: prepareNameFor(plural(toTable2), tableColumns),
8896
type: 'through',
8997
tableFrom: toTable1,
9098
columnsFrom: columnsTo1,
@@ -100,7 +108,7 @@ export const relationsToTypeScript = (
100108
}
101109

102110
tableRelations[toTable2].push({
103-
name: plural(toTable1),
111+
name: prepareNameFor(plural(toTable1), tableColumns),
104112
// this type is used for .many() side of relation, when another side has .through() with from and to fields
105113
type: 'many-through',
106114
tableFrom: toTable2,
@@ -129,7 +137,7 @@ export const relationsToTypeScript = (
129137
}
130138

131139
tableRelations[keyFrom].push({
132-
name: singular(tableTo),
140+
name: prepareNameFor(singular(tableTo), tableColumns),
133141
type: 'one',
134142
tableFrom,
135143
columnsFrom,
@@ -155,7 +163,7 @@ export const relationsToTypeScript = (
155163
// maybe it can be done by introducing some sort of flag or just not providing columnsFrom and columnsTo
156164
// but I decided just to have a different type field here
157165
tableRelations[keyTo].push({
158-
name: plural(tableFrom),
166+
name: prepareNameFor(plural(tableFrom), tableColumns),
159167
type: 'one-one',
160168
tableFrom: tableTo,
161169
columnsFrom: columnsTo,
@@ -164,7 +172,7 @@ export const relationsToTypeScript = (
164172
});
165173
} else {
166174
tableRelations[keyTo].push({
167-
name: plural(tableFrom),
175+
name: prepareNameFor(plural(tableFrom), tableColumns),
168176
type: 'many',
169177
tableFrom: tableTo,
170178
columnsFrom: columnsTo,
@@ -176,7 +184,9 @@ export const relationsToTypeScript = (
176184
}
177185
});
178186

179-
const importsTs = `import { defineRelations } from "drizzle-orm";\nimport * as schema from "./schema";\n\n`;
187+
const importsTs = `import { defineRelations } from "drizzle-orm";\nimport * as schema from "${
188+
schemaPath ?? './schema'
189+
}";\n\n`;
180190

181191
let relationString = `export const relations = defineRelations(schema, (r) => ({`;
182192

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@ const createTableIndexes = (tableName: string, idxs: Index[], casing: Casing): s
610610
it.columns
611611
.map((it) => {
612612
if (it.isExpression) {
613-
return `sql\`${it.isExpression}\``;
613+
return `sql\`${it.value}\``;
614614
} else {
615615
return `table.${withCasing(it.value, casing)}${it.asc ? '.asc()' : '.desc()'}`;
616616
}

drizzle-kit/src/dialects/mysql/ddl.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ export function mysqlToRelationsPull(schema: MysqlDDL): SchemaForPull {
297297
const rawTable = tableFromDDL(table, schema);
298298
return {
299299
foreignKeys: rawTable.fks,
300+
columns: rawTable.columns.map((it) => ({ name: it.name })),
300301
uniques: Object.values(rawTable.indexes).map((idx) => ({
301302
columns: idx.columns.map((idxc) => {
302303
if (!idxc.isExpression && idx.isUnique) {

drizzle-kit/src/dialects/mysql/drizzle.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
MySqlChar,
99
MySqlColumn,
1010
MySqlCustomColumn,
11+
MySqlDateTime,
1112
MySqlDialect,
1213
MySqlEnumColumn,
1314
MySqlTable,
@@ -117,8 +118,8 @@ export const fromDrizzleSchema = (
117118

118119
let onUpdateNow: boolean = false;
119120
let onUpdateNowFsp: number | null = null;
120-
if (is(column, MySqlTimestamp)) {
121-
onUpdateNow = column.hasOnUpdateNow ?? false; // TODO
121+
if (is(column, MySqlTimestamp) || is(column, MySqlDateTime)) {
122+
onUpdateNow = column.hasOnUpdateNow ?? false;
122123
onUpdateNowFsp = column.onUpdateNowFsp ?? null;
123124
}
124125

drizzle-kit/src/dialects/mysql/grammar.ts

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -373,12 +373,12 @@ export const Varbinary: SqlType = {
373373
},
374374
defaultFromIntrospect: (value) => value,
375375
toTs: (type, value) => {
376-
if (!value) return { default: '' };
377-
378376
const options: any = {};
379377
const [length] = parseParams(type);
380378
if (length) options['length'] = Number(length);
381379

380+
if (!value) return { default: '', options };
381+
382382
let trimmed = value.startsWith('(') ? value.substring(1, value.length - 1) : value;
383383
trimmed = trimChar(value, "'");
384384
if (trimmed.startsWith('0x')) {
@@ -445,10 +445,17 @@ export const Timestamp: SqlType = {
445445

446446
if (!def) return { options, default: '' };
447447
const trimmed = trimChar(def, "'");
448-
if (trimmed === 'now()' || trimmed === '(now())' || trimmed === '(CURRENT_TIMESTAMP)') {
448+
if (
449+
trimmed === 'now()' || trimmed === '(now())' || trimmed === '(CURRENT_TIMESTAMP)'
450+
|| trimmed === 'CURRENT_TIMESTAMP'
451+
) {
449452
return { options, default: '.defaultNow()' };
450453
}
451454

455+
if (trimmed.includes('now(') || trimmed.includes('CURRENT_TIMESTAMP(')) {
456+
return { options, default: `sql\`${trimmed}\`` };
457+
}
458+
452459
if (fsp && Number(fsp) > 3) return { options, default: `sql\`'${trimmed}'\`` };
453460
// TODO: we can handle fsp 6 here too, using sql``
454461
return { options, default: `new Date("${trimmed}Z")` };
@@ -460,7 +467,22 @@ export const DateTime: SqlType = {
460467
drizzleImport: () => 'datetime',
461468
defaultFromDrizzle: Timestamp.defaultFromDrizzle,
462469
defaultFromIntrospect: Timestamp.defaultFromIntrospect,
463-
toTs: Timestamp.toTs,
470+
toTs: (type, def) => {
471+
const options: any = {};
472+
const [fsp] = parseParams(type);
473+
if (fsp) options['fsp'] = Number(fsp);
474+
475+
if (!def) return { options, default: '' };
476+
const trimmed = trimChar(def, "'");
477+
478+
if (trimmed.includes('now(') || trimmed.includes('CURRENT_TIMESTAMP(')) {
479+
return { options, default: `sql\`${trimmed}\`` };
480+
}
481+
482+
if (fsp && Number(fsp) > 3) return { options, default: `sql\`'${trimmed}'\`` };
483+
// TODO: we can handle fsp 6 here too, using sql``
484+
return { options, default: `new Date("${trimmed}Z")` };
485+
},
464486
};
465487

466488
export const Time: SqlType = {
@@ -656,9 +678,7 @@ const commutativeTypes = [
656678
['tinyint(1)', 'boolean'],
657679
['binary(1)', 'binary'],
658680
['char(1)', 'char'],
659-
['now()', '(now())', 'CURRENT_TIMESTAMP', '(CURRENT_TIMESTAMP)', 'CURRENT_TIMESTAMP()'],
660681
];
661-
662682
export const commutative = (left: string, right: string, mode: 'push' | 'default' = 'default') => {
663683
for (const it of commutativeTypes) {
664684
const leftIn = it.some((x) => x === left);
@@ -667,6 +687,19 @@ export const commutative = (left: string, right: string, mode: 'push' | 'default
667687
if (leftIn && rightIn) return true;
668688
}
669689

690+
// commutativity for:
691+
// - now(4) and CURRENT_TIMESTAMP(4)
692+
// - (now()) and (CURRENT_TIMESTAMP
693+
// ...etc
694+
const timeDefaultValueRegex = /^\(?(?:now|CURRENT_TIMESTAMP)(?:\((\d*)\))?\)?$/;
695+
const leftMatch = left.match(timeDefaultValueRegex);
696+
const rightMatch = right.match(timeDefaultValueRegex);
697+
if (leftMatch && rightMatch) {
698+
const leftValue = leftMatch[1] ?? ''; // undefined becomes '' for comparison
699+
const rightValue = rightMatch[1] ?? '';
700+
if (leftValue === rightValue) return true;
701+
}
702+
670703
const leftPatched = left.replace(', ', ',');
671704
const rightPatched = right.replace(', ', ',');
672705
if (leftPatched === rightPatched) return true;

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export const fromDatabase = async (
8080
SELECT
8181
*
8282
FROM information_schema.columns
83-
WHERE table_schema = '${schema}' and table_name != '__drizzle_migrations'
83+
WHERE table_schema = '${schema}'
8484
ORDER BY lower(table_name), ordinal_position;
8585
`).then((rows) => {
8686
const filtered = rows.filter((it) => tablesAndViews.some((x) => it['TABLE_NAME'] === x.name));
@@ -96,9 +96,8 @@ export const fromDatabase = async (
9696
*
9797
FROM INFORMATION_SCHEMA.STATISTICS
9898
WHERE INFORMATION_SCHEMA.STATISTICS.TABLE_SCHEMA = '${schema}'
99-
AND INFORMATION_SCHEMA.STATISTICS.TABLE_NAME != '__drizzle_migrations'
10099
AND INFORMATION_SCHEMA.STATISTICS.INDEX_NAME != 'PRIMARY'
101-
ORDER BY lower(INDEX_NAME);
100+
ORDER BY seq_in_index ASC;
102101
`).then((rows) => {
103102
const filtered = rows.filter((it) => tablesAndViews.some((x) => it['TABLE_NAME'] === x.name));
104103
queryCallback('indexes', filtered, null);
@@ -147,7 +146,7 @@ export const fromDatabase = async (
147146
const extra = column['EXTRA'] ?? '';
148147
// const isDefaultAnExpression = extra.includes('DEFAULT_GENERATED'); // 'auto_increment', ''
149148
// const dataType = column['DATA_TYPE']; // varchar
150-
const isPrimary = column['COLUMN_KEY'] === 'PRI'; // 'PRI', ''
149+
// const isPrimary = column['COLUMN_KEY'] === 'PRI'; // 'PRI', ''
151150
// const numericPrecision = column['NUMERIC_PRECISION'];
152151
// const numericScale = column['NUMERIC_SCALE'];
153152
const isAutoincrement = extra === 'auto_increment';
@@ -189,7 +188,6 @@ export const fromDatabase = async (
189188
table: table,
190189
name: name,
191190
type: changedType,
192-
isPK: isPrimary, // isPK is an interim flag we use in Drizzle Schema and ignore in database introspect
193191
notNull: !isNullable,
194192
autoIncrement: isAutoincrement,
195193
collation: collation,
@@ -204,6 +202,9 @@ export const fromDatabase = async (
204202
}
205203
: null,
206204
isUnique: false,
205+
// If to create "unique + not null" column, mysql shows it as "PRI"
206+
// need to check by constraints only
207+
isPK: false,
207208
uniqueName: null,
208209
});
209210
}
@@ -214,7 +215,6 @@ export const fromDatabase = async (
214215
FROM information_schema.table_constraints t
215216
LEFT JOIN information_schema.key_column_usage k USING(constraint_name,table_schema,table_name)
216217
WHERE t.constraint_type='PRIMARY KEY'
217-
AND table_name != '__drizzle_migrations'
218218
AND t.table_schema = '${schema}'
219219
ORDER BY ordinal_position
220220
`).then((rows) => {
@@ -265,7 +265,7 @@ export const fromDatabase = async (
265265
rc.UPDATE_RULE,
266266
rc.DELETE_RULE
267267
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
268-
LEFT JOIN information_schema.referential_constraints rc ON kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME
268+
LEFT JOIN information_schema.referential_constraints rc ON kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME AND kcu.CONSTRAINT_SCHEMA = rc.CONSTRAINT_SCHEMA
269269
WHERE kcu.TABLE_SCHEMA = '${schema}'
270270
AND kcu.CONSTRAINT_NAME != 'PRIMARY'
271271
AND kcu.REFERENCED_TABLE_NAME IS NOT NULL;

0 commit comments

Comments
 (0)