chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
import { describe, it } from 'vitest';
|
||||
import { toCamelCase, toSnakeCase } from '~/casing';
|
||||
|
||||
describe.concurrent('casing', () => {
|
||||
it('transforms to snake case', ({ expect }) => {
|
||||
expect(toSnakeCase('drizzleKit')).toEqual('drizzle_kit');
|
||||
});
|
||||
|
||||
it('transforms an uppercase acronym/abbreviation to snake case', ({ expect }) => {
|
||||
expect(toSnakeCase('drizzleORM')).toEqual('drizzle_orm');
|
||||
});
|
||||
|
||||
it('transforms a camel case acronym/abbreviation to snake case', ({ expect }) => {
|
||||
expect(toSnakeCase('drizzleOrm')).toEqual('drizzle_orm');
|
||||
});
|
||||
|
||||
it('transforms an uppercase acronym/abbreviation followed by a word to snake case', ({ expect }) => {
|
||||
expect(toSnakeCase('drizzleORMAndKit')).toEqual('drizzle_orm_and_kit');
|
||||
});
|
||||
|
||||
it('transforms a camel case acronym/abbreviation followed by a word to snake case', ({ expect }) => {
|
||||
expect(toSnakeCase('drizzleOrmAndKit')).toEqual('drizzle_orm_and_kit');
|
||||
});
|
||||
|
||||
it('transforms to camel case 1', ({ expect }) => {
|
||||
expect(toCamelCase('drizzle_kit')).toEqual('drizzleKit');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,299 @@
|
||||
import { Client } from '@planetscale/database';
|
||||
import { connect } from '@tidbcloud/serverless';
|
||||
import { beforeEach, describe, it } from 'vitest';
|
||||
import { alias, boolean, int, mysqlSchema, mysqlTable, serial, text, union } from '~/mysql-core';
|
||||
import { drizzle as planetscale } from '~/planetscale-serverless';
|
||||
import { relations } from '~/relations';
|
||||
import { asc, eq, sql } from '~/sql';
|
||||
import { drizzle as mysql } from '~/tidb-serverless';
|
||||
|
||||
const testSchema = mysqlSchema('test');
|
||||
const users = mysqlTable('users', {
|
||||
id: serial().primaryKey(),
|
||||
first_name: text().notNull(),
|
||||
last_name: text().notNull(),
|
||||
// Test that custom aliases remain
|
||||
age: int('AGE'),
|
||||
});
|
||||
const usersRelations = relations(users, ({ one }) => ({
|
||||
developers: one(developers),
|
||||
}));
|
||||
const developers = testSchema.table('developers', {
|
||||
user_id: serial().primaryKey().references(() => users.id),
|
||||
uses_drizzle_orm: boolean().notNull(),
|
||||
});
|
||||
const developersRelations = relations(developers, ({ one }) => ({
|
||||
user: one(users, {
|
||||
fields: [developers.user_id],
|
||||
references: [users.id],
|
||||
}),
|
||||
}));
|
||||
const devs = alias(developers, 'devs');
|
||||
const schema = { users, usersRelations, developers, developersRelations };
|
||||
|
||||
const db = mysql(connect({}), { schema, casing: 'camelCase' });
|
||||
const ps = planetscale(new Client({}), { schema, casing: 'camelCase' });
|
||||
|
||||
const usersCache = {
|
||||
'public.users.id': 'id',
|
||||
'public.users.first_name': 'firstName',
|
||||
'public.users.last_name': 'lastName',
|
||||
'public.users.AGE': 'age',
|
||||
};
|
||||
const developersCache = {
|
||||
'test.developers.user_id': 'userId',
|
||||
'test.developers.uses_drizzle_orm': 'usesDrizzleOrm',
|
||||
};
|
||||
const cache = {
|
||||
...usersCache,
|
||||
...developersCache,
|
||||
};
|
||||
|
||||
const fullName = sql`${users.first_name} || ' ' || ${users.last_name}`.as('name');
|
||||
|
||||
describe('mysql to snake case', () => {
|
||||
beforeEach(() => {
|
||||
ps.dialect.casing.clearCache();
|
||||
db.dialect.casing.clearCache();
|
||||
});
|
||||
|
||||
it('select', ({ expect }) => {
|
||||
const query = db
|
||||
.select({ name: fullName, age: users.age })
|
||||
.from(users)
|
||||
.leftJoin(developers, eq(users.id, developers.user_id))
|
||||
.orderBy(asc(users.first_name));
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
"select `users`.`firstName` || ' ' || `users`.`lastName` as `name`, `users`.`AGE` from `users` left join `test`.`developers` on `users`.`id` = `test`.`developers`.`userId` order by `users`.`firstName` asc",
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('select (with alias)', ({ expect }) => {
|
||||
const query = db
|
||||
.select({ firstName: users.first_name })
|
||||
.from(users)
|
||||
.leftJoin(devs, eq(users.id, devs.user_id));
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'select `users`.`firstName` from `users` left join `test`.`developers` `devs` on `users`.`id` = `devs`.`userId`',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('with CTE', ({ expect }) => {
|
||||
const cte = db.$with('cte').as(db.select({ name: fullName }).from(users));
|
||||
const query = db.with(cte).select().from(cte);
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: "with `cte` as (select `firstName` || ' ' || `lastName` as `name` from `users`) select `name` from `cte`",
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('with CTE (with query builder)', ({ expect }) => {
|
||||
const cte = db.$with('cte').as((qb) => qb.select({ name: fullName }).from(users));
|
||||
const query = db.with(cte).select().from(cte);
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: "with `cte` as (select `firstName` || ' ' || `lastName` as `name` from `users`) select `name` from `cte`",
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('set operator', ({ expect }) => {
|
||||
const query = db
|
||||
.select({ firstName: users.first_name })
|
||||
.from(users)
|
||||
.union(db.select({ firstName: users.first_name }).from(users));
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: '(select `firstName` from `users`) union (select `firstName` from `users`)',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('set operator (function)', ({ expect }) => {
|
||||
const query = union(
|
||||
db.select({ firstName: users.first_name }).from(users),
|
||||
db.select({ firstName: users.first_name }).from(users),
|
||||
);
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: '(select `firstName` from `users`) union (select `firstName` from `users`)',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('query (find first)', ({ expect }) => {
|
||||
const query = db.query.users.findFirst({
|
||||
columns: {
|
||||
id: true,
|
||||
age: true,
|
||||
},
|
||||
extras: {
|
||||
fullName,
|
||||
},
|
||||
where: eq(users.id, 1),
|
||||
with: {
|
||||
developers: {
|
||||
columns: {
|
||||
uses_drizzle_orm: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
"select `users`.`id`, `users`.`AGE`, `users`.`firstName` || ' ' || `users`.`lastName` as `name`, `users_developers`.`data` as `developers` from `users` `users` left join lateral (select json_array(`users_developers`.`usesDrizzleOrm`) as `data` from (select * from `test`.`developers` `users_developers` where `users_developers`.`userId` = `users`.`id` limit ?) `users_developers`) `users_developers` on true where `users`.`id` = ? limit ?",
|
||||
params: [1, 1, 1],
|
||||
typings: ['none', 'none', 'none'],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('query (find first, planetscale)', ({ expect }) => {
|
||||
const query = ps.query.users.findFirst({
|
||||
columns: {
|
||||
id: true,
|
||||
age: true,
|
||||
},
|
||||
extras: {
|
||||
fullName,
|
||||
},
|
||||
where: eq(users.id, 1),
|
||||
with: {
|
||||
developers: {
|
||||
columns: {
|
||||
uses_drizzle_orm: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
"select `id`, `AGE`, `firstName` || ' ' || `lastName` as `name`, (select json_array(`usesDrizzleOrm`) from (select * from `test`.`developers` `users_developers` where `users_developers`.`userId` = `users`.`id` limit ?) `users_developers`) as `developers` from `users` `users` where `users`.`id` = ? limit ?",
|
||||
params: [1, 1, 1],
|
||||
typings: ['none', 'none', 'none'],
|
||||
});
|
||||
expect(ps.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('query (find many)', ({ expect }) => {
|
||||
const query = db.query.users.findMany({
|
||||
columns: {
|
||||
id: true,
|
||||
age: true,
|
||||
},
|
||||
extras: {
|
||||
fullName,
|
||||
},
|
||||
where: eq(users.id, 1),
|
||||
with: {
|
||||
developers: {
|
||||
columns: {
|
||||
uses_drizzle_orm: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
"select `users`.`id`, `users`.`AGE`, `users`.`firstName` || ' ' || `users`.`lastName` as `name`, `users_developers`.`data` as `developers` from `users` `users` left join lateral (select json_array(`users_developers`.`usesDrizzleOrm`) as `data` from (select * from `test`.`developers` `users_developers` where `users_developers`.`userId` = `users`.`id` limit ?) `users_developers`) `users_developers` on true where `users`.`id` = ?",
|
||||
params: [1, 1],
|
||||
typings: ['none', 'none'],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('query (find many, planetscale)', ({ expect }) => {
|
||||
const query = ps.query.users.findMany({
|
||||
columns: {
|
||||
id: true,
|
||||
age: true,
|
||||
},
|
||||
extras: {
|
||||
fullName,
|
||||
},
|
||||
where: eq(users.id, 1),
|
||||
with: {
|
||||
developers: {
|
||||
columns: {
|
||||
uses_drizzle_orm: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
"select `id`, `AGE`, `firstName` || ' ' || `lastName` as `name`, (select json_array(`usesDrizzleOrm`) from (select * from `test`.`developers` `users_developers` where `users_developers`.`userId` = `users`.`id` limit ?) `users_developers`) as `developers` from `users` `users` where `users`.`id` = ?",
|
||||
params: [1, 1],
|
||||
typings: ['none', 'none'],
|
||||
});
|
||||
expect(ps.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('insert', ({ expect }) => {
|
||||
const query = db
|
||||
.insert(users)
|
||||
.values({ first_name: 'John', last_name: 'Doe', age: 30 });
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: 'insert into `users` (`id`, `firstName`, `lastName`, `AGE`) values (default, ?, ?, ?)',
|
||||
params: ['John', 'Doe', 30],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('insert (on duplicate key update)', ({ expect }) => {
|
||||
const query = db
|
||||
.insert(users)
|
||||
.values({ first_name: 'John', last_name: 'Doe', age: 30 })
|
||||
.onDuplicateKeyUpdate({ set: { age: 31 } });
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'insert into `users` (`id`, `firstName`, `lastName`, `AGE`) values (default, ?, ?, ?) on duplicate key update `AGE` = ?',
|
||||
params: ['John', 'Doe', 30, 31],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('update', ({ expect }) => {
|
||||
const query = db
|
||||
.update(users)
|
||||
.set({ first_name: 'John', last_name: 'Doe', age: 30 })
|
||||
.where(eq(users.id, 1));
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: 'update `users` set `firstName` = ?, `lastName` = ?, `AGE` = ? where `users`.`id` = ?',
|
||||
params: ['John', 'Doe', 30, 1],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('delete', ({ expect }) => {
|
||||
const query = db
|
||||
.delete(users)
|
||||
.where(eq(users.id, 1));
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: 'delete from `users` where `users`.`id` = ?',
|
||||
params: [1],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,299 @@
|
||||
import { Client } from '@planetscale/database';
|
||||
import { connect } from '@tidbcloud/serverless';
|
||||
import { beforeEach, describe, it } from 'vitest';
|
||||
import { alias, boolean, int, mysqlSchema, mysqlTable, serial, text, union } from '~/mysql-core';
|
||||
import { drizzle as planetscale } from '~/planetscale-serverless';
|
||||
import { relations } from '~/relations';
|
||||
import { asc, eq, sql } from '~/sql';
|
||||
import { drizzle as mysql } from '~/tidb-serverless';
|
||||
|
||||
const testSchema = mysqlSchema('test');
|
||||
const users = mysqlTable('users', {
|
||||
id: serial().primaryKey(),
|
||||
firstName: text().notNull(),
|
||||
lastName: text().notNull(),
|
||||
// Test that custom aliases remain
|
||||
age: int('AGE'),
|
||||
});
|
||||
const usersRelations = relations(users, ({ one }) => ({
|
||||
developers: one(developers),
|
||||
}));
|
||||
const developers = testSchema.table('developers', {
|
||||
userId: serial().primaryKey().references(() => users.id),
|
||||
usesDrizzleORM: boolean().notNull(),
|
||||
});
|
||||
const developersRelations = relations(developers, ({ one }) => ({
|
||||
user: one(users, {
|
||||
fields: [developers.userId],
|
||||
references: [users.id],
|
||||
}),
|
||||
}));
|
||||
const devs = alias(developers, 'devs');
|
||||
const schema = { users, usersRelations, developers, developersRelations };
|
||||
|
||||
const db = mysql(connect({}), { schema, casing: 'snake_case' });
|
||||
const ps = planetscale(new Client({}), { schema, casing: 'snake_case' });
|
||||
|
||||
const usersCache = {
|
||||
'public.users.id': 'id',
|
||||
'public.users.firstName': 'first_name',
|
||||
'public.users.lastName': 'last_name',
|
||||
'public.users.AGE': 'age',
|
||||
};
|
||||
const developersCache = {
|
||||
'test.developers.userId': 'user_id',
|
||||
'test.developers.usesDrizzleORM': 'uses_drizzle_orm',
|
||||
};
|
||||
const cache = {
|
||||
...usersCache,
|
||||
...developersCache,
|
||||
};
|
||||
|
||||
const fullName = sql`${users.firstName} || ' ' || ${users.lastName}`.as('name');
|
||||
|
||||
describe('mysql to snake case', () => {
|
||||
beforeEach(() => {
|
||||
db.dialect.casing.clearCache();
|
||||
ps.dialect.casing.clearCache();
|
||||
});
|
||||
|
||||
it('select', ({ expect }) => {
|
||||
const query = db
|
||||
.select({ name: fullName, age: users.age })
|
||||
.from(users)
|
||||
.leftJoin(developers, eq(users.id, developers.userId))
|
||||
.orderBy(asc(users.firstName));
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
"select `users`.`first_name` || ' ' || `users`.`last_name` as `name`, `users`.`AGE` from `users` left join `test`.`developers` on `users`.`id` = `test`.`developers`.`user_id` order by `users`.`first_name` asc",
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('select (with alias)', ({ expect }) => {
|
||||
const query = db
|
||||
.select({ firstName: users.firstName })
|
||||
.from(users)
|
||||
.leftJoin(devs, eq(users.id, devs.userId));
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'select `users`.`first_name` from `users` left join `test`.`developers` `devs` on `users`.`id` = `devs`.`user_id`',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('with CTE', ({ expect }) => {
|
||||
const cte = db.$with('cte').as(db.select({ name: fullName }).from(users));
|
||||
const query = db.with(cte).select().from(cte);
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: "with `cte` as (select `first_name` || ' ' || `last_name` as `name` from `users`) select `name` from `cte`",
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('with CTE (with query builder)', ({ expect }) => {
|
||||
const cte = db.$with('cte').as((qb) => qb.select({ name: fullName }).from(users));
|
||||
const query = db.with(cte).select().from(cte);
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: "with `cte` as (select `first_name` || ' ' || `last_name` as `name` from `users`) select `name` from `cte`",
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('set operator', ({ expect }) => {
|
||||
const query = db
|
||||
.select({ firstName: users.firstName })
|
||||
.from(users)
|
||||
.union(db.select({ firstName: users.firstName }).from(users));
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: '(select `first_name` from `users`) union (select `first_name` from `users`)',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('set operator (function)', ({ expect }) => {
|
||||
const query = union(
|
||||
db.select({ firstName: users.firstName }).from(users),
|
||||
db.select({ firstName: users.firstName }).from(users),
|
||||
);
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: '(select `first_name` from `users`) union (select `first_name` from `users`)',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('query (find first)', ({ expect }) => {
|
||||
const query = db.query.users.findFirst({
|
||||
columns: {
|
||||
id: true,
|
||||
age: true,
|
||||
},
|
||||
extras: {
|
||||
fullName,
|
||||
},
|
||||
where: eq(users.id, 1),
|
||||
with: {
|
||||
developers: {
|
||||
columns: {
|
||||
usesDrizzleORM: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
"select `users`.`id`, `users`.`AGE`, `users`.`first_name` || ' ' || `users`.`last_name` as `name`, `users_developers`.`data` as `developers` from `users` `users` left join lateral (select json_array(`users_developers`.`uses_drizzle_orm`) as `data` from (select * from `test`.`developers` `users_developers` where `users_developers`.`user_id` = `users`.`id` limit ?) `users_developers`) `users_developers` on true where `users`.`id` = ? limit ?",
|
||||
params: [1, 1, 1],
|
||||
typings: ['none', 'none', 'none'],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('query (find first, planetscale)', ({ expect }) => {
|
||||
const query = ps.query.users.findFirst({
|
||||
columns: {
|
||||
id: true,
|
||||
age: true,
|
||||
},
|
||||
extras: {
|
||||
fullName,
|
||||
},
|
||||
where: eq(users.id, 1),
|
||||
with: {
|
||||
developers: {
|
||||
columns: {
|
||||
usesDrizzleORM: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
"select `id`, `AGE`, `first_name` || ' ' || `last_name` as `name`, (select json_array(`uses_drizzle_orm`) from (select * from `test`.`developers` `users_developers` where `users_developers`.`user_id` = `users`.`id` limit ?) `users_developers`) as `developers` from `users` `users` where `users`.`id` = ? limit ?",
|
||||
params: [1, 1, 1],
|
||||
typings: ['none', 'none', 'none'],
|
||||
});
|
||||
expect(ps.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('query (find many)', ({ expect }) => {
|
||||
const query = db.query.users.findMany({
|
||||
columns: {
|
||||
id: true,
|
||||
age: true,
|
||||
},
|
||||
extras: {
|
||||
fullName,
|
||||
},
|
||||
where: eq(users.id, 1),
|
||||
with: {
|
||||
developers: {
|
||||
columns: {
|
||||
usesDrizzleORM: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
"select `users`.`id`, `users`.`AGE`, `users`.`first_name` || ' ' || `users`.`last_name` as `name`, `users_developers`.`data` as `developers` from `users` `users` left join lateral (select json_array(`users_developers`.`uses_drizzle_orm`) as `data` from (select * from `test`.`developers` `users_developers` where `users_developers`.`user_id` = `users`.`id` limit ?) `users_developers`) `users_developers` on true where `users`.`id` = ?",
|
||||
params: [1, 1],
|
||||
typings: ['none', 'none'],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('query (find many, planetscale)', ({ expect }) => {
|
||||
const query = ps.query.users.findMany({
|
||||
columns: {
|
||||
id: true,
|
||||
age: true,
|
||||
},
|
||||
extras: {
|
||||
fullName,
|
||||
},
|
||||
where: eq(users.id, 1),
|
||||
with: {
|
||||
developers: {
|
||||
columns: {
|
||||
usesDrizzleORM: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
"select `id`, `AGE`, `first_name` || ' ' || `last_name` as `name`, (select json_array(`uses_drizzle_orm`) from (select * from `test`.`developers` `users_developers` where `users_developers`.`user_id` = `users`.`id` limit ?) `users_developers`) as `developers` from `users` `users` where `users`.`id` = ?",
|
||||
params: [1, 1],
|
||||
typings: ['none', 'none'],
|
||||
});
|
||||
expect(ps.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('insert', ({ expect }) => {
|
||||
const query = db
|
||||
.insert(users)
|
||||
.values({ firstName: 'John', lastName: 'Doe', age: 30 });
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: 'insert into `users` (`id`, `first_name`, `last_name`, `AGE`) values (default, ?, ?, ?)',
|
||||
params: ['John', 'Doe', 30],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('insert (on duplicate key update)', ({ expect }) => {
|
||||
const query = db
|
||||
.insert(users)
|
||||
.values({ firstName: 'John', lastName: 'Doe', age: 30 })
|
||||
.onDuplicateKeyUpdate({ set: { age: 31 } });
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'insert into `users` (`id`, `first_name`, `last_name`, `AGE`) values (default, ?, ?, ?) on duplicate key update `AGE` = ?',
|
||||
params: ['John', 'Doe', 30, 31],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('update', ({ expect }) => {
|
||||
const query = db
|
||||
.update(users)
|
||||
.set({ firstName: 'John', lastName: 'Doe', age: 30 })
|
||||
.where(eq(users.id, 1));
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: 'update `users` set `first_name` = ?, `last_name` = ?, `AGE` = ? where `users`.`id` = ?',
|
||||
params: ['John', 'Doe', 30, 1],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('delete', ({ expect }) => {
|
||||
const query = db
|
||||
.delete(users)
|
||||
.where(eq(users.id, 1));
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: 'delete from `users` where `users`.`id` = ?',
|
||||
params: [1],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,246 @@
|
||||
import postgres from 'postgres';
|
||||
import { beforeEach, describe, it } from 'vitest';
|
||||
import { alias, boolean, integer, pgSchema, pgTable, serial, text, union } from '~/pg-core';
|
||||
import { drizzle } from '~/postgres-js';
|
||||
import { relations } from '~/relations';
|
||||
import { asc, eq, sql } from '~/sql';
|
||||
|
||||
const testSchema = pgSchema('test');
|
||||
const users = pgTable('users', {
|
||||
id: serial().primaryKey(),
|
||||
first_name: text().notNull(),
|
||||
last_name: text().notNull(),
|
||||
// Test that custom aliases remain
|
||||
age: integer('AGE'),
|
||||
});
|
||||
const usersRelations = relations(users, ({ one }) => ({
|
||||
developers: one(developers),
|
||||
}));
|
||||
const developers = testSchema.table('developers', {
|
||||
user_id: serial().primaryKey().references(() => users.id),
|
||||
uses_drizzle_orm: boolean().notNull(),
|
||||
});
|
||||
const developersRelations = relations(developers, ({ one }) => ({
|
||||
user: one(users, {
|
||||
fields: [developers.user_id],
|
||||
references: [users.id],
|
||||
}),
|
||||
}));
|
||||
const devs = alias(developers, 'devs');
|
||||
const schema = { users, usersRelations, developers, developersRelations };
|
||||
|
||||
const db = drizzle(postgres(''), { schema, casing: 'camelCase' });
|
||||
|
||||
const usersCache = {
|
||||
'public.users.id': 'id',
|
||||
'public.users.first_name': 'firstName',
|
||||
'public.users.last_name': 'lastName',
|
||||
'public.users.AGE': 'age',
|
||||
};
|
||||
const developersCache = {
|
||||
'test.developers.user_id': 'userId',
|
||||
'test.developers.uses_drizzle_orm': 'usesDrizzleOrm',
|
||||
};
|
||||
const cache = {
|
||||
...usersCache,
|
||||
...developersCache,
|
||||
};
|
||||
|
||||
const fullName = sql`${users.first_name} || ' ' || ${users.last_name}`.as('name');
|
||||
|
||||
describe('postgres to camel case', () => {
|
||||
beforeEach(() => {
|
||||
db.dialect.casing.clearCache();
|
||||
});
|
||||
|
||||
it('select', ({ expect }) => {
|
||||
const query = db
|
||||
.select({ name: fullName, age: users.age })
|
||||
.from(users)
|
||||
.leftJoin(developers, eq(users.id, developers.user_id))
|
||||
.orderBy(asc(users.first_name));
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'select "users"."firstName" || \' \' || "users"."lastName" as "name", "users"."AGE" from "users" left join "test"."developers" on "users"."id" = "test"."developers"."userId" order by "users"."firstName" asc',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('select (with alias)', ({ expect }) => {
|
||||
const query = db
|
||||
.select({ first_name: users.first_name })
|
||||
.from(users)
|
||||
.leftJoin(devs, eq(users.id, devs.user_id));
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'select "users"."firstName" from "users" left join "test"."developers" "devs" on "users"."id" = "devs"."userId"',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('with CTE', ({ expect }) => {
|
||||
const cte = db.$with('cte').as(db.select({ name: fullName }).from(users));
|
||||
const query = db.with(cte).select().from(cte);
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: 'with "cte" as (select "firstName" || \' \' || "lastName" as "name" from "users") select "name" from "cte"',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('with CTE (with query builder)', ({ expect }) => {
|
||||
const cte = db.$with('cte').as((qb) => qb.select({ name: fullName }).from(users));
|
||||
const query = db.with(cte).select().from(cte);
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: 'with "cte" as (select "firstName" || \' \' || "lastName" as "name" from "users") select "name" from "cte"',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('set operator', ({ expect }) => {
|
||||
const query = db
|
||||
.select({ first_name: users.first_name })
|
||||
.from(users)
|
||||
.union(db.select({ first_name: users.first_name }).from(users));
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: '(select "firstName" from "users") union (select "firstName" from "users")',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('set operator (function)', ({ expect }) => {
|
||||
const query = union(
|
||||
db.select({ first_name: users.first_name }).from(users),
|
||||
db.select({ first_name: users.first_name }).from(users),
|
||||
);
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: '(select "firstName" from "users") union (select "firstName" from "users")',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('query (find first)', ({ expect }) => {
|
||||
const query = db.query.users.findFirst({
|
||||
columns: {
|
||||
id: true,
|
||||
age: true,
|
||||
},
|
||||
extras: {
|
||||
fullName,
|
||||
},
|
||||
where: eq(users.id, 1),
|
||||
with: {
|
||||
developers: {
|
||||
columns: {
|
||||
uses_drizzle_orm: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'select "users"."id", "users"."AGE", "users"."firstName" || \' \' || "users"."lastName" as "name", "users_developers"."data" as "developers" from "users" "users" left join lateral (select json_build_array("users_developers"."usesDrizzleOrm") as "data" from (select * from "test"."developers" "users_developers" where "users_developers"."userId" = "users"."id" limit $1) "users_developers") "users_developers" on true where "users"."id" = $2 limit $3',
|
||||
params: [1, 1, 1],
|
||||
typings: ['none', 'none', 'none'],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('query (find many)', ({ expect }) => {
|
||||
const query = db.query.users.findMany({
|
||||
columns: {
|
||||
id: true,
|
||||
age: true,
|
||||
},
|
||||
extras: {
|
||||
fullName,
|
||||
},
|
||||
where: eq(users.id, 1),
|
||||
with: {
|
||||
developers: {
|
||||
columns: {
|
||||
uses_drizzle_orm: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'select "users"."id", "users"."AGE", "users"."firstName" || \' \' || "users"."lastName" as "name", "users_developers"."data" as "developers" from "users" "users" left join lateral (select json_build_array("users_developers"."usesDrizzleOrm") as "data" from (select * from "test"."developers" "users_developers" where "users_developers"."userId" = "users"."id" limit $1) "users_developers") "users_developers" on true where "users"."id" = $2',
|
||||
params: [1, 1],
|
||||
typings: ['none', 'none'],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('insert (on conflict do nothing)', ({ expect }) => {
|
||||
const query = db
|
||||
.insert(users)
|
||||
.values({ first_name: 'John', last_name: 'Doe', age: 30 })
|
||||
.onConflictDoNothing({ target: users.first_name })
|
||||
.returning({ first_name: users.first_name, age: users.age });
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'insert into "users" ("id", "firstName", "lastName", "AGE") values (default, $1, $2, $3) on conflict ("firstName") do nothing returning "firstName", "AGE"',
|
||||
params: ['John', 'Doe', 30],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('insert (on conflict do update)', ({ expect }) => {
|
||||
const query = db
|
||||
.insert(users)
|
||||
.values({ first_name: 'John', last_name: 'Doe', age: 30 })
|
||||
.onConflictDoUpdate({ target: users.first_name, set: { age: 31 } })
|
||||
.returning({ first_name: users.first_name, age: users.age });
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'insert into "users" ("id", "firstName", "lastName", "AGE") values (default, $1, $2, $3) on conflict ("firstName") do update set "AGE" = $4 returning "firstName", "AGE"',
|
||||
params: ['John', 'Doe', 30, 31],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('update', ({ expect }) => {
|
||||
const query = db
|
||||
.update(users)
|
||||
.set({ first_name: 'John', last_name: 'Doe', age: 30 })
|
||||
.where(eq(users.id, 1))
|
||||
.returning({ first_name: users.first_name, age: users.age });
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'update "users" set "firstName" = $1, "lastName" = $2, "AGE" = $3 where "users"."id" = $4 returning "firstName", "AGE"',
|
||||
params: ['John', 'Doe', 30, 1],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('delete', ({ expect }) => {
|
||||
const query = db
|
||||
.delete(users)
|
||||
.where(eq(users.id, 1))
|
||||
.returning({ first_name: users.first_name, age: users.age });
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: 'delete from "users" where "users"."id" = $1 returning "firstName", "AGE"',
|
||||
params: [1],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,248 @@
|
||||
import postgres from 'postgres';
|
||||
import { beforeEach, describe, it } from 'vitest';
|
||||
import { alias, boolean, integer, pgSchema, pgTable, serial, text, union } from '~/pg-core';
|
||||
import { drizzle } from '~/postgres-js';
|
||||
import { relations } from '~/relations';
|
||||
import { asc, eq, sql } from '~/sql';
|
||||
|
||||
const testSchema = pgSchema('test');
|
||||
const users = pgTable('users', {
|
||||
id: serial().primaryKey(),
|
||||
firstName: text().notNull(),
|
||||
lastName: text().notNull(),
|
||||
// Test that custom aliases remain
|
||||
age: integer('AGE'),
|
||||
});
|
||||
const usersRelations = relations(users, ({ one }) => ({
|
||||
developers: one(developers),
|
||||
}));
|
||||
const developers = testSchema.table('developers', {
|
||||
userId: serial().primaryKey().references(() => users.id),
|
||||
usesDrizzleORM: boolean().notNull(),
|
||||
});
|
||||
const developersRelations = relations(developers, ({ one }) => ({
|
||||
user: one(users, {
|
||||
fields: [developers.userId],
|
||||
references: [users.id],
|
||||
}),
|
||||
}));
|
||||
const devs = alias(developers, 'devs');
|
||||
const schema = { users, usersRelations, developers, developersRelations };
|
||||
|
||||
const db = drizzle(postgres(''), { schema, casing: 'snake_case' });
|
||||
|
||||
const usersCache = {
|
||||
'public.users.id': 'id',
|
||||
'public.users.firstName': 'first_name',
|
||||
'public.users.lastName': 'last_name',
|
||||
'public.users.AGE': 'age',
|
||||
};
|
||||
const developersCache = {
|
||||
'test.developers.userId': 'user_id',
|
||||
'test.developers.usesDrizzleORM': 'uses_drizzle_orm',
|
||||
};
|
||||
const cache = {
|
||||
...usersCache,
|
||||
...developersCache,
|
||||
};
|
||||
|
||||
const fullName = sql`${users.firstName} || ' ' || ${users.lastName}`.as('name');
|
||||
|
||||
describe('postgres to snake case', () => {
|
||||
beforeEach(() => {
|
||||
db.dialect.casing.clearCache();
|
||||
});
|
||||
|
||||
it('select', ({ expect }) => {
|
||||
const query = db
|
||||
.select({ name: fullName, age: users.age })
|
||||
.from(users)
|
||||
.leftJoin(developers, eq(users.id, developers.userId))
|
||||
.orderBy(asc(users.firstName));
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'select "users"."first_name" || \' \' || "users"."last_name" as "name", "users"."AGE" from "users" left join "test"."developers" on "users"."id" = "test"."developers"."user_id" order by "users"."first_name" asc',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('select (with alias)', ({ expect }) => {
|
||||
const query = db
|
||||
.select({ firstName: users.firstName })
|
||||
.from(users)
|
||||
.leftJoin(devs, eq(users.id, devs.userId));
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'select "users"."first_name" from "users" left join "test"."developers" "devs" on "users"."id" = "devs"."user_id"',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('with CTE', ({ expect }) => {
|
||||
const cte = db.$with('cte').as(db.select({ name: fullName }).from(users));
|
||||
const query = db.with(cte).select().from(cte);
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'with "cte" as (select "first_name" || \' \' || "last_name" as "name" from "users") select "name" from "cte"',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('with CTE (with query builder)', ({ expect }) => {
|
||||
const cte = db.$with('cte').as((qb) => qb.select({ name: fullName }).from(users));
|
||||
const query = db.with(cte).select().from(cte);
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'with "cte" as (select "first_name" || \' \' || "last_name" as "name" from "users") select "name" from "cte"',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('set operator', ({ expect }) => {
|
||||
const query = db
|
||||
.select({ firstName: users.firstName })
|
||||
.from(users)
|
||||
.union(db.select({ firstName: users.firstName }).from(users));
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: '(select "first_name" from "users") union (select "first_name" from "users")',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('set operator (function)', ({ expect }) => {
|
||||
const query = union(
|
||||
db.select({ firstName: users.firstName }).from(users),
|
||||
db.select({ firstName: users.firstName }).from(users),
|
||||
);
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: '(select "first_name" from "users") union (select "first_name" from "users")',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('query (find first)', ({ expect }) => {
|
||||
const query = db.query.users.findFirst({
|
||||
columns: {
|
||||
id: true,
|
||||
age: true,
|
||||
},
|
||||
extras: {
|
||||
fullName,
|
||||
},
|
||||
where: eq(users.id, 1),
|
||||
with: {
|
||||
developers: {
|
||||
columns: {
|
||||
usesDrizzleORM: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'select "users"."id", "users"."AGE", "users"."first_name" || \' \' || "users"."last_name" as "name", "users_developers"."data" as "developers" from "users" "users" left join lateral (select json_build_array("users_developers"."uses_drizzle_orm") as "data" from (select * from "test"."developers" "users_developers" where "users_developers"."user_id" = "users"."id" limit $1) "users_developers") "users_developers" on true where "users"."id" = $2 limit $3',
|
||||
params: [1, 1, 1],
|
||||
typings: ['none', 'none', 'none'],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('query (find many)', ({ expect }) => {
|
||||
const query = db.query.users.findMany({
|
||||
columns: {
|
||||
id: true,
|
||||
age: true,
|
||||
},
|
||||
extras: {
|
||||
fullName,
|
||||
},
|
||||
where: eq(users.id, 1),
|
||||
with: {
|
||||
developers: {
|
||||
columns: {
|
||||
usesDrizzleORM: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'select "users"."id", "users"."AGE", "users"."first_name" || \' \' || "users"."last_name" as "name", "users_developers"."data" as "developers" from "users" "users" left join lateral (select json_build_array("users_developers"."uses_drizzle_orm") as "data" from (select * from "test"."developers" "users_developers" where "users_developers"."user_id" = "users"."id" limit $1) "users_developers") "users_developers" on true where "users"."id" = $2',
|
||||
params: [1, 1],
|
||||
typings: ['none', 'none'],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('insert (on conflict do nothing)', ({ expect }) => {
|
||||
const query = db
|
||||
.insert(users)
|
||||
.values({ firstName: 'John', lastName: 'Doe', age: 30 })
|
||||
.onConflictDoNothing({ target: users.firstName })
|
||||
.returning({ firstName: users.firstName, age: users.age });
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'insert into "users" ("id", "first_name", "last_name", "AGE") values (default, $1, $2, $3) on conflict ("first_name") do nothing returning "first_name", "AGE"',
|
||||
params: ['John', 'Doe', 30],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('insert (on conflict do update)', ({ expect }) => {
|
||||
const query = db
|
||||
.insert(users)
|
||||
.values({ firstName: 'John', lastName: 'Doe', age: 30 })
|
||||
.onConflictDoUpdate({ target: users.firstName, set: { age: 31 } })
|
||||
.returning({ firstName: users.firstName, age: users.age });
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'insert into "users" ("id", "first_name", "last_name", "AGE") values (default, $1, $2, $3) on conflict ("first_name") do update set "AGE" = $4 returning "first_name", "AGE"',
|
||||
params: ['John', 'Doe', 30, 31],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('update', ({ expect }) => {
|
||||
const query = db
|
||||
.update(users)
|
||||
.set({ firstName: 'John', lastName: 'Doe', age: 30 })
|
||||
.where(eq(users.id, 1))
|
||||
.returning({ firstName: users.firstName, age: users.age });
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'update "users" set "first_name" = $1, "last_name" = $2, "AGE" = $3 where "users"."id" = $4 returning "first_name", "AGE"',
|
||||
params: ['John', 'Doe', 30, 1],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('delete', ({ expect }) => {
|
||||
const query = db
|
||||
.delete(users)
|
||||
.where(eq(users.id, 1))
|
||||
.returning({ firstName: users.firstName, age: users.age });
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: 'delete from "users" where "users"."id" = $1 returning "first_name", "AGE"',
|
||||
params: [1],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,244 @@
|
||||
import Database from 'better-sqlite3';
|
||||
import { beforeEach, describe, it } from 'vitest';
|
||||
import { drizzle } from '~/better-sqlite3';
|
||||
import { relations } from '~/relations';
|
||||
import { asc, eq, sql } from '~/sql';
|
||||
import { alias, integer, sqliteTable, text, union } from '~/sqlite-core';
|
||||
|
||||
const users = sqliteTable('users', {
|
||||
id: integer().primaryKey({ autoIncrement: true }),
|
||||
first_name: text().notNull(),
|
||||
last_name: text().notNull(),
|
||||
// Test that custom aliases remain
|
||||
age: integer('AGE'),
|
||||
});
|
||||
const usersRelations = relations(users, ({ one }) => ({
|
||||
developers: one(developers),
|
||||
}));
|
||||
const developers = sqliteTable('developers', {
|
||||
user_id: integer().primaryKey().references(() => users.id),
|
||||
uses_drizzle_orm: integer({ mode: 'boolean' }).notNull(),
|
||||
});
|
||||
const developersRelations = relations(developers, ({ one }) => ({
|
||||
user: one(users, {
|
||||
fields: [developers.user_id],
|
||||
references: [users.id],
|
||||
}),
|
||||
}));
|
||||
const devs = alias(developers, 'devs');
|
||||
const schema = { users, usersRelations, developers, developersRelations };
|
||||
|
||||
const db = drizzle(new Database(':memory:'), { schema, casing: 'camelCase' });
|
||||
|
||||
const usersCache = {
|
||||
'public.users.id': 'id',
|
||||
'public.users.first_name': 'firstName',
|
||||
'public.users.last_name': 'lastName',
|
||||
'public.users.AGE': 'age',
|
||||
};
|
||||
const developersCache = {
|
||||
'public.developers.user_id': 'userId',
|
||||
'public.developers.uses_drizzle_orm': 'usesDrizzleOrm',
|
||||
};
|
||||
const cache = {
|
||||
...usersCache,
|
||||
...developersCache,
|
||||
};
|
||||
|
||||
const fullName = sql`${users.first_name} || ' ' || ${users.last_name}`.as('name');
|
||||
|
||||
describe('sqlite to camel case', () => {
|
||||
beforeEach(() => {
|
||||
db.dialect.casing.clearCache();
|
||||
});
|
||||
|
||||
it('select', ({ expect }) => {
|
||||
const query = db
|
||||
.select({ name: fullName, age: users.age })
|
||||
.from(users)
|
||||
.leftJoin(developers, eq(users.id, developers.user_id))
|
||||
.orderBy(asc(users.first_name));
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'select "users"."firstName" || \' \' || "users"."lastName" as "name", "users"."AGE" from "users" left join "developers" on "users"."id" = "developers"."userId" order by "users"."firstName" asc',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('select (with alias)', ({ expect }) => {
|
||||
const query = db
|
||||
.select({ first_name: users.first_name })
|
||||
.from(users)
|
||||
.leftJoin(devs, eq(users.id, devs.user_id));
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: 'select "users"."firstName" from "users" left join "developers" "devs" on "users"."id" = "devs"."userId"',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('with CTE', ({ expect }) => {
|
||||
const cte = db.$with('cte').as(db.select({ name: fullName }).from(users));
|
||||
const query = db.with(cte).select().from(cte);
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: 'with "cte" as (select "firstName" || \' \' || "lastName" as "name" from "users") select "name" from "cte"',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('with CTE (with query builder)', ({ expect }) => {
|
||||
const cte = db.$with('cte').as((qb) => qb.select({ name: fullName }).from(users));
|
||||
const query = db.with(cte).select().from(cte);
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: 'with "cte" as (select "firstName" || \' \' || "lastName" as "name" from "users") select "name" from "cte"',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('set operator', ({ expect }) => {
|
||||
const query = db
|
||||
.select({ first_name: users.first_name })
|
||||
.from(users)
|
||||
.union(db.select({ first_name: users.first_name }).from(users));
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: 'select "firstName" from "users" union select "firstName" from "users"',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('set operator (function)', ({ expect }) => {
|
||||
const query = union(
|
||||
db.select({ first_name: users.first_name }).from(users),
|
||||
db.select({ first_name: users.first_name }).from(users),
|
||||
);
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: 'select "firstName" from "users" union select "firstName" from "users"',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('query (find first)', ({ expect }) => {
|
||||
const query = db.query.users.findFirst({
|
||||
columns: {
|
||||
id: true,
|
||||
age: true,
|
||||
},
|
||||
extras: {
|
||||
fullName,
|
||||
},
|
||||
where: eq(users.id, 1),
|
||||
with: {
|
||||
developers: {
|
||||
columns: {
|
||||
uses_drizzle_orm: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'select "id", "AGE", "firstName" || \' \' || "lastName" as "name", (select json_array("usesDrizzleOrm") as "data" from (select * from "developers" "users_developers" where "users_developers"."userId" = "users"."id" limit ?) "users_developers") as "developers" from "users" "users" where "users"."id" = ? limit ?',
|
||||
params: [1, 1, 1],
|
||||
typings: ['none', 'none', 'none'],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('query (find many)', ({ expect }) => {
|
||||
const query = db.query.users.findMany({
|
||||
columns: {
|
||||
id: true,
|
||||
age: true,
|
||||
},
|
||||
extras: {
|
||||
fullName,
|
||||
},
|
||||
where: eq(users.id, 1),
|
||||
with: {
|
||||
developers: {
|
||||
columns: {
|
||||
uses_drizzle_orm: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'select "id", "AGE", "firstName" || \' \' || "lastName" as "name", (select json_array("usesDrizzleOrm") as "data" from (select * from "developers" "users_developers" where "users_developers"."userId" = "users"."id" limit ?) "users_developers") as "developers" from "users" "users" where "users"."id" = ?',
|
||||
params: [1, 1],
|
||||
typings: ['none', 'none'],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('insert (on conflict do nothing)', ({ expect }) => {
|
||||
const query = db
|
||||
.insert(users)
|
||||
.values({ first_name: 'John', last_name: 'Doe', age: 30 })
|
||||
.onConflictDoNothing({ target: users.first_name })
|
||||
.returning({ first_name: users.first_name, age: users.age });
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'insert into "users" ("id", "firstName", "lastName", "AGE") values (null, ?, ?, ?) on conflict ("users"."firstName") do nothing returning "firstName", "AGE"',
|
||||
params: ['John', 'Doe', 30],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('insert (on conflict do update)', ({ expect }) => {
|
||||
const query = db
|
||||
.insert(users)
|
||||
.values({ first_name: 'John', last_name: 'Doe', age: 30 })
|
||||
.onConflictDoUpdate({ target: users.first_name, set: { age: 31 } })
|
||||
.returning({ first_name: users.first_name, age: users.age });
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'insert into "users" ("id", "firstName", "lastName", "AGE") values (null, ?, ?, ?) on conflict ("users"."firstName") do update set "AGE" = ? returning "firstName", "AGE"',
|
||||
params: ['John', 'Doe', 30, 31],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('update', ({ expect }) => {
|
||||
const query = db
|
||||
.update(users)
|
||||
.set({ first_name: 'John', last_name: 'Doe', age: 30 })
|
||||
.where(eq(users.id, 1))
|
||||
.returning({ first_name: users.first_name, age: users.age });
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'update "users" set "firstName" = ?, "lastName" = ?, "AGE" = ? where "users"."id" = ? returning "firstName", "AGE"',
|
||||
params: ['John', 'Doe', 30, 1],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('delete', ({ expect }) => {
|
||||
const query = db
|
||||
.delete(users)
|
||||
.where(eq(users.id, 1))
|
||||
.returning({ first_name: users.first_name, age: users.age });
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: 'delete from "users" where "users"."id" = ? returning "firstName", "AGE"',
|
||||
params: [1],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,246 @@
|
||||
import Database from 'better-sqlite3';
|
||||
import { beforeEach, describe, it } from 'vitest';
|
||||
import { drizzle } from '~/better-sqlite3';
|
||||
import { relations } from '~/relations';
|
||||
import { asc, eq, sql } from '~/sql';
|
||||
import { alias, integer, sqliteTable, text, union } from '~/sqlite-core';
|
||||
|
||||
const users = sqliteTable('users', {
|
||||
id: integer().primaryKey({ autoIncrement: true }),
|
||||
firstName: text().notNull(),
|
||||
lastName: text().notNull(),
|
||||
// Test that custom aliases remain
|
||||
age: integer('AGE'),
|
||||
});
|
||||
const usersRelations = relations(users, ({ one }) => ({
|
||||
developers: one(developers),
|
||||
}));
|
||||
const developers = sqliteTable('developers', {
|
||||
userId: integer().primaryKey().references(() => users.id),
|
||||
usesDrizzleORM: integer({ mode: 'boolean' }).notNull(),
|
||||
});
|
||||
const developersRelations = relations(developers, ({ one }) => ({
|
||||
user: one(users, {
|
||||
fields: [developers.userId],
|
||||
references: [users.id],
|
||||
}),
|
||||
}));
|
||||
const devs = alias(developers, 'devs');
|
||||
const schema = { users, usersRelations, developers, developersRelations };
|
||||
|
||||
const db = drizzle(new Database(':memory:'), { schema, casing: 'snake_case' });
|
||||
|
||||
const usersCache = {
|
||||
'public.users.id': 'id',
|
||||
'public.users.firstName': 'first_name',
|
||||
'public.users.lastName': 'last_name',
|
||||
'public.users.AGE': 'age',
|
||||
};
|
||||
const developersCache = {
|
||||
'public.developers.userId': 'user_id',
|
||||
'public.developers.usesDrizzleORM': 'uses_drizzle_orm',
|
||||
};
|
||||
const cache = {
|
||||
...usersCache,
|
||||
...developersCache,
|
||||
};
|
||||
|
||||
const fullName = sql`${users.firstName} || ' ' || ${users.lastName}`.as('name');
|
||||
|
||||
describe('sqlite to camel case', () => {
|
||||
beforeEach(() => {
|
||||
db.dialect.casing.clearCache();
|
||||
});
|
||||
|
||||
it('select', ({ expect }) => {
|
||||
const query = db
|
||||
.select({ name: fullName, age: users.age })
|
||||
.from(users)
|
||||
.leftJoin(developers, eq(users.id, developers.userId))
|
||||
.orderBy(asc(users.firstName));
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'select "users"."first_name" || \' \' || "users"."last_name" as "name", "users"."AGE" from "users" left join "developers" on "users"."id" = "developers"."user_id" order by "users"."first_name" asc',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('select (with alias)', ({ expect }) => {
|
||||
const query = db
|
||||
.select({ firstName: users.firstName })
|
||||
.from(users)
|
||||
.leftJoin(devs, eq(users.id, devs.userId));
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: 'select "users"."first_name" from "users" left join "developers" "devs" on "users"."id" = "devs"."user_id"',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('with CTE', ({ expect }) => {
|
||||
const cte = db.$with('cte').as(db.select({ name: fullName }).from(users));
|
||||
const query = db.with(cte).select().from(cte);
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'with "cte" as (select "first_name" || \' \' || "last_name" as "name" from "users") select "name" from "cte"',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('with CTE (with query builder)', ({ expect }) => {
|
||||
const cte = db.$with('cte').as((qb) => qb.select({ name: fullName }).from(users));
|
||||
const query = db.with(cte).select().from(cte);
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'with "cte" as (select "first_name" || \' \' || "last_name" as "name" from "users") select "name" from "cte"',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('set operator', ({ expect }) => {
|
||||
const query = db
|
||||
.select({ firstName: users.firstName })
|
||||
.from(users)
|
||||
.union(db.select({ firstName: users.firstName }).from(users));
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: 'select "first_name" from "users" union select "first_name" from "users"',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('set operator (function)', ({ expect }) => {
|
||||
const query = union(
|
||||
db.select({ firstName: users.firstName }).from(users),
|
||||
db.select({ firstName: users.firstName }).from(users),
|
||||
);
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: 'select "first_name" from "users" union select "first_name" from "users"',
|
||||
params: [],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('query (find first)', ({ expect }) => {
|
||||
const query = db.query.users.findFirst({
|
||||
columns: {
|
||||
id: true,
|
||||
age: true,
|
||||
},
|
||||
extras: {
|
||||
fullName,
|
||||
},
|
||||
where: eq(users.id, 1),
|
||||
with: {
|
||||
developers: {
|
||||
columns: {
|
||||
usesDrizzleORM: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'select "id", "AGE", "first_name" || \' \' || "last_name" as "name", (select json_array("uses_drizzle_orm") as "data" from (select * from "developers" "users_developers" where "users_developers"."user_id" = "users"."id" limit ?) "users_developers") as "developers" from "users" "users" where "users"."id" = ? limit ?',
|
||||
params: [1, 1, 1],
|
||||
typings: ['none', 'none', 'none'],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('query (find many)', ({ expect }) => {
|
||||
const query = db.query.users.findMany({
|
||||
columns: {
|
||||
id: true,
|
||||
age: true,
|
||||
},
|
||||
extras: {
|
||||
fullName,
|
||||
},
|
||||
where: eq(users.id, 1),
|
||||
with: {
|
||||
developers: {
|
||||
columns: {
|
||||
usesDrizzleORM: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'select "id", "AGE", "first_name" || \' \' || "last_name" as "name", (select json_array("uses_drizzle_orm") as "data" from (select * from "developers" "users_developers" where "users_developers"."user_id" = "users"."id" limit ?) "users_developers") as "developers" from "users" "users" where "users"."id" = ?',
|
||||
params: [1, 1],
|
||||
typings: ['none', 'none'],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(cache);
|
||||
});
|
||||
|
||||
it('insert (on conflict do nothing)', ({ expect }) => {
|
||||
const query = db
|
||||
.insert(users)
|
||||
.values({ firstName: 'John', lastName: 'Doe', age: 30 })
|
||||
.onConflictDoNothing({ target: users.firstName })
|
||||
.returning({ firstName: users.firstName, age: users.age });
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'insert into "users" ("id", "first_name", "last_name", "AGE") values (null, ?, ?, ?) on conflict ("users"."first_name") do nothing returning "first_name", "AGE"',
|
||||
params: ['John', 'Doe', 30],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('insert (on conflict do update)', ({ expect }) => {
|
||||
const query = db
|
||||
.insert(users)
|
||||
.values({ firstName: 'John', lastName: 'Doe', age: 30 })
|
||||
.onConflictDoUpdate({ target: users.firstName, set: { age: 31 } })
|
||||
.returning({ firstName: users.firstName, age: users.age });
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'insert into "users" ("id", "first_name", "last_name", "AGE") values (null, ?, ?, ?) on conflict ("users"."first_name") do update set "AGE" = ? returning "first_name", "AGE"',
|
||||
params: ['John', 'Doe', 30, 31],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('update', ({ expect }) => {
|
||||
const query = db
|
||||
.update(users)
|
||||
.set({ firstName: 'John', lastName: 'Doe', age: 30 })
|
||||
.where(eq(users.id, 1))
|
||||
.returning({ firstName: users.firstName, age: users.age });
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql:
|
||||
'update "users" set "first_name" = ?, "last_name" = ?, "AGE" = ? where "users"."id" = ? returning "first_name", "AGE"',
|
||||
params: ['John', 'Doe', 30, 1],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
|
||||
it('delete', ({ expect }) => {
|
||||
const query = db
|
||||
.delete(users)
|
||||
.where(eq(users.id, 1))
|
||||
.returning({ first_name: users.firstName, age: users.age });
|
||||
|
||||
expect(query.toSQL()).toEqual({
|
||||
sql: 'delete from "users" where "users"."id" = ? returning "first_name", "AGE"',
|
||||
params: [1],
|
||||
});
|
||||
expect(db.dialect.casing.cache).toEqual(usersCache);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
import { globSync } from 'glob';
|
||||
import { Project } from 'ts-morph';
|
||||
import { assert, test } from 'vitest';
|
||||
|
||||
const project = new Project({ tsConfigFilePath: './tsconfig.build.json' });
|
||||
|
||||
const filesList = globSync('src/**/*.ts');
|
||||
|
||||
for (const filePath of filesList) {
|
||||
test(filePath, () => {
|
||||
const conflicts: { name: string; files: [string, string] }[] = [];
|
||||
const exports = new Map<string, string>();
|
||||
|
||||
const sourceFile = project.getSourceFileOrThrow(filePath);
|
||||
|
||||
for (const decl of sourceFile.getExportDeclarations()) {
|
||||
const moduleSpecifier = decl.getModuleSpecifierValue();
|
||||
if (!moduleSpecifier || !moduleSpecifier.endsWith('.ts')) {
|
||||
continue;
|
||||
}
|
||||
const exportSourcePath = decl.getModuleSpecifierSourceFile()!.getFilePath();
|
||||
const exported = project.getSourceFileOrThrow(exportSourcePath);
|
||||
|
||||
for (const symbol of exported.getExportSymbols()) {
|
||||
const name = symbol.getName();
|
||||
const from = exports.get(name);
|
||||
if (from) {
|
||||
conflicts.push({
|
||||
name,
|
||||
files: [from, moduleSpecifier],
|
||||
});
|
||||
} else {
|
||||
exports.set(name, moduleSpecifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (conflicts.length) {
|
||||
assert.fail(
|
||||
conflicts.map(({ name, files }) => `\n- ${name} is exported from ${files.join(' and ')}`).join('\n'),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { describe, test } from 'vitest';
|
||||
import { Column, is } from '~/index.ts';
|
||||
import { PgArray, PgColumn, PgSerial, pgTable, serial } from '~/pg-core/index.ts';
|
||||
|
||||
const pgExampleTable = pgTable('test', {
|
||||
a: serial('a').array(),
|
||||
});
|
||||
|
||||
describe.concurrent('is', () => {
|
||||
test('Column', ({ expect }) => {
|
||||
expect(is(pgExampleTable.a, Column)).toBe(true);
|
||||
expect(is(pgExampleTable.a, PgColumn)).toBe(true);
|
||||
expect(is(pgExampleTable.a, PgArray)).toBe(true);
|
||||
expect(is(pgExampleTable.a, PgSerial)).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,148 @@
|
||||
import { describe, it } from 'vitest';
|
||||
import { customType, pgTable } from '~/pg-core/index.ts';
|
||||
|
||||
const anyColumn = customType<{ data: any }>({
|
||||
dataType() {
|
||||
return 'any';
|
||||
},
|
||||
});
|
||||
|
||||
const table = pgTable('test', {
|
||||
a: anyColumn('a').array(),
|
||||
b: anyColumn('a').array().array(),
|
||||
});
|
||||
|
||||
describe.concurrent('makePgArray', () => {
|
||||
it('parses simple 1D array', ({ expect }) => {
|
||||
const input = ['1', '2', '3'];
|
||||
const output = table.a.mapToDriverValue(input);
|
||||
expect(output).toEqual('{"1","2","3"}');
|
||||
});
|
||||
|
||||
it('parses simple 2D array', ({ expect }) => {
|
||||
const input = [
|
||||
['1', '2', '3'],
|
||||
['4', '5', '6'],
|
||||
['7', '8', '9'],
|
||||
];
|
||||
const output = table.b.mapToDriverValue(input);
|
||||
expect(output).toEqual('{{"1","2","3"},{"4","5","6"},{"7","8","9"}}');
|
||||
});
|
||||
|
||||
it('parses array with quoted values', ({ expect }) => {
|
||||
const input = ['1', '2,3', '4'];
|
||||
const output = table.a.mapToDriverValue(input);
|
||||
expect(output).toEqual('{"1","2,3","4"}');
|
||||
});
|
||||
|
||||
it('parses array with nested quoted values', ({ expect }) => {
|
||||
const input = [
|
||||
['1', '2,3', '4'],
|
||||
['5', '6,7', '8'],
|
||||
];
|
||||
const output = table.b.mapToDriverValue(input);
|
||||
expect(output).toEqual('{{"1","2,3","4"},{"5","6,7","8"}}');
|
||||
});
|
||||
|
||||
it('parses array with empty values', ({ expect }) => {
|
||||
const input = ['1', '', '3'];
|
||||
const output = table.a.mapToDriverValue(input);
|
||||
expect(output).toEqual('{"1","","3"}');
|
||||
});
|
||||
|
||||
it('parses array with empty nested values', ({ expect }) => {
|
||||
const input = [
|
||||
['1', '2', '3'],
|
||||
['', '5', '6'],
|
||||
['7', '8', '9'],
|
||||
];
|
||||
const output = table.b.mapToDriverValue(input);
|
||||
expect(output).toEqual('{{"1","2","3"},{"","5","6"},{"7","8","9"}}');
|
||||
});
|
||||
|
||||
it('parses empty array', ({ expect }) => {
|
||||
const input: string[] = [];
|
||||
const output = table.a.mapToDriverValue(input);
|
||||
expect(output).toEqual('{}');
|
||||
});
|
||||
|
||||
it('parses empty nested array', ({ expect }) => {
|
||||
const input = [[]];
|
||||
const output = table.b.mapToDriverValue(input);
|
||||
expect(output).toEqual('{{}}');
|
||||
});
|
||||
|
||||
it('parses single-level array with strings', ({ expect }) => {
|
||||
const input = ['one', 'two', 'three'];
|
||||
const output = table.a.mapToDriverValue(input);
|
||||
expect(output).toEqual('{"one","two","three"}');
|
||||
});
|
||||
|
||||
it('parses single-level array with mixed values', ({ expect }) => {
|
||||
const input = ['1', 'two', '3'];
|
||||
const output = table.a.mapToDriverValue(input);
|
||||
expect(output).toEqual('{"1","two","3"}');
|
||||
});
|
||||
|
||||
it('parses single-level array with commas inside quotes', ({ expect }) => {
|
||||
const input = ['1', 'two, three', '4'];
|
||||
const output = table.a.mapToDriverValue(input);
|
||||
expect(output).toEqual('{"1","two, three","4"}');
|
||||
});
|
||||
|
||||
it('parses single-level array with escaped quotes inside quotes', ({ expect }) => {
|
||||
const input = ['1', 'two "three", four', '5'];
|
||||
const output = table.a.mapToDriverValue(input);
|
||||
expect(output).toEqual('{"1","two \\"three\\", four","5"}');
|
||||
});
|
||||
|
||||
it('parses two-dimensional array with strings', ({ expect }) => {
|
||||
const input = [
|
||||
['one', 'two', 'three'],
|
||||
['four', 'five', 'six'],
|
||||
['seven', 'eight', 'nine'],
|
||||
];
|
||||
const output = table.b.mapToDriverValue(input);
|
||||
expect(output).toEqual('{{"one","two","three"},{"four","five","six"},{"seven","eight","nine"}}');
|
||||
});
|
||||
|
||||
it('parses two-dimensional array with mixed values and escaped quotes', ({ expect }) => {
|
||||
const input = [
|
||||
['1', 'two "and a half", three', '3'],
|
||||
['four', 'five "and a half", six', '6'],
|
||||
['seven', 'eight', 'nine'],
|
||||
];
|
||||
const output = table.b.mapToDriverValue(input);
|
||||
expect(output).toEqual(
|
||||
'{{"1","two \\"and a half\\", three","3"},{"four","five \\"and a half\\", six","6"},{"seven","eight","nine"}}',
|
||||
);
|
||||
});
|
||||
|
||||
it('parses an array with null values', ({ expect }) => {
|
||||
const input = ['1', null, '3'];
|
||||
const output = table.a.mapToDriverValue(input);
|
||||
expect(output).toEqual('{"1",null,"3"}');
|
||||
});
|
||||
|
||||
it('parses an array with null values in nested arrays', ({ expect }) => {
|
||||
const input = [
|
||||
['1', '2', '3'],
|
||||
[null, '5', '6'],
|
||||
['7', '8', '9'],
|
||||
];
|
||||
const output = table.b.mapToDriverValue(input);
|
||||
expect(output).toEqual('{{"1","2","3"},{null,"5","6"},{"7","8","9"}}');
|
||||
});
|
||||
|
||||
it('parses string array with empty strings', ({ expect }) => {
|
||||
const input = ['1', '', '3'];
|
||||
const output = table.a.mapToDriverValue(input);
|
||||
expect(output).toEqual('{"1","","3"}');
|
||||
});
|
||||
|
||||
it('parses string array with backlash strings', ({ expect }) => {
|
||||
const input = ['1', '\n', '3\\'];
|
||||
const output = table.a.mapToDriverValue(input);
|
||||
expect(output).toEqual('{"1","\n","3\\\\"}');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,119 @@
|
||||
import { describe, it } from 'vitest';
|
||||
import { customType, pgTable } from '~/pg-core/index.ts';
|
||||
|
||||
const anyColumn = customType<{ data: any }>({
|
||||
dataType() {
|
||||
return 'any';
|
||||
},
|
||||
});
|
||||
|
||||
const table = pgTable('test', {
|
||||
a: anyColumn('a').array(),
|
||||
b: anyColumn('a').array().array(),
|
||||
});
|
||||
|
||||
describe.concurrent('parsePgArray', () => {
|
||||
it('parses simple 1D array', ({ expect }) => {
|
||||
const input = '{1,2,3}';
|
||||
const output = table.a.mapFromDriverValue(input);
|
||||
expect(output).toEqual(['1', '2', '3']);
|
||||
});
|
||||
|
||||
it('parses simple 2D array', ({ expect }) => {
|
||||
const input = '{{1,2,3},{4,5,6},{7,8,9}}';
|
||||
const output = table.b.mapFromDriverValue(input);
|
||||
expect(output).toEqual([
|
||||
['1', '2', '3'],
|
||||
['4', '5', '6'],
|
||||
['7', '8', '9'],
|
||||
]);
|
||||
});
|
||||
|
||||
it('parses array with quoted values', ({ expect }) => {
|
||||
const input = '{1,"2,3",4}';
|
||||
const output = table.a.mapFromDriverValue(input);
|
||||
expect(output).toEqual(['1', '2,3', '4']);
|
||||
});
|
||||
|
||||
it('parses array with nested quoted values', ({ expect }) => {
|
||||
const input = '{{1,"2,3",4},{5,"6,7",8}}';
|
||||
const output = table.b.mapFromDriverValue(input);
|
||||
expect(output).toEqual([
|
||||
['1', '2,3', '4'],
|
||||
['5', '6,7', '8'],
|
||||
]);
|
||||
});
|
||||
|
||||
it('parses array with empty values', ({ expect }) => {
|
||||
const input = '{1,"",3}';
|
||||
const output = table.a.mapFromDriverValue(input);
|
||||
expect(output).toEqual(['1', '', '3']);
|
||||
});
|
||||
|
||||
it('parses array with empty nested values', ({ expect }) => {
|
||||
const input = '{{1,2,3},{,5,6},{7,8,9}}';
|
||||
const output = table.b.mapFromDriverValue(input);
|
||||
expect(output).toEqual([
|
||||
['1', '2', '3'],
|
||||
['', '5', '6'],
|
||||
['7', '8', '9'],
|
||||
]);
|
||||
});
|
||||
|
||||
it('parses empty array', ({ expect }) => {
|
||||
const input = '{}';
|
||||
const output = table.a.mapFromDriverValue(input);
|
||||
expect(output).toEqual([]);
|
||||
});
|
||||
|
||||
it('parses empty nested array', ({ expect }) => {
|
||||
const input = '{{}}';
|
||||
const output = table.b.mapFromDriverValue(input);
|
||||
expect(output).toEqual([[]]);
|
||||
});
|
||||
|
||||
it('parses single-level array with strings', ({ expect }) => {
|
||||
const input = '{"one","two","three"}';
|
||||
const output = table.a.mapFromDriverValue(input);
|
||||
expect(output).toEqual(['one', 'two', 'three']);
|
||||
});
|
||||
|
||||
it('parses single-level array with mixed values', ({ expect }) => {
|
||||
const input = '{1,"two",3}';
|
||||
const output = table.a.mapFromDriverValue(input);
|
||||
expect(output).toEqual(['1', 'two', '3']);
|
||||
});
|
||||
|
||||
it('parses single-level array with commas inside quotes', ({ expect }) => {
|
||||
const input = '{1,"two, three",4}';
|
||||
const output = table.a.mapFromDriverValue(input);
|
||||
expect(output).toEqual(['1', 'two, three', '4']);
|
||||
});
|
||||
|
||||
it('parses single-level array with escaped quotes inside quotes', ({ expect }) => {
|
||||
const input = '{1,"two \\"three\\", four",5}';
|
||||
const output = table.a.mapFromDriverValue(input);
|
||||
expect(output).toEqual(['1', 'two "three", four', '5']);
|
||||
});
|
||||
|
||||
it('parses two-dimensional array with strings', ({ expect }) => {
|
||||
const input = '{{"one","two",three},{"four",five,"six"},{seven,eight,"nine"}}';
|
||||
const output = table.b.mapFromDriverValue(input);
|
||||
expect(output).toEqual([
|
||||
['one', 'two', 'three'],
|
||||
['four', 'five', 'six'],
|
||||
['seven', 'eight', 'nine'],
|
||||
]);
|
||||
});
|
||||
|
||||
it('parses two-dimensional array with mixed values and escaped quotes', ({ expect }) => {
|
||||
const input =
|
||||
'{{1,"two \\"and a half\\", three",3},{"four","five \\"and a half\\", six",6},{"seven","eight","nine"}}';
|
||||
const output = table.b.mapFromDriverValue(input);
|
||||
expect(output).toEqual([
|
||||
['1', 'two "and a half", three', '3'],
|
||||
['four', 'five "and a half", six', '6'],
|
||||
['seven', 'eight', 'nine'],
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import { pgSchema, pgTable } from '~/pg-core/index.ts';
|
||||
import { createTableRelationsHelpers, extractTablesRelationalConfig } from '~/relations.ts';
|
||||
|
||||
test('tables with same name in different schemas', () => {
|
||||
const folder = pgSchema('folder');
|
||||
const schema = {
|
||||
folder: {
|
||||
usersInFolder: folder.table('users', {}),
|
||||
},
|
||||
public: {
|
||||
users: pgTable('users', {}),
|
||||
},
|
||||
};
|
||||
|
||||
const relationalSchema = {
|
||||
...Object.fromEntries(
|
||||
Object.entries(schema)
|
||||
.flatMap(([key, val]) => {
|
||||
// have unique keys across schemas
|
||||
|
||||
const mappedTableEntries = Object.entries(val).map((tableEntry) => {
|
||||
return [`__${key}__.${tableEntry[0]}`, tableEntry[1]];
|
||||
});
|
||||
|
||||
return mappedTableEntries;
|
||||
}),
|
||||
),
|
||||
};
|
||||
|
||||
const relationsConfig = extractTablesRelationalConfig(
|
||||
relationalSchema,
|
||||
createTableRelationsHelpers,
|
||||
);
|
||||
|
||||
expect(Object.keys(relationsConfig)).toHaveLength(2);
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "../tsconfig.build.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": ".."
|
||||
},
|
||||
"include": [".", "../src"]
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import { RDSDataClient } from '@aws-sdk/client-rds-data';
|
||||
import crypto from 'crypto';
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import { drizzle } from '~/aws-data-api/pg';
|
||||
import { customType, json, PgDialect, pgTable, text, timestamp, uuid, varchar } from '~/pg-core';
|
||||
import { sql } from '~/sql/sql';
|
||||
|
||||
const db = drizzle(new RDSDataClient(), {
|
||||
database: '',
|
||||
resourceArn: '',
|
||||
secretArn: '',
|
||||
});
|
||||
|
||||
test('type hints - case #1', () => {
|
||||
const t = pgTable('t', {
|
||||
id: varchar('id', { length: 255 }).primaryKey(),
|
||||
workspaceID: varchar('workspace_id', { length: 255 }).notNull(),
|
||||
description: text('description').notNull(),
|
||||
enrichment: json('enrichment').notNull(),
|
||||
category: text('category'),
|
||||
tags: text('tags').array().notNull(),
|
||||
counterpartyName: text('counterparty_name'),
|
||||
timePlaced: timestamp('time_placed').notNull(),
|
||||
timeSynced: timestamp('time_synced').notNull(),
|
||||
});
|
||||
|
||||
const q = db.insert(t).values({
|
||||
id: 'id',
|
||||
tags: [],
|
||||
workspaceID: 'workspaceID',
|
||||
enrichment: {},
|
||||
category: 'category',
|
||||
description: 'description',
|
||||
timePlaced: new Date(),
|
||||
timeSynced: sql<string>`CURRENT_TIMESTAMP(6)`,
|
||||
counterpartyName: 'counterpartyName',
|
||||
});
|
||||
|
||||
const query = new PgDialect().sqlToQuery(q.getSQL());
|
||||
|
||||
expect(query.typings).toEqual(['none', 'none', 'none', 'json', 'none', 'none', 'none', 'timestamp']);
|
||||
});
|
||||
|
||||
test('type hints - case #2', () => {
|
||||
const prefixedUlid = <Prefix extends string, PrefixedUlid = `${Prefix}_${string}`>(
|
||||
name: string,
|
||||
opts: { prefix: Prefix },
|
||||
) =>
|
||||
customType<{ data: PrefixedUlid; driverData: string }>({
|
||||
dataType: () => 'uuid',
|
||||
toDriver: (value) => {
|
||||
return value as string;
|
||||
},
|
||||
fromDriver: (value) => {
|
||||
return `${opts.prefix}_${value}` as PrefixedUlid;
|
||||
},
|
||||
})(name);
|
||||
|
||||
const calendars = pgTable('calendars', {
|
||||
id: uuid('id').primaryKey().default(sql`gen_random_uuid()`),
|
||||
orgMembershipId: prefixedUlid('om_id', { prefix: 'om' }).notNull(),
|
||||
platform: text('platform').notNull(),
|
||||
externalId: text('external_id').notNull(),
|
||||
externalData: json('external_data').notNull(),
|
||||
updatedAt: timestamp('updated_at').notNull().default(sql`now()`),
|
||||
createdAt: timestamp('created_at').notNull().default(sql`now()`),
|
||||
});
|
||||
|
||||
const q = db
|
||||
.insert(calendars)
|
||||
.values({
|
||||
id: crypto.randomUUID(),
|
||||
orgMembershipId: 'om_id',
|
||||
platform: 'platform',
|
||||
externalId: 'externalId',
|
||||
externalData: {},
|
||||
})
|
||||
.returning();
|
||||
|
||||
const query = new PgDialect().sqlToQuery(q.getSQL());
|
||||
|
||||
expect(query.typings).toEqual(['uuid', 'none', 'none', 'none', 'json']);
|
||||
});
|
||||
Reference in New Issue
Block a user