chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:10:05 +08:00
commit d37d8d293b
1388 changed files with 484182 additions and 0 deletions
@@ -0,0 +1,490 @@
import Docker from 'dockerode';
import { sql } from 'drizzle-orm';
import type { MySql2Database } from 'drizzle-orm/mysql2';
import { drizzle } from 'drizzle-orm/mysql2';
import { reset, seed } from 'drizzle-seed';
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 * as schema from './mysqlSchema.ts';
let mysqlContainer: Docker.Container;
let client: Connection;
let db: MySql2Database;
async function createDockerDB(): Promise<string> {
const docker = new Docker();
const port = await getPort({ port: 3306 });
const image = 'mysql:8';
const pullStream = await docker.pull(image);
await new Promise((resolve, reject) =>
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
docker.modem.followProgress(pullStream, (err) => err ? reject(err) : resolve(err))
);
mysqlContainer = await docker.createContainer({
Image: image,
Env: ['MYSQL_ROOT_PASSWORD=mysql', 'MYSQL_DATABASE=drizzle'],
name: `drizzle-integration-tests-${uuid()}`,
HostConfig: {
AutoRemove: true,
PortBindings: {
'3306/tcp': [{ HostPort: `${port}` }],
},
},
});
await mysqlContainer.start();
return `mysql://root:mysql@127.0.0.1:${port}/drizzle`;
}
const createNorthwindTables = async () => {
await db.execute(
sql`
CREATE TABLE \`customer\` (
\`id\` varchar(256) NOT NULL,
\`company_name\` text NOT NULL,
\`contact_name\` text NOT NULL,
\`contact_title\` text NOT NULL,
\`address\` text NOT NULL,
\`city\` text NOT NULL,
\`postal_code\` text,
\`region\` text,
\`country\` text NOT NULL,
\`phone\` text NOT NULL,
\`fax\` text,
CONSTRAINT \`customer_id\` PRIMARY KEY(\`id\`)
);
`,
);
await db.execute(
sql`
CREATE TABLE \`order_detail\` (
\`unit_price\` float NOT NULL,
\`quantity\` int NOT NULL,
\`discount\` float NOT NULL,
\`order_id\` int NOT NULL,
\`product_id\` int NOT NULL
);
`,
);
await db.execute(
sql`
CREATE TABLE \`employee\` (
\`id\` int NOT NULL,
\`last_name\` text NOT NULL,
\`first_name\` text,
\`title\` text NOT NULL,
\`title_of_courtesy\` text NOT NULL,
\`birth_date\` timestamp NOT NULL,
\`hire_date\` timestamp NOT NULL,
\`address\` text NOT NULL,
\`city\` text NOT NULL,
\`postal_code\` text NOT NULL,
\`country\` text NOT NULL,
\`home_phone\` text NOT NULL,
\`extension\` int NOT NULL,
\`notes\` text NOT NULL,
\`reports_to\` int,
\`photo_path\` text,
CONSTRAINT \`employee_id\` PRIMARY KEY(\`id\`)
);
`,
);
await db.execute(
sql`
CREATE TABLE \`order\` (
\`id\` int NOT NULL,
\`order_date\` timestamp NOT NULL,
\`required_date\` timestamp NOT NULL,
\`shipped_date\` timestamp,
\`ship_via\` int NOT NULL,
\`freight\` float NOT NULL,
\`ship_name\` text NOT NULL,
\`ship_city\` text NOT NULL,
\`ship_region\` text,
\`ship_postal_code\` text,
\`ship_country\` text NOT NULL,
\`customer_id\` varchar(256) NOT NULL,
\`employee_id\` int NOT NULL,
CONSTRAINT \`order_id\` PRIMARY KEY(\`id\`)
);
`,
);
await db.execute(
sql`
CREATE TABLE \`product\` (
\`id\` int NOT NULL,
\`name\` text NOT NULL,
\`quantity_per_unit\` text NOT NULL,
\`unit_price\` float NOT NULL,
\`units_in_stock\` int NOT NULL,
\`units_on_order\` int NOT NULL,
\`reorder_level\` int NOT NULL,
\`discontinued\` int NOT NULL,
\`supplier_id\` int NOT NULL,
CONSTRAINT \`product_id\` PRIMARY KEY(\`id\`)
);
`,
);
await db.execute(
sql`
CREATE TABLE \`supplier\` (
\`id\` int NOT NULL,
\`company_name\` text NOT NULL,
\`contact_name\` text NOT NULL,
\`contact_title\` text NOT NULL,
\`address\` text NOT NULL,
\`city\` text NOT NULL,
\`region\` text,
\`postal_code\` text NOT NULL,
\`country\` text NOT NULL,
\`phone\` text NOT NULL,
CONSTRAINT \`supplier_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;
`,
);
await db.execute(
sql`
ALTER TABLE \`order_detail\` ADD CONSTRAINT \`order_detail_product_id_product_id_fk\` FOREIGN KEY (\`product_id\`) REFERENCES \`product\`(\`id\`) ON DELETE cascade ON UPDATE no action;
`,
);
await db.execute(
sql`
ALTER TABLE \`employee\` ADD CONSTRAINT \`employee_reports_to_employee_id_fk\` FOREIGN KEY (\`reports_to\`) REFERENCES \`employee\`(\`id\`) ON DELETE no action ON UPDATE no action;
`,
);
await db.execute(
sql`
ALTER TABLE \`order\` ADD CONSTRAINT \`order_customer_id_customer_id_fk\` FOREIGN KEY (\`customer_id\`) REFERENCES \`customer\`(\`id\`) ON DELETE cascade ON UPDATE no action;
`,
);
await db.execute(
sql`
ALTER TABLE \`order\` ADD CONSTRAINT \`order_employee_id_employee_id_fk\` FOREIGN KEY (\`employee_id\`) REFERENCES \`employee\`(\`id\`) ON DELETE cascade ON UPDATE no action;
`,
);
await db.execute(
sql`
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;
`,
);
};
const createAllDataTypesTable = async () => {
await db.execute(
sql`
CREATE TABLE \`all_data_types\` (
\`integer\` int,
\`tinyint\` tinyint,
\`smallint\` smallint,
\`mediumint\` mediumint,
\`bigint\` bigint,
\`bigint_number\` bigint,
\`real\` real,
\`decimal\` decimal,
\`double\` double,
\`float\` float,
\`serial\` serial AUTO_INCREMENT,
\`binary\` binary(255),
\`varbinary\` varbinary(256),
\`char\` char(255),
\`varchar\` varchar(256),
\`text\` text,
\`boolean\` boolean,
\`date_string\` date,
\`date\` date,
\`datetime\` datetime,
\`datetimeString\` datetime,
\`time\` time,
\`year\` year,
\`timestamp_date\` timestamp,
\`timestamp_string\` timestamp,
\`json\` json,
\`popularity\` enum('unknown','known','popular')
);
`,
);
};
const createAllGeneratorsTables = async () => {
await db.execute(
sql`
CREATE TABLE \`datetime_table\` (
\`datetime\` datetime
);
`,
);
await db.execute(
sql`
CREATE TABLE \`year_table\` (
\`year\` year
);
`,
);
};
beforeAll(async () => {
const connectionString = await createDockerDB();
const sleep = 1000;
let timeLeft = 40000;
let connected = false;
let lastError: unknown | undefined;
do {
try {
client = await createConnection(connectionString);
await client.connect();
db = drizzle(client);
connected = true;
break;
} catch (e) {
lastError = e;
await new Promise((resolve) => setTimeout(resolve, sleep));
timeLeft -= sleep;
}
} while (timeLeft > 0);
if (!connected) {
console.error('Cannot connect to MySQL');
await client?.end().catch(console.error);
await mysqlContainer?.stop().catch(console.error);
throw lastError;
}
await createNorthwindTables();
await createAllDataTypesTable();
await createAllGeneratorsTables();
});
afterAll(async () => {
await client?.end().catch(console.error);
await mysqlContainer?.stop().catch(console.error);
});
afterEach(async () => {
await reset(db, schema);
});
test('basic seed test', async () => {
await seed(db, schema);
const customers = await db.select().from(schema.customers);
const details = await db.select().from(schema.details);
const employees = await db.select().from(schema.employees);
const orders = await db.select().from(schema.orders);
const products = await db.select().from(schema.products);
const suppliers = await db.select().from(schema.suppliers);
expect(customers.length).toBe(10);
expect(details.length).toBe(10);
expect(employees.length).toBe(10);
expect(orders.length).toBe(10);
expect(products.length).toBe(10);
expect(suppliers.length).toBe(10);
});
test('seed with options.count:11 test', async () => {
await seed(db, schema, { count: 11 });
const customers = await db.select().from(schema.customers);
const details = await db.select().from(schema.details);
const employees = await db.select().from(schema.employees);
const orders = await db.select().from(schema.orders);
const products = await db.select().from(schema.products);
const suppliers = await db.select().from(schema.suppliers);
expect(customers.length).toBe(11);
expect(details.length).toBe(11);
expect(employees.length).toBe(11);
expect(orders.length).toBe(11);
expect(products.length).toBe(11);
expect(suppliers.length).toBe(11);
});
test('redefine(refine) customers count', async () => {
await seed(db, schema, { count: 11 }).refine(() => ({
customers: {
count: 12,
},
}));
const customers = await db.select().from(schema.customers);
const details = await db.select().from(schema.details);
const employees = await db.select().from(schema.employees);
const orders = await db.select().from(schema.orders);
const products = await db.select().from(schema.products);
const suppliers = await db.select().from(schema.suppliers);
expect(customers.length).toBe(12);
expect(details.length).toBe(11);
expect(employees.length).toBe(11);
expect(orders.length).toBe(11);
expect(products.length).toBe(11);
expect(suppliers.length).toBe(11);
});
test('redefine(refine) all tables count', async () => {
await seed(db, schema, { count: 11 }).refine(() => ({
customers: {
count: 12,
},
details: {
count: 13,
},
employees: {
count: 14,
},
orders: {
count: 15,
},
products: {
count: 16,
},
suppliers: {
count: 17,
},
}));
const customers = await db.select().from(schema.customers);
const details = await db.select().from(schema.details);
const employees = await db.select().from(schema.employees);
const orders = await db.select().from(schema.orders);
const products = await db.select().from(schema.products);
const suppliers = await db.select().from(schema.suppliers);
expect(customers.length).toBe(12);
expect(details.length).toBe(13);
expect(employees.length).toBe(14);
expect(orders.length).toBe(15);
expect(products.length).toBe(16);
expect(suppliers.length).toBe(17);
});
test("redefine(refine) orders count using 'with' in customers", async () => {
await seed(db, schema, { count: 11 }).refine(() => ({
customers: {
count: 4,
with: {
orders: 2,
},
},
orders: {
count: 13,
},
}));
const customers = await db.select().from(schema.customers);
const details = await db.select().from(schema.details);
const employees = await db.select().from(schema.employees);
const orders = await db.select().from(schema.orders);
const products = await db.select().from(schema.products);
const suppliers = await db.select().from(schema.suppliers);
expect(customers.length).toBe(4);
expect(details.length).toBe(11);
expect(employees.length).toBe(11);
expect(orders.length).toBe(8);
expect(products.length).toBe(11);
expect(suppliers.length).toBe(11);
});
test("sequential using of 'with'", async () => {
await seed(db, schema, { count: 11 }).refine(() => ({
customers: {
count: 4,
with: {
orders: 2,
},
},
orders: {
count: 12,
with: {
details: 3,
},
},
}));
const customers = await db.select().from(schema.customers);
const details = await db.select().from(schema.details);
const employees = await db.select().from(schema.employees);
const orders = await db.select().from(schema.orders);
const products = await db.select().from(schema.products);
const suppliers = await db.select().from(schema.suppliers);
expect(customers.length).toBe(4);
expect(details.length).toBe(24);
expect(employees.length).toBe(11);
expect(orders.length).toBe(8);
expect(products.length).toBe(11);
expect(suppliers.length).toBe(11);
});
// All data types test -------------------------------
test('basic seed test for all mysql data types', async () => {
await seed(db, schema, { count: 1000 });
const allDataTypes = await db.select().from(schema.allDataTypes);
// every value in each 10 rows does not equal undefined.
const predicate = allDataTypes.every((row) => Object.values(row).every((val) => val !== undefined && val !== null));
expect(predicate).toBe(true);
});
// All generators test-------------------------------
const count = 10000;
test('datetime generator test', async () => {
await seed(db, { datetimeTable: schema.datetimeTable }).refine((funcs) => ({
datetimeTable: {
count,
columns: {
datetime: funcs.datetime(),
},
},
}));
const data = await db.select().from(schema.datetimeTable);
// every value in each row does not equal undefined.
const predicate = data.length !== 0
&& data.every((row) => Object.values(row).every((val) => val !== undefined && val !== null));
expect(predicate).toBe(true);
});
test('year generator test', async () => {
await seed(db, { yearTable: schema.yearTable }).refine((funcs) => ({
yearTable: {
count,
columns: {
year: funcs.year(),
},
},
}));
const data = await db.select().from(schema.yearTable);
// every value in each row does not equal undefined.
const predicate = data.length !== 0
&& data.every((row) => Object.values(row).every((val) => val !== undefined && val !== null));
expect(predicate).toBe(true);
});
@@ -0,0 +1,167 @@
import type { AnyMySqlColumn } from 'drizzle-orm/mysql-core';
import {
bigint,
binary,
boolean,
char,
date,
datetime,
decimal,
double,
float,
int,
json,
mediumint,
mysqlEnum,
mysqlTable,
real,
serial,
smallint,
text,
time,
timestamp,
tinyint,
varbinary,
varchar,
year,
} from 'drizzle-orm/mysql-core';
export const customers = mysqlTable('customer', {
id: varchar('id', { length: 256 }).primaryKey(),
companyName: text('company_name').notNull(),
contactName: text('contact_name').notNull(),
contactTitle: text('contact_title').notNull(),
address: text('address').notNull(),
city: text('city').notNull(),
postalCode: text('postal_code'),
region: text('region'),
country: text('country').notNull(),
phone: text('phone').notNull(),
fax: text('fax'),
});
export const employees = mysqlTable(
'employee',
{
id: int('id').primaryKey(),
lastName: text('last_name').notNull(),
firstName: text('first_name'),
title: text('title').notNull(),
titleOfCourtesy: text('title_of_courtesy').notNull(),
birthDate: timestamp('birth_date').notNull(),
hireDate: timestamp('hire_date').notNull(),
address: text('address').notNull(),
city: text('city').notNull(),
postalCode: text('postal_code').notNull(),
country: text('country').notNull(),
homePhone: text('home_phone').notNull(),
extension: int('extension').notNull(),
notes: text('notes').notNull(),
reportsTo: int('reports_to').references((): AnyMySqlColumn => employees.id),
photoPath: text('photo_path'),
},
);
export const orders = mysqlTable('order', {
id: int('id').primaryKey(),
orderDate: timestamp('order_date').notNull(),
requiredDate: timestamp('required_date').notNull(),
shippedDate: timestamp('shipped_date'),
shipVia: int('ship_via').notNull(),
freight: float('freight').notNull(),
shipName: text('ship_name').notNull(),
shipCity: text('ship_city').notNull(),
shipRegion: text('ship_region'),
shipPostalCode: text('ship_postal_code'),
shipCountry: text('ship_country').notNull(),
customerId: varchar('customer_id', { length: 256 })
.notNull()
.references(() => customers.id, { onDelete: 'cascade' }),
employeeId: int('employee_id')
.notNull()
.references(() => employees.id, { onDelete: 'cascade' }),
});
export const suppliers = mysqlTable('supplier', {
id: int('id').primaryKey(),
companyName: text('company_name').notNull(),
contactName: text('contact_name').notNull(),
contactTitle: text('contact_title').notNull(),
address: text('address').notNull(),
city: text('city').notNull(),
region: text('region'),
postalCode: text('postal_code').notNull(),
country: text('country').notNull(),
phone: text('phone').notNull(),
});
export const products = mysqlTable('product', {
id: int('id').primaryKey(),
name: text('name').notNull(),
quantityPerUnit: text('quantity_per_unit').notNull(),
unitPrice: float('unit_price').notNull(),
unitsInStock: int('units_in_stock').notNull(),
unitsOnOrder: int('units_on_order').notNull(),
reorderLevel: int('reorder_level').notNull(),
discontinued: int('discontinued').notNull(),
supplierId: int('supplier_id')
.notNull()
.references(() => suppliers.id, { onDelete: 'cascade' }),
});
export const details = mysqlTable('order_detail', {
unitPrice: float('unit_price').notNull(),
quantity: int('quantity').notNull(),
discount: float('discount').notNull(),
orderId: int('order_id')
.notNull()
.references(() => orders.id, { onDelete: 'cascade' }),
productId: int('product_id')
.notNull()
.references(() => products.id, { onDelete: 'cascade' }),
});
// All data types table -------------------------------
export const allDataTypes = mysqlTable('all_data_types', {
int: int('integer'),
tinyint: tinyint('tinyint'),
smallint: smallint('smallint'),
mediumint: mediumint('mediumint'),
biginteger: bigint('bigint', { mode: 'bigint' }),
bigintNumber: bigint('bigint_number', { mode: 'number' }),
real: real('real'),
decimal: decimal('decimal'),
double: double('double'),
float: float('float'),
serial: serial('serial'),
binary: binary('binary', { length: 255 }),
varbinary: varbinary('varbinary', { length: 256 }),
char: char('char', { length: 255 }),
varchar: varchar('varchar', { length: 256 }),
text: text('text'),
boolean: boolean('boolean'),
dateString: date('date_string', { mode: 'string' }),
date: date('date', { mode: 'date' }),
datetime: datetime('datetime', { mode: 'date' }),
datetimeString: datetime('datetimeString', { mode: 'string' }),
time: time('time'),
year: year('year'),
timestampDate: timestamp('timestamp_date', { mode: 'date' }),
timestampString: timestamp('timestamp_string', { mode: 'string' }),
json: json('json'),
mysqlEnum: mysqlEnum('popularity', ['unknown', 'known', 'popular']),
});
// All generators tables -------------------------------
export const datetimeTable = mysqlTable('datetime_table', {
datetime: datetime('datetime'),
});
export const yearTable = mysqlTable('year_table', {
year: year('year'),
});
File diff suppressed because it is too large Load Diff
+502
View File
@@ -0,0 +1,502 @@
import type { AnyPgColumn } from 'drizzle-orm/pg-core';
import {
bigint,
bigserial,
boolean,
char,
date,
decimal,
doublePrecision,
integer,
interval,
json,
jsonb,
line,
numeric,
pgEnum,
pgSchema,
point,
real,
serial,
smallint,
smallserial,
text,
time,
timestamp,
uuid,
varchar,
} from 'drizzle-orm/pg-core';
export const schema = pgSchema('seeder_lib_pg');
export const customers = schema.table('customer', {
id: varchar('id', { length: 256 }).primaryKey(),
companyName: text('company_name').notNull(),
contactName: text('contact_name').notNull(),
contactTitle: text('contact_title').notNull(),
address: text('address').notNull(),
city: text('city').notNull(),
postalCode: text('postal_code'),
region: text('region'),
country: text('country').notNull(),
phone: text('phone').notNull(),
fax: text('fax'),
});
export const employees = schema.table(
'employee',
{
id: integer('id').primaryKey(),
lastName: text('last_name').notNull(),
firstName: text('first_name'),
title: text('title').notNull(),
titleOfCourtesy: text('title_of_courtesy').notNull(),
birthDate: timestamp('birth_date').notNull(),
hireDate: timestamp('hire_date').notNull(),
address: text('address').notNull(),
city: text('city').notNull(),
postalCode: text('postal_code').notNull(),
country: text('country').notNull(),
homePhone: text('home_phone').notNull(),
extension: integer('extension').notNull(),
notes: text('notes').notNull(),
reportsTo: integer('reports_to').references((): AnyPgColumn => employees.id),
photoPath: text('photo_path'),
},
);
export const orders = schema.table('order', {
id: integer('id').primaryKey(),
orderDate: timestamp('order_date').notNull(),
requiredDate: timestamp('required_date').notNull(),
shippedDate: timestamp('shipped_date'),
shipVia: integer('ship_via').notNull(),
freight: numeric('freight').notNull(),
shipName: text('ship_name').notNull(),
shipCity: text('ship_city').notNull(),
shipRegion: text('ship_region'),
shipPostalCode: text('ship_postal_code'),
shipCountry: text('ship_country').notNull(),
customerId: text('customer_id')
.notNull()
.references(() => customers.id, { onDelete: 'cascade' }),
employeeId: integer('employee_id')
.notNull()
.references(() => employees.id, { onDelete: 'cascade' }),
});
export const suppliers = schema.table('supplier', {
id: integer('id').primaryKey(),
companyName: text('company_name').notNull(),
contactName: text('contact_name').notNull(),
contactTitle: text('contact_title').notNull(),
address: text('address').notNull(),
city: text('city').notNull(),
region: text('region'),
postalCode: text('postal_code').notNull(),
country: text('country').notNull(),
phone: text('phone').notNull(),
});
export const products = schema.table('product', {
id: integer('id').primaryKey(),
name: text('name').notNull(),
quantityPerUnit: text('quantity_per_unit').notNull(),
unitPrice: numeric('unit_price').notNull(),
unitsInStock: integer('units_in_stock').notNull(),
unitsOnOrder: integer('units_on_order').notNull(),
reorderLevel: integer('reorder_level').notNull(),
discontinued: integer('discontinued').notNull(),
supplierId: integer('supplier_id')
.notNull()
.references(() => suppliers.id, { onDelete: 'cascade' }),
});
export const details = schema.table('order_detail', {
unitPrice: numeric('unit_price').notNull(),
quantity: integer('quantity').notNull(),
discount: numeric('discount').notNull(),
orderId: integer('order_id')
.notNull()
.references(() => orders.id, { onDelete: 'cascade' }),
productId: integer('product_id')
.notNull()
.references(() => products.id, { onDelete: 'cascade' }),
});
// All data types table -------------------------------
export const moodEnum = pgEnum('mood_enum', ['sad', 'ok', 'happy']);
export const allDataTypes = schema.table('all_data_types', {
integer: integer('integer'),
smallint: smallint('smallint'),
biginteger: bigint('bigint', { mode: 'bigint' }),
bigintNumber: bigint('bigint_number', { mode: 'number' }),
serial: serial('serial'),
smallserial: smallserial('smallserial'),
bigserial: bigserial('bigserial', { mode: 'bigint' }),
bigserialNumber: bigserial('bigserial_number', { mode: 'number' }),
boolean: boolean('boolean'),
text: text('text'),
varchar: varchar('varchar', { length: 256 }),
char: char('char', { length: 256 }),
numeric: numeric('numeric'),
decimal: decimal('decimal'),
real: real('real'),
doublePrecision: doublePrecision('double_precision'),
json: json('json'),
jsonb: jsonb('jsonb'),
time: time('time'),
timestampDate: timestamp('timestamp_date', { mode: 'date' }),
timestampString: timestamp('timestamp_string', { mode: 'string' }),
dateString: date('date_string', { mode: 'string' }),
date: date('date', { mode: 'date' }),
interval: interval('interval'),
point: point('point', { mode: 'xy' }),
pointTuple: point('point_tuple', { mode: 'tuple' }),
line: line('line', { mode: 'abc' }),
lineTuple: line('line_tuple', { mode: 'tuple' }),
moodEnum: moodEnum('mood_enum'),
uuid: uuid('uuid'),
});
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(),
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(),
});
export const ndArrays = schema.table('nd_arrays', {
integer1DArray: integer('integer_1d_array').array(3),
integer2DArray: integer('integer_2d_array').array(3).array(4),
integer3DArray: integer('integer_3d_array').array(3).array(4).array(5),
integer4DArray: integer('integer_4d_array').array(3).array(4).array(5).array(6),
});
// All generators tables -------------------------------
export const enumTable = schema.table('enum_table', {
mood: moodEnum('mood_enum'),
});
export const defaultTable = schema.table('default_table', {
defaultString: text('default_string'),
});
export const defaultArrayTable = schema.table('default_array_table', {
defaultString: text('default_string').array(),
});
export const valuesFromArrayTable = schema.table('values_from_array_table', {
valuesFromArrayNotNull: varchar('values_from_array_not_null', { length: 256 }).notNull(),
valuesFromArrayWeightedNotNull: varchar('values_from_array_weighted_not_null', { length: 256 }).notNull(),
});
export const valuesFromArrayUniqueTable = schema.table('values_from_array_unique_table', {
valuesFromArray: varchar('values_from_array', { length: 256 }).unique(),
valuesFromArrayNotNull: varchar('values_from_array_not_null', { length: 256 }).unique().notNull(),
valuesFromArrayWeighted: varchar('values_from_array_weighted', { length: 256 }).unique(),
valuesFromArrayWeightedNotNull: varchar('values_from_array_weighted_not_null', { length: 256 }).unique().notNull(),
});
export const valuesFromArrayArrayTable = schema.table('values_from_array_array_table', {
valuesFromArray: varchar('values_from_array', { length: 256 }).array(),
});
export const intPrimaryKeyTable = schema.table('int_primary_key_table', {
intPrimaryKey: integer('int_primary_key').unique(),
});
export const numberTable = schema.table('number_table', {
number: real('number'),
});
export const numberUniqueTable = schema.table('number_unique_table', {
numberUnique: real('number_unique').unique(),
});
export const numberArrayTable = schema.table('number_array_table', {
number: real('number').array(),
});
export const intTable = schema.table('int_table', {
int: integer('int'),
});
export const intUniqueTable = schema.table('int_unique_table', {
intUnique: integer('int_unique').unique(),
});
export const intArrayTable = schema.table('int_array_table', {
int: integer('int').array(),
});
export const booleanTable = schema.table('boolean_table', {
boolean: boolean('boolean'),
});
export const booleanArrayTable = schema.table('boolean_array_table', {
boolean: boolean('boolean').array(),
});
export const dateTable = schema.table('date_table', {
date: date('date'),
});
// TODO: add tests for data type with different modes
export const dateArrayTable = schema.table('date_array_table', {
date: date('date', { mode: 'date' }).array(),
dateString: date('date_string', { mode: 'string' }).array(),
});
export const timeTable = schema.table('time_table', {
time: time('time'),
});
export const timeArrayTable = schema.table('time_array_table', {
time: time('time').array(),
});
export const timestampTable = schema.table('timestamp_table', {
timestamp: timestamp('timestamp'),
});
export const timestampArrayTable = schema.table('timestamp_array_table', {
timestamp: timestamp('timestamp').array(),
});
export const jsonTable = schema.table('json_table', {
json: json('json'),
});
export const jsonArrayTable = schema.table('json_array_table', {
json: json('json').array(),
});
export const intervalTable = schema.table('interval_table', {
interval: interval('interval'),
});
export const intervalUniqueTable = schema.table('interval_unique_table', {
intervalUnique: interval('interval_unique').unique(),
});
export const intervalArrayTable = schema.table('interval_array_table', {
interval: interval('interval').array(),
});
export const stringTable = schema.table('string_table', {
string: text('string'),
});
export const stringUniqueTable = schema.table('string_unique_table', {
stringUnique: varchar('string_unique', { length: 256 }).unique(),
});
export const stringArrayTable = schema.table('string_array_table', {
string: text('string').array(),
});
export const emailTable = schema.table('email_table', {
email: varchar('email', { length: 256 }).unique(),
});
export const emailArrayTable = schema.table('email_array_table', {
email: varchar('email', { length: 256 }).array(),
});
export const firstNameTable = schema.table('first_name_table', {
firstName: varchar('first_name', { length: 256 }),
});
export const firstNameUniqueTable = schema.table('first_name_unique_table', {
firstNameUnique: varchar('first_name_unique', { length: 256 }).unique(),
});
export const firstNameArrayTable = schema.table('first_name_array_table', {
firstName: varchar('first_name', { length: 256 }).array(),
});
export const lastNameTable = schema.table('last_name_table', {
lastName: varchar('last_name', { length: 256 }),
});
export const lastNameUniqueTable = schema.table('last_name_unique_table', {
lastNameUnique: varchar('last_name_unique', { length: 256 }).unique(),
});
export const lastNameArrayTable = schema.table('last_name_array_table', {
lastName: varchar('last_name', { length: 256 }).array(),
});
export const fullNameTable = schema.table('full_name__table', {
fullName: varchar('full_name_', { length: 256 }),
});
export const fullNameUniqueTable = schema.table('full_name_unique_table', {
fullNameUnique: varchar('full_name_unique', { length: 256 }).unique(),
});
export const fullNameArrayTable = schema.table('full_name_array_table', {
fullName: varchar('full_name', { length: 256 }).array(),
});
export const countryTable = schema.table('country_table', {
country: varchar('country', { length: 256 }),
});
export const countryUniqueTable = schema.table('country_unique_table', {
countryUnique: varchar('country_unique', { length: 256 }).unique(),
});
export const countryArrayTable = schema.table('country_array_table', {
country: varchar('country', { length: 256 }).array(),
});
export const cityTable = schema.table('city_table', {
city: varchar('city', { length: 256 }),
});
export const cityUniqueTable = schema.table('city_unique_table', {
cityUnique: varchar('city_unique', { length: 256 }).unique(),
});
export const cityArrayTable = schema.table('city_array_table', {
city: varchar('city', { length: 256 }).array(),
});
export const streetAddressTable = schema.table('street_address_table', {
streetAddress: varchar('street_address', { length: 256 }),
});
export const streetAddressUniqueTable = schema.table('street_address_unique_table', {
streetAddressUnique: varchar('street_address_unique', { length: 256 }).unique(),
});
export const streetAddressArrayTable = schema.table('street_address_array_table', {
streetAddress: varchar('street_address', { length: 256 }).array(),
});
export const jobTitleTable = schema.table('job_title_table', {
jobTitle: text('job_title'),
});
export const jobTitleArrayTable = schema.table('job_title_array_table', {
jobTitle: text('job_title').array(),
});
export const postcodeTable = schema.table('postcode_table', {
postcode: varchar('postcode', { length: 256 }),
});
export const postcodeUniqueTable = schema.table('postcode_unique_table', {
postcodeUnique: varchar('postcode_unique', { length: 256 }).unique(),
});
export const postcodeArrayTable = schema.table('postcode_array_table', {
postcode: varchar('postcode', { length: 256 }).array(),
});
export const stateTable = schema.table('state_table', {
state: text('state'),
});
export const stateArrayTable = schema.table('state_array_table', {
state: text('state').array(),
});
export const companyNameTable = schema.table('company_name_table', {
companyName: text('company_name'),
});
export const companyNameUniqueTable = schema.table('company_name_unique_table', {
companyNameUnique: varchar('company_name_unique', { length: 256 }).unique(),
});
export const companyNameArrayTable = schema.table('company_name_array_table', {
companyName: text('company_name').array(),
});
export const loremIpsumTable = schema.table('lorem_ipsum_table', {
loremIpsum: text('lorem_ipsum'),
});
export const loremIpsumArrayTable = schema.table('lorem_ipsum_array_table', {
loremIpsum: text('lorem_ipsum').array(),
});
export const pointTable = schema.table('point_table', {
point: point('point'),
});
export const pointArrayTable = schema.table('point_array_table', {
point: point('point').array(),
});
export const lineTable = schema.table('line_table', {
line: line('line'),
});
export const lineArrayTable = schema.table('line_array_table', {
line: line('line').array(),
});
// export const pointUniqueTable = schema.table("point_unique_table", {
// pointUnique: point("point_unique").unique(),
// });
// export const lineUniqueTable = schema.table("line_unique_table", {
// lineUnique: line("line_unique").unique(),
// });
export const phoneNumberTable = schema.table('phone_number_table', {
phoneNumber: varchar('phoneNumber', { length: 256 }).unique(),
phoneNumberTemplate: varchar('phone_number_template', { length: 256 }).unique(),
phoneNumberPrefixes: varchar('phone_number_prefixes', { length: 256 }).unique(),
});
export const phoneNumberArrayTable = schema.table('phone_number_array_table', {
phoneNumber: varchar('phoneNumber', { length: 256 }).array(),
phoneNumberTemplate: varchar('phone_number_template', { length: 256 }).array(),
phoneNumberPrefixes: varchar('phone_number_prefixes', { length: 256 }).array(),
});
export const weightedRandomTable = schema.table('weighted_random_table', {
weightedRandom: varchar('weighted_random', { length: 256 }),
});
export const weightedRandomWithUniqueGensTable = schema.table('weighted_random_with_unique_gens_table', {
weightedRandomWithUniqueGens: varchar('weighted_random_with_unique_gens', { length: 256 }).unique(),
});
export const identityColumnsTable = schema.table('identity_columns_table', {
id: integer('id').generatedAlwaysAsIdentity(),
id1: integer('id1'),
name: text('name'),
});
@@ -0,0 +1,322 @@
import BetterSqlite3 from 'better-sqlite3';
import { sql } from 'drizzle-orm';
import type { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
import { drizzle } from 'drizzle-orm/better-sqlite3';
import { reset, seed } from 'drizzle-seed';
import { afterAll, afterEach, beforeAll, expect, test } from 'vitest';
import * as schema from './sqliteSchema.ts';
let client: BetterSqlite3.Database;
let db: BetterSQLite3Database;
beforeAll(async () => {
client = new BetterSqlite3(':memory:');
db = drizzle(client);
db.run(
sql.raw(`
CREATE TABLE \`customer\` (
\`id\` text PRIMARY KEY NOT NULL,
\`company_name\` text NOT NULL,
\`contact_name\` text NOT NULL,
\`contact_title\` text NOT NULL,
\`address\` text NOT NULL,
\`city\` text NOT NULL,
\`postal_code\` text,
\`region\` text,
\`country\` text NOT NULL,
\`phone\` text NOT NULL,
\`fax\` text
);
`),
);
db.run(
sql.raw(`
CREATE TABLE \`order_detail\` (
\`unit_price\` numeric NOT NULL,
\`quantity\` integer NOT NULL,
\`discount\` numeric NOT NULL,
\`order_id\` integer NOT NULL,
\`product_id\` integer NOT NULL,
FOREIGN KEY (\`order_id\`) REFERENCES \`order\`(\`id\`) ON UPDATE no action ON DELETE cascade,
FOREIGN KEY (\`product_id\`) REFERENCES \`product\`(\`id\`) ON UPDATE no action ON DELETE cascade
);
`),
);
db.run(
sql.raw(`
CREATE TABLE \`employee\` (
\`id\` integer PRIMARY KEY NOT NULL,
\`last_name\` text NOT NULL,
\`first_name\` text,
\`title\` text NOT NULL,
\`title_of_courtesy\` text NOT NULL,
\`birth_date\` integer NOT NULL,
\`hire_date\` integer NOT NULL,
\`address\` text NOT NULL,
\`city\` text NOT NULL,
\`postal_code\` text NOT NULL,
\`country\` text NOT NULL,
\`home_phone\` text NOT NULL,
\`extension\` integer NOT NULL,
\`notes\` text NOT NULL,
\`reports_to\` integer,
\`photo_path\` text,
FOREIGN KEY (\`reports_to\`) REFERENCES \`employee\`(\`id\`) ON UPDATE no action ON DELETE no action
);
`),
);
db.run(
sql.raw(`
CREATE TABLE \`order\` (
\`id\` integer PRIMARY KEY NOT NULL,
\`order_date\` integer NOT NULL,
\`required_date\` integer NOT NULL,
\`shipped_date\` integer,
\`ship_via\` integer NOT NULL,
\`freight\` numeric NOT NULL,
\`ship_name\` text NOT NULL,
\`ship_city\` text NOT NULL,
\`ship_region\` text,
\`ship_postal_code\` text,
\`ship_country\` text NOT NULL,
\`customer_id\` text NOT NULL,
\`employee_id\` integer NOT NULL,
FOREIGN KEY (\`customer_id\`) REFERENCES \`customer\`(\`id\`) ON UPDATE no action ON DELETE cascade,
FOREIGN KEY (\`employee_id\`) REFERENCES \`employee\`(\`id\`) ON UPDATE no action ON DELETE cascade
);
`),
);
db.run(
sql.raw(`
CREATE TABLE \`product\` (
\`id\` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
\`name\` text NOT NULL,
\`quantity_per_unit\` text NOT NULL,
\`unit_price\` numeric NOT NULL,
\`units_in_stock\` integer NOT NULL,
\`units_on_order\` integer NOT NULL,
\`reorder_level\` integer NOT NULL,
\`discontinued\` integer NOT NULL,
\`supplier_id\` integer NOT NULL,
FOREIGN KEY (\`supplier_id\`) REFERENCES \`supplier\`(\`id\`) ON UPDATE no action ON DELETE cascade
);
`),
);
db.run(
sql.raw(`
CREATE TABLE \`supplier\` (
\`id\` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
\`company_name\` text NOT NULL,
\`contact_name\` text NOT NULL,
\`contact_title\` text NOT NULL,
\`address\` text NOT NULL,
\`city\` text NOT NULL,
\`region\` text,
\`postal_code\` text NOT NULL,
\`country\` text NOT NULL,
\`phone\` text NOT NULL
);
`),
);
// All data types test -------------------------------
db.run(
sql.raw(`
CREATE TABLE \`all_data_types\` (
\`integer_number\` integer,
\`integer_boolean\` integer,
\`integer_timestamp\` integer,
\`integer_timestampms\` integer,
\`real\` real,
\`text\` text,
\`text_json\` text,
\`blob_bigint\` blob,
\`blob_buffer\` blob,
\`blob_json\` blob,
\`numeric\` numeric
);
`),
);
});
afterAll(async () => {
client.close();
});
afterEach(async () => {
await reset(db, schema);
});
test('basic seed test', async () => {
await seed(db, schema);
const customers = await db.select().from(schema.customers);
const details = await db.select().from(schema.details);
const employees = await db.select().from(schema.employees);
const orders = await db.select().from(schema.orders);
const products = await db.select().from(schema.products);
const suppliers = await db.select().from(schema.suppliers);
expect(customers.length).toBe(10);
expect(details.length).toBe(10);
expect(employees.length).toBe(10);
expect(orders.length).toBe(10);
expect(products.length).toBe(10);
expect(suppliers.length).toBe(10);
});
test('seed with options.count:11 test', async () => {
await seed(db, schema, { count: 11 });
const customers = await db.select().from(schema.customers);
const details = await db.select().from(schema.details);
const employees = await db.select().from(schema.employees);
const orders = await db.select().from(schema.orders);
const products = await db.select().from(schema.products);
const suppliers = await db.select().from(schema.suppliers);
expect(customers.length).toBe(11);
expect(details.length).toBe(11);
expect(employees.length).toBe(11);
expect(orders.length).toBe(11);
expect(products.length).toBe(11);
expect(suppliers.length).toBe(11);
});
test('redefine(refine) customers count', async () => {
await seed(db, schema, { count: 11 }).refine(() => ({
customers: {
count: 12,
},
}));
const customers = await db.select().from(schema.customers);
const details = await db.select().from(schema.details);
const employees = await db.select().from(schema.employees);
const orders = await db.select().from(schema.orders);
const products = await db.select().from(schema.products);
const suppliers = await db.select().from(schema.suppliers);
expect(customers.length).toBe(12);
expect(details.length).toBe(11);
expect(employees.length).toBe(11);
expect(orders.length).toBe(11);
expect(products.length).toBe(11);
expect(suppliers.length).toBe(11);
});
test('redefine(refine) all tables count', async () => {
await seed(db, schema, { count: 11 }).refine(() => ({
customers: {
count: 12,
},
details: {
count: 13,
},
employees: {
count: 14,
},
orders: {
count: 15,
},
products: {
count: 16,
},
suppliers: {
count: 17,
},
}));
const customers = await db.select().from(schema.customers);
const details = await db.select().from(schema.details);
const employees = await db.select().from(schema.employees);
const orders = await db.select().from(schema.orders);
const products = await db.select().from(schema.products);
const suppliers = await db.select().from(schema.suppliers);
expect(customers.length).toBe(12);
expect(details.length).toBe(13);
expect(employees.length).toBe(14);
expect(orders.length).toBe(15);
expect(products.length).toBe(16);
expect(suppliers.length).toBe(17);
});
test("redefine(refine) orders count using 'with' in customers", async () => {
await seed(db, schema, { count: 11 }).refine(() => ({
customers: {
count: 4,
with: {
orders: 2,
},
},
orders: {
count: 13,
},
}));
const customers = await db.select().from(schema.customers);
const details = await db.select().from(schema.details);
const employees = await db.select().from(schema.employees);
const orders = await db.select().from(schema.orders);
const products = await db.select().from(schema.products);
const suppliers = await db.select().from(schema.suppliers);
expect(customers.length).toBe(4);
expect(details.length).toBe(11);
expect(employees.length).toBe(11);
expect(orders.length).toBe(8);
expect(products.length).toBe(11);
expect(suppliers.length).toBe(11);
});
test("sequential using of 'with'", async () => {
await seed(db, schema, { count: 11 }).refine(() => ({
customers: {
count: 4,
with: {
orders: 2,
},
},
orders: {
count: 12,
with: {
details: 3,
},
},
}));
const customers = await db.select().from(schema.customers);
const details = await db.select().from(schema.details);
const employees = await db.select().from(schema.employees);
const orders = await db.select().from(schema.orders);
const products = await db.select().from(schema.products);
const suppliers = await db.select().from(schema.suppliers);
expect(customers.length).toBe(4);
expect(details.length).toBe(24);
expect(employees.length).toBe(11);
expect(orders.length).toBe(8);
expect(products.length).toBe(11);
expect(suppliers.length).toBe(11);
});
// All data types test -------------------------------
test('basic seed test for all sqlite data types', async () => {
// migrate(db, { migrationsFolder: path.join(__dirname, "sqliteMigrations") });
await seed(db, { allDataTypes: schema.allDataTypes }, { count: 10000 });
const allDataTypes = await db.select().from(schema.allDataTypes);
// every value in each 10 rows does not equal undefined.
const predicate = allDataTypes.every((row) => Object.values(row).every((val) => val !== undefined && val !== null));
expect(predicate).toBe(true);
});
@@ -0,0 +1,122 @@
import { blob, foreignKey, integer, numeric, real, sqliteTable, text } from 'drizzle-orm/sqlite-core';
export const customers = sqliteTable('customer', {
id: text('id').primaryKey(),
companyName: text('company_name').notNull(),
contactName: text('contact_name').notNull(),
contactTitle: text('contact_title').notNull(),
address: text('address').notNull(),
city: text('city').notNull(),
postalCode: text('postal_code'),
region: text('region'),
country: text('country').notNull(),
phone: text('phone').notNull(),
fax: text('fax'),
});
export const employees = sqliteTable(
'employee',
{
id: integer('id').primaryKey(),
lastName: text('last_name').notNull(),
firstName: text('first_name'),
title: text('title').notNull(),
titleOfCourtesy: text('title_of_courtesy').notNull(),
birthDate: integer('birth_date', { mode: 'timestamp' }).notNull(),
hireDate: integer('hire_date', { mode: 'timestamp' }).notNull(),
address: text('address').notNull(),
city: text('city').notNull(),
postalCode: text('postal_code').notNull(),
country: text('country').notNull(),
homePhone: text('home_phone').notNull(),
extension: integer('extension').notNull(),
notes: text('notes').notNull(),
reportsTo: integer('reports_to'),
photoPath: text('photo_path'),
},
(table) => ({
reportsToFk: foreignKey(() => ({
columns: [table.reportsTo],
foreignColumns: [table.id],
})),
}),
);
export const orders = sqliteTable('order', {
id: integer('id').primaryKey(),
orderDate: integer('order_date', { mode: 'timestamp' }).notNull(),
requiredDate: integer('required_date', { mode: 'timestamp' }).notNull(),
shippedDate: integer('shipped_date', { mode: 'timestamp' }),
shipVia: integer('ship_via').notNull(),
freight: numeric('freight').notNull(),
shipName: text('ship_name').notNull(),
shipCity: text('ship_city').notNull(),
shipRegion: text('ship_region'),
shipPostalCode: text('ship_postal_code'),
shipCountry: text('ship_country').notNull(),
customerId: text('customer_id')
.notNull()
.references(() => customers.id, { onDelete: 'cascade' }),
employeeId: integer('employee_id')
.notNull()
.references(() => employees.id, { onDelete: 'cascade' }),
});
export const suppliers = sqliteTable('supplier', {
id: integer('id').primaryKey({ autoIncrement: true }),
companyName: text('company_name').notNull(),
contactName: text('contact_name').notNull(),
contactTitle: text('contact_title').notNull(),
address: text('address').notNull(),
city: text('city').notNull(),
region: text('region'),
postalCode: text('postal_code').notNull(),
country: text('country').notNull(),
phone: text('phone').notNull(),
});
export const products = sqliteTable('product', {
id: integer('id').primaryKey({ autoIncrement: true }),
name: text('name').notNull(),
quantityPerUnit: text('quantity_per_unit').notNull(),
unitPrice: numeric('unit_price').notNull(),
unitsInStock: integer('units_in_stock').notNull(),
unitsOnOrder: integer('units_on_order').notNull(),
reorderLevel: integer('reorder_level').notNull(),
discontinued: integer('discontinued').notNull(),
supplierId: integer('supplier_id')
.notNull()
.references(() => suppliers.id, { onDelete: 'cascade' }),
});
export const details = sqliteTable('order_detail', {
unitPrice: numeric('unit_price').notNull(),
quantity: integer('quantity').notNull(),
discount: numeric('discount').notNull(),
orderId: integer('order_id')
.notNull()
.references(() => orders.id, { onDelete: 'cascade' }),
productId: integer('product_id')
.notNull()
.references(() => products.id, { onDelete: 'cascade' }),
});
// All data types table -------------------------------
export const allDataTypes = sqliteTable('all_data_types', {
integerNumber: integer('integer_number', { mode: 'number' }),
integerBoolean: integer('integer_boolean', { mode: 'boolean' }),
integerTimestamp: integer('integer_timestamp', { mode: 'timestamp' }),
integerTimestampms: integer('integer_timestampms', { mode: 'timestamp_ms' }),
real: real('real'),
text: text('text', { mode: 'text' }),
textJson: text('text_json', { mode: 'json' }),
blobBigint: blob('blob_bigint', { mode: 'bigint' }),
blobBuffer: blob('blob_buffer', { mode: 'buffer' }),
blobJson: blob('blob_json', { mode: 'json' }),
numeric: numeric('numeric'),
});