Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Beta #4037

Merged
merged 18 commits into from
Jan 29, 2025
Merged

Beta #4037

Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fixes
OleksiiKH0240 committed Jan 27, 2025
commit e5713d6b7d6a26da08d93a13493f823b92ce6545
27 changes: 12 additions & 15 deletions drizzle-seed/src/index.ts
Original file line number Diff line number Diff line change
@@ -659,13 +659,12 @@ const getPostgresInfo = (
tableRelations[tableTsName]?.some((rel) =>
rel.table === relation.table
&& rel.refTable === relation.refTable
) === true
)
) {
console.warn(
`You are providing a one-to-many relation from the '${relation.table}' table to the '${relation.refTable}' table,\n`
+ `while your '${relation.table}' table object already has foreign key constraint in the schema(from the '${relation.table}' table to the '${relation.refTable}' table).\n`
+ `You can specify either the foreign key constraint or the relation, but not both.\n`
+ `By default, one-to-many relation will be ignored to respect foreign key constraint.\n`,
`You are providing a one-to-many relation between the '${relation.refTable}' and '${relation.table}' tables,\n`
+ `while the '${relation.table}' table object already has foreign key constraint in the schema referencing '${relation.refTable}' table.\n`
+ `In this case, the foreign key constraint will be used.\n`,
);
continue;
}
@@ -1053,13 +1052,12 @@ const getMySqlInfo = (
tableRelations[tableTsName]?.some((rel) =>
rel.table === relation.table
&& rel.refTable === relation.refTable
) === true
)
) {
console.warn(
`You are providing a one-to-many relation from the '${relation.table}' table to the '${relation.refTable}' table,\n`
+ `while your '${relation.table}' table object already has foreign key constraint in the schema(from the '${relation.table}' table to the '${relation.refTable}' table).\n`
+ `You can specify either the foreign key constraint or the relation, but not both.\n`
+ `By default, one-to-many relation will be ignored to respect foreign key constraint.\n`,
`You are providing a one-to-many relation between the '${relation.refTable}' and '${relation.table}' tables,\n`
+ `while the '${relation.table}' table object already has foreign key constraint in the schema referencing '${relation.refTable}' table.\n`
+ `In this case, the foreign key constraint will be used.\n`,
);
continue;
}
@@ -1374,13 +1372,12 @@ const getSqliteInfo = (
tableRelations[tableTsName]?.some((rel) =>
rel.table === relation.table
&& rel.refTable === relation.refTable
) === true
)
) {
console.warn(
`You are providing a one-to-many relation from the '${relation.table}' table to the '${relation.refTable}' table,\n`
+ `while your '${relation.table}' table object already has foreign key constraint in the schema(from the '${relation.table}' table to the '${relation.refTable}' table).\n`
+ `You can specify either the foreign key constraint or the relation, but not both.\n`
+ `By default, one-to-many relation will be ignored to respect foreign key constraint.\n`,
`You are providing a one-to-many relation between the '${relation.refTable}' and '${relation.table}' tables,\n`
+ `while the '${relation.table}' table object already has foreign key constraint in the schema referencing '${relation.refTable}' table.\n`
+ `In this case, the foreign key constraint will be used.\n`,
);
continue;
}
7 changes: 0 additions & 7 deletions drizzle-seed/tests/mysql/allDataTypesTest/drizzle.config.ts

This file was deleted.

7 changes: 0 additions & 7 deletions drizzle-seed/tests/mysql/drizzle.config.ts

This file was deleted.

7 changes: 0 additions & 7 deletions drizzle-seed/tests/mysql/generatorsTest/drizzle.config.ts

This file was deleted.

64 changes: 62 additions & 2 deletions drizzle-seed/tests/mysql/mysql.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import Docker from 'dockerode';
import { sql } from 'drizzle-orm';
import { relations, sql } from 'drizzle-orm';
import type { MySql2Database } from 'drizzle-orm/mysql2';
import { drizzle } from 'drizzle-orm/mysql2';
import getPort from 'get-port';
import type { Connection } from 'mysql2/promise';
import { createConnection } from 'mysql2/promise';
import { v4 as uuid } from 'uuid';
import { afterAll, afterEach, beforeAll, expect, test } from 'vitest';
import { afterAll, afterEach, beforeAll, expect, test, vi } from 'vitest';
import { reset, seed } from '../../src/index.ts';
import * as schema from './mysqlSchema.ts';

@@ -180,6 +180,29 @@ beforeAll(async () => {
`,
);

await db.execute(
sql`
CREATE TABLE \`users\` (
\`id\` int,
\`name\` text,
\`invitedBy\` int,
CONSTRAINT \`users_id\` PRIMARY KEY(\`id\`)
);
`,
);

await db.execute(
sql`
CREATE TABLE \`posts\` (
\`id\` int,
\`name\` text,
\`content\` text,
\`userId\` int,
CONSTRAINT \`posts_id\` PRIMARY KEY(\`id\`)
);
`,
);

await db.execute(
sql`
ALTER TABLE \`order_detail\` ADD CONSTRAINT \`order_detail_order_id_order_id_fk\` FOREIGN KEY (\`order_id\`) REFERENCES \`order\`(\`id\`) ON DELETE cascade ON UPDATE no action;
@@ -215,6 +238,18 @@ beforeAll(async () => {
ALTER TABLE \`product\` ADD CONSTRAINT \`product_supplier_id_supplier_id_fk\` FOREIGN KEY (\`supplier_id\`) REFERENCES \`supplier\`(\`id\`) ON DELETE cascade ON UPDATE no action;
`,
);

await db.execute(
sql`
ALTER TABLE \`users\` ADD CONSTRAINT \`users_invitedBy_users_id_fk\` FOREIGN KEY (\`invitedBy\`) REFERENCES \`users\`(\`id\`) ON DELETE cascade ON UPDATE no action;
`,
);

await db.execute(
sql`
ALTER TABLE \`posts\` ADD CONSTRAINT \`posts_userId_users_id_fk\` FOREIGN KEY (\`userId\`) REFERENCES \`users\`(\`id\`) ON DELETE cascade ON UPDATE no action;
`,
);
});

afterAll(async () => {
@@ -379,3 +414,28 @@ test("sequential using of 'with'", async () => {
expect(products.length).toBe(11);
expect(suppliers.length).toBe(11);
});

test('overlapping a foreign key constraint with a one-to-many relation', async () => {
const postsRelation = relations(schema.posts, ({ one }) => ({
user: one(schema.users, { fields: [schema.posts.userId], references: [schema.users.id] }),
}));

const consoleMock = vi.spyOn(console, 'warn').mockImplementation(() => {});

await reset(db, { users: schema.users, posts: schema.posts, postsRelation });
await seed(db, { users: schema.users, posts: schema.posts, postsRelation });
// expecting to get a warning
expect(consoleMock).toBeCalled();
expect(consoleMock).toBeCalledWith(expect.stringMatching(/^You are providing a one-to-many relation.+/));

const users = await db.select().from(schema.users);
const posts = await db.select().from(schema.posts);

expect(users.length).toBe(10);
let predicate = users.every((row) => Object.values(row).every((val) => val !== undefined && val !== null));
expect(predicate).toBe(true);

expect(posts.length).toBe(10);
predicate = posts.every((row) => Object.values(row).every((val) => val !== undefined && val !== null));
expect(predicate).toBe(true);
});
19 changes: 19 additions & 0 deletions drizzle-seed/tests/mysql/mysqlSchema.ts
Original file line number Diff line number Diff line change
@@ -100,3 +100,22 @@ export const details = mysqlTable('order_detail', {
.notNull()
.references(() => products.id, { onDelete: 'cascade' }),
});

export const users = mysqlTable(
'users',
{
id: int().primaryKey(),
name: text(),
invitedBy: int().references((): AnyMySqlColumn => users.id),
},
);

export const posts = mysqlTable(
'posts',
{
id: int().primaryKey(),
name: text(),
content: text(),
userId: int().references(() => users.id),
},
);
46 changes: 23 additions & 23 deletions drizzle-seed/tests/pg/allDataTypesTest/pgSchema.ts
Original file line number Diff line number Diff line change
@@ -64,31 +64,31 @@ export const allDataTypes = schema.table('all_data_types', {
});

export const allArrayDataTypes = schema.table('all_array_data_types', {
// integerArray: integer('integer_array').array(),
// smallintArray: smallint('smallint_array').array(),
// bigintegerArray: bigint('bigint_array', { mode: 'bigint' }).array(),
// bigintNumberArray: bigint('bigint_number_array', { mode: 'number' }).array(),
// booleanArray: boolean('boolean_array').array(),
// textArray: text('text_array').array(),
// varcharArray: varchar('varchar_array', { length: 256 }).array(),
// charArray: char('char_array', { length: 256 }).array(),
// numericArray: numeric('numeric_array').array(),
// decimalArray: decimal('decimal_array').array(),
// realArray: real('real_array').array(),
// doublePrecisionArray: doublePrecision('double_precision_array').array(),
// jsonArray: json('json_array').array(),
// jsonbArray: jsonb('jsonb_array').array(),
// timeArray: time('time_array').array(),
// timestampDateArray: timestamp('timestamp_date_array', { mode: 'date' }).array(),
// timestampStringArray: timestamp('timestamp_string_array', { mode: 'string' }).array(),
integerArray: integer('integer_array').array(),
smallintArray: smallint('smallint_array').array(),
bigintegerArray: bigint('bigint_array', { mode: 'bigint' }).array(),
bigintNumberArray: bigint('bigint_number_array', { mode: 'number' }).array(),
booleanArray: boolean('boolean_array').array(),
textArray: text('text_array').array(),
varcharArray: varchar('varchar_array', { length: 256 }).array(),
charArray: char('char_array', { length: 256 }).array(),
numericArray: numeric('numeric_array').array(),
decimalArray: decimal('decimal_array').array(),
realArray: real('real_array').array(),
doublePrecisionArray: doublePrecision('double_precision_array').array(),
jsonArray: json('json_array').array(),
jsonbArray: jsonb('jsonb_array').array(),
timeArray: time('time_array').array(),
timestampDateArray: timestamp('timestamp_date_array', { mode: 'date' }).array(),
timestampStringArray: timestamp('timestamp_string_array', { mode: 'string' }).array(),
dateStringArray: date('date_string_array', { mode: 'string' }).array(),
dateArray: date('date_array', { mode: 'date' }).array(),
// intervalArray: interval('interval_array').array(),
// pointArray: point('point_array', { mode: 'xy' }).array(),
// pointTupleArray: point('point_tuple_array', { mode: 'tuple' }).array(),
// lineArray: line('line_array', { mode: 'abc' }).array(),
// lineTupleArray: line('line_tuple_array', { mode: 'tuple' }).array(),
// moodEnumArray: moodEnum('mood_enum_array').array(),
intervalArray: interval('interval_array').array(),
pointArray: point('point_array', { mode: 'xy' }).array(),
pointTupleArray: point('point_tuple_array', { mode: 'tuple' }).array(),
lineArray: line('line_array', { mode: 'abc' }).array(),
lineTupleArray: line('line_tuple_array', { mode: 'tuple' }).array(),
moodEnumArray: moodEnum('mood_enum_array').array(),
});

export const ndArrays = schema.table('nd_arrays', {
54 changes: 47 additions & 7 deletions drizzle-seed/tests/pg/pg.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { PGlite } from '@electric-sql/pglite';
import { sql } from 'drizzle-orm';
import { relations, sql } from 'drizzle-orm';
import type { PgliteDatabase } from 'drizzle-orm/pglite';
import { drizzle } from 'drizzle-orm/pglite';
import { afterAll, afterEach, beforeAll, expect, test } from 'vitest';
import { afterAll, afterEach, beforeAll, expect, test, vi } from 'vitest';
import { reset, seed } from '../../src/index.ts';
import * as schema from './pgSchema.ts';

@@ -193,14 +193,29 @@ beforeAll(async () => {

await db.execute(
sql`
create table "seeder_lib_pg"."user"
create table "seeder_lib_pg"."users"
(
id serial
primary key,
name text,
"invitedBy" integer
constraint "user_invitedBy_user_id_fk"
references "seeder_lib_pg"."user"
constraint "users_invitedBy_user_id_fk"
references "seeder_lib_pg"."users"
);
`,
);

await db.execute(
sql`
create table "seeder_lib_pg"."posts"
(
id serial
primary key,
name text,
content text,
"userId" integer
constraint "users_userId_user_id_fk"
references "seeder_lib_pg"."users"
);
`,
);
@@ -385,11 +400,36 @@ test('seeding with identity columns', async () => {
});

test('seeding with self relation', async () => {
await seed(db, { user: schema.user });
await seed(db, { users: schema.users });

const result = await db.select().from(schema.user);
const result = await db.select().from(schema.users);

expect(result.length).toBe(10);
const predicate = result.every((row) => Object.values(row).every((val) => val !== undefined && val !== null));
expect(predicate).toBe(true);
});

test('overlapping a foreign key constraint with a one-to-many relation', async () => {
const postsRelation = relations(schema.posts, ({ one }) => ({
user: one(schema.users, { fields: [schema.posts.userId], references: [schema.users.id] }),
}));

const consoleMock = vi.spyOn(console, 'warn').mockImplementation(() => {});

await reset(db, { users: schema.users, posts: schema.posts, postsRelation });
await seed(db, { users: schema.users, posts: schema.posts, postsRelation });
// expecting to get a warning
expect(consoleMock).toBeCalled();
expect(consoleMock).toBeCalledWith(expect.stringMatching(/^You are providing a one-to-many relation.+/));

const users = await db.select().from(schema.users);
const posts = await db.select().from(schema.posts);

expect(users.length).toBe(10);
let predicate = users.every((row) => Object.values(row).every((val) => val !== undefined && val !== null));
expect(predicate).toBe(true);

expect(posts.length).toBe(10);
predicate = posts.every((row) => Object.values(row).every((val) => val !== undefined && val !== null));
expect(predicate).toBe(true);
});
16 changes: 13 additions & 3 deletions drizzle-seed/tests/pg/pgSchema.ts
Original file line number Diff line number Diff line change
@@ -109,11 +109,21 @@ export const identityColumnsTable = schema.table('identity_columns_table', {
name: text(),
});

export const user = schema.table(
'user',
export const users = schema.table(
'users',
{
id: serial().primaryKey(),
name: text(),
invitedBy: integer().references((): AnyPgColumn => user.id),
invitedBy: integer().references((): AnyPgColumn => users.id),
},
);

export const posts = schema.table(
'posts',
{
id: serial().primaryKey(),
name: text(),
content: text(),
userId: integer().references(() => users.id),
},
);
52 changes: 50 additions & 2 deletions drizzle-seed/tests/sqlite/sqlite.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import BetterSqlite3 from 'better-sqlite3';
import { sql } from 'drizzle-orm';
import { relations, sql } from 'drizzle-orm';
import type { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
import { drizzle } from 'drizzle-orm/better-sqlite3';
import { afterAll, afterEach, beforeAll, expect, test } from 'vitest';
import { afterAll, afterEach, beforeAll, expect, test, vi } from 'vitest';
import { reset, seed } from '../../src/index.ts';
import * as schema from './sqliteSchema.ts';

@@ -122,6 +122,29 @@ beforeAll(async () => {
\`postal_code\` text NOT NULL,
\`country\` text NOT NULL,
\`phone\` text NOT NULL
);
`),
);

db.run(
sql.raw(`
CREATE TABLE \`users\` (
\`id\` integer PRIMARY KEY,
\`name\` text,
\`invitedBy\` integer,
FOREIGN KEY (\`invitedBy\`) REFERENCES \`users\`(\`id\`) ON UPDATE no action ON DELETE cascade
);
`),
);

db.run(
sql.raw(`
CREATE TABLE \`posts\` (
\`id\` integer PRIMARY KEY,
\`name\` text,
\`content\` text,
\`userId\` integer,
FOREIGN KEY (\`userId\`) REFERENCES \`users\`(\`id\`) ON UPDATE no action ON DELETE cascade
);
`),
);
@@ -288,3 +311,28 @@ test("sequential using of 'with'", async () => {
expect(products.length).toBe(11);
expect(suppliers.length).toBe(11);
});

test('overlapping a foreign key constraint with a one-to-many relation', async () => {
const postsRelation = relations(schema.posts, ({ one }) => ({
user: one(schema.users, { fields: [schema.posts.userId], references: [schema.users.id] }),
}));

const consoleMock = vi.spyOn(console, 'warn').mockImplementation(() => {});

await reset(db, { users: schema.users, posts: schema.posts, postsRelation });
await seed(db, { users: schema.users, posts: schema.posts, postsRelation });
// expecting to get a warning
expect(consoleMock).toBeCalled();
expect(consoleMock).toBeCalledWith(expect.stringMatching(/^You are providing a one-to-many relation.+/));

const users = await db.select().from(schema.users);
const posts = await db.select().from(schema.posts);

expect(users.length).toBe(10);
let predicate = users.every((row) => Object.values(row).every((val) => val !== undefined && val !== null));
expect(predicate).toBe(true);

expect(posts.length).toBe(10);
predicate = posts.every((row) => Object.values(row).every((val) => val !== undefined && val !== null));
expect(predicate).toBe(true);
});
25 changes: 25 additions & 0 deletions drizzle-seed/tests/sqlite/sqliteSchema.ts
Original file line number Diff line number Diff line change
@@ -105,3 +105,28 @@ export const details = sqliteTable('order_detail', {
.notNull()
.references(() => products.id, { onDelete: 'cascade' }),
});

export const users = sqliteTable(
'users',
{
id: integer().primaryKey(),
name: text(),
invitedBy: integer(),
},
(table) => ({
reportsToFk: foreignKey(() => ({
columns: [table.invitedBy],
foreignColumns: [table.id],
})),
}),
);

export const posts = sqliteTable(
'posts',
{
id: integer().primaryKey(),
name: text(),
content: text(),
userId: integer().references(() => users.id),
},
);