923 lines
31 KiB
TypeScript
923 lines
31 KiB
TypeScript
import { sql } from 'drizzle-orm';
|
|
import { drizzle } from 'drizzle-orm/singlestore';
|
|
import { serial, singlestoreTable, withReplicas } from 'drizzle-orm/singlestore-core';
|
|
import { describe, expect, it, vi } from 'vitest';
|
|
|
|
// const usersTable = singlestoreTable('users', {
|
|
// id: serial('id' as string).primaryKey(),
|
|
// name: text('name').notNull(),
|
|
// verified: boolean('verified').notNull().default(false),
|
|
// });
|
|
|
|
const users = singlestoreTable('users', {
|
|
id: serial('id' as string).primaryKey(),
|
|
});
|
|
|
|
describe('[select] read replicas singlestore', () => {
|
|
it('primary select', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
const read2 = drizzle.mock();
|
|
|
|
const db = withReplicas(primaryDb, [read1, read2]);
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, 'select');
|
|
const spyRead1 = vi.spyOn(read1, 'select');
|
|
const spyRead2 = vi.spyOn(read2, 'select');
|
|
|
|
const query = db.$primary.select().from(users);
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(1);
|
|
expect(query.toSQL().sql).toEqual('select `id` from `users`');
|
|
|
|
expect(spyRead1).toHaveBeenCalledTimes(0);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
});
|
|
|
|
it('random replica select', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
const read2 = drizzle.mock();
|
|
|
|
const randomMockReplica = vi.fn().mockReturnValueOnce(read1).mockReturnValueOnce(read2);
|
|
|
|
const db = withReplicas(primaryDb, [read1, read2], () => {
|
|
return randomMockReplica();
|
|
});
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, 'select');
|
|
const spyRead1 = vi.spyOn(read1, 'select');
|
|
const spyRead2 = vi.spyOn(read2, 'select');
|
|
|
|
const query1 = db.select({ count: sql`count(*)`.as('count') }).from(users).limit(1);
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
|
|
expect(query1.toSQL().sql).toEqual('select count(*) as `count` from `users` limit ?');
|
|
|
|
const query2 = db.select().from(users);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
expect(spyRead2).toHaveBeenCalledTimes(1);
|
|
expect(query2.toSQL().sql).toEqual('select `id` from `users`');
|
|
});
|
|
|
|
it('single read replica select', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
|
|
const db = withReplicas(primaryDb, [read1]);
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, 'select');
|
|
const spyRead1 = vi.spyOn(read1, 'select');
|
|
|
|
const query1 = db.select().from(users);
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
expect(query1.toSQL().sql).toEqual('select `id` from `users`');
|
|
|
|
const query2 = db.select().from(users);
|
|
expect(spyRead1).toHaveBeenCalledTimes(2);
|
|
expect(query2.toSQL().sql).toEqual('select `id` from `users`');
|
|
});
|
|
|
|
it('single read replica select + primary select', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
|
|
const db = withReplicas(primaryDb, [read1]);
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, 'select');
|
|
const spyRead1 = vi.spyOn(read1, 'select');
|
|
|
|
const query1 = db.select({ id: users.id }).from(users);
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
expect(query1.toSQL().sql).toEqual('select `id` from `users`');
|
|
|
|
const query2 = db.$primary.select().from(users);
|
|
expect(spyPrimary).toHaveBeenCalledTimes(1);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
expect(query2.toSQL().sql).toEqual('select `id` from `users`');
|
|
});
|
|
|
|
it('always first read select', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
const read2 = drizzle.mock();
|
|
|
|
const db = withReplicas(primaryDb, [read1, read2], (replicas) => {
|
|
return replicas[0]!;
|
|
});
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, 'select');
|
|
const spyRead1 = vi.spyOn(read1, 'select');
|
|
const spyRead2 = vi.spyOn(read2, 'select');
|
|
|
|
const query1 = db.select().from(users);
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
expect(query1.toSQL().sql).toEqual('select `id` from `users`');
|
|
|
|
const query2 = db.select().from(users);
|
|
|
|
expect(spyRead1).toHaveBeenCalledTimes(2);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
expect(query2.toSQL().sql).toEqual('select `id` from `users`');
|
|
});
|
|
});
|
|
|
|
describe('[selectDistinct] read replicas singlestore', () => {
|
|
it('primary selectDistinct', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
const read2 = drizzle.mock();
|
|
|
|
const db = withReplicas(primaryDb, [read1, read2]);
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, 'selectDistinct');
|
|
const spyRead1 = vi.spyOn(read1, 'selectDistinct');
|
|
const spyRead2 = vi.spyOn(read2, 'selectDistinct');
|
|
|
|
const query = db.$primary.selectDistinct().from(users);
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(1);
|
|
expect(spyRead1).toHaveBeenCalledTimes(0);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
expect(query.toSQL().sql).toEqual('select distinct `id` from `users`');
|
|
});
|
|
|
|
it('random replica selectDistinct', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
const read2 = drizzle.mock();
|
|
|
|
const randomMockReplica = vi.fn().mockReturnValueOnce(read1).mockReturnValueOnce(read2);
|
|
|
|
const db = withReplicas(primaryDb, [read1, read2], () => {
|
|
return randomMockReplica();
|
|
});
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, 'selectDistinct');
|
|
const spyRead1 = vi.spyOn(read1, 'selectDistinct');
|
|
const spyRead2 = vi.spyOn(read2, 'selectDistinct');
|
|
|
|
const query1 = db.selectDistinct().from(users);
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
expect(query1.toSQL().sql).toEqual('select distinct `id` from `users`');
|
|
|
|
const query2 = db.selectDistinct().from(users);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
expect(spyRead2).toHaveBeenCalledTimes(1);
|
|
expect(query2.toSQL().sql).toEqual('select distinct `id` from `users`');
|
|
});
|
|
|
|
it('single read replica selectDistinct', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
|
|
const db = withReplicas(primaryDb, [read1]);
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, 'selectDistinct');
|
|
const spyRead1 = vi.spyOn(read1, 'selectDistinct');
|
|
|
|
const query1 = db.selectDistinct().from(users);
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
expect(query1.toSQL().sql).toEqual('select distinct `id` from `users`');
|
|
|
|
const query2 = db.selectDistinct().from(users);
|
|
expect(spyRead1).toHaveBeenCalledTimes(2);
|
|
expect(query2.toSQL().sql).toEqual('select distinct `id` from `users`');
|
|
});
|
|
|
|
it('single read replica selectDistinct + primary selectDistinct', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
|
|
const db = withReplicas(primaryDb, [read1]);
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, 'selectDistinct');
|
|
const spyRead1 = vi.spyOn(read1, 'selectDistinct');
|
|
|
|
const query1 = db.selectDistinct().from(users);
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
expect(query1.toSQL().sql).toEqual('select distinct `id` from `users`');
|
|
|
|
const query2 = db.$primary.selectDistinct().from(users);
|
|
expect(spyPrimary).toHaveBeenCalledTimes(1);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
expect(query2.toSQL().sql).toEqual('select distinct `id` from `users`');
|
|
});
|
|
|
|
it('always first read selectDistinct', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
const read2 = drizzle.mock();
|
|
|
|
const db = withReplicas(primaryDb, [read1, read2], (replicas) => {
|
|
return replicas[0]!;
|
|
});
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, 'selectDistinct');
|
|
const spyRead1 = vi.spyOn(read1, 'selectDistinct');
|
|
const spyRead2 = vi.spyOn(read2, 'selectDistinct');
|
|
|
|
const query1 = db.selectDistinct().from(users);
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
expect(query1.toSQL().sql).toEqual('select distinct `id` from `users`');
|
|
|
|
const query2 = db.selectDistinct().from(users);
|
|
expect(spyRead1).toHaveBeenCalledTimes(2);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
expect(query2.toSQL().sql).toEqual('select distinct `id` from `users`');
|
|
});
|
|
});
|
|
|
|
describe('[with] read replicas singlestore', () => {
|
|
it('primary with', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
const read2 = drizzle.mock();
|
|
|
|
const db = withReplicas(primaryDb, [read1, read2]);
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, 'with');
|
|
const spyRead1 = vi.spyOn(read1, 'with');
|
|
const spyRead2 = vi.spyOn(read2, 'with');
|
|
const obj1 = {} as any;
|
|
const obj2 = {} as any;
|
|
const obj3 = {} as any;
|
|
const obj4 = {} as any;
|
|
|
|
db.$primary.with(obj1, obj2, obj3, obj4);
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(1);
|
|
expect(spyRead1).toHaveBeenCalledTimes(0);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
expect(spyPrimary).toHaveBeenCalledWith(obj1, obj2, obj3, obj4);
|
|
});
|
|
|
|
it('random replica with', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
const read2 = drizzle.mock();
|
|
|
|
const randomMockReplica = vi.fn().mockReturnValueOnce(read1).mockReturnValueOnce(read2);
|
|
|
|
const db = withReplicas(primaryDb, [read1, read2], () => {
|
|
return randomMockReplica();
|
|
});
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, 'with');
|
|
const spyRead1 = vi.spyOn(read1, 'with');
|
|
const spyRead2 = vi.spyOn(read2, 'with');
|
|
|
|
db.with();
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
|
|
db.with();
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
expect(spyRead2).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('single read replica with', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
|
|
const db = withReplicas(primaryDb, [read1]);
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, 'with');
|
|
const spyRead1 = vi.spyOn(read1, 'with');
|
|
|
|
db.with();
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
|
|
db.with();
|
|
expect(spyRead1).toHaveBeenCalledTimes(2);
|
|
});
|
|
|
|
it('single read replica with + primary with', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
|
|
const db = withReplicas(primaryDb, [read1]);
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, 'with');
|
|
const spyRead1 = vi.spyOn(read1, 'with');
|
|
|
|
db.with();
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
|
|
db.$primary.with();
|
|
expect(spyPrimary).toHaveBeenCalledTimes(1);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('always first read with', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
const read2 = drizzle.mock();
|
|
|
|
const db = withReplicas(primaryDb, [read1, read2], (replicas) => {
|
|
return replicas[0]!;
|
|
});
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, 'with');
|
|
const spyRead1 = vi.spyOn(read1, 'with');
|
|
const spyRead2 = vi.spyOn(read2, 'with');
|
|
const obj1 = {} as any;
|
|
const obj2 = {} as any;
|
|
const obj3 = {} as any;
|
|
|
|
db.with(obj1);
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
expect(spyRead1).toHaveBeenCalledWith(obj1);
|
|
|
|
db.with(obj2, obj3);
|
|
expect(spyRead1).toHaveBeenCalledTimes(2);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
expect(spyRead1).toHaveBeenCalledWith(obj2, obj3);
|
|
});
|
|
});
|
|
|
|
describe('[update] replicas singlestore', () => {
|
|
it('primary update', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
const read2 = drizzle.mock();
|
|
|
|
const db = withReplicas(primaryDb, [read1, read2]);
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, 'update');
|
|
const spyRead1 = vi.spyOn(read1, 'update');
|
|
const spyRead2 = vi.spyOn(read2, 'update');
|
|
|
|
const query1 = db.update(users).set({ id: 1 });
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(1);
|
|
expect(spyRead1).toHaveBeenCalledTimes(0);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
expect(query1.toSQL().sql).toEqual('update `users` set `id` = ?');
|
|
|
|
const query2 = db.update(users).set({ id: 1 });
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(2);
|
|
expect(spyRead1).toHaveBeenCalledTimes(0);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
expect(query2.toSQL().sql).toEqual('update `users` set `id` = ?');
|
|
|
|
const query3 = db.$primary.update(users).set({ id: 1 });
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(3);
|
|
expect(spyRead1).toHaveBeenCalledTimes(0);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
expect(query3.toSQL().sql).toEqual('update `users` set `id` = ?');
|
|
});
|
|
});
|
|
|
|
describe('[delete] replicas singlestore', () => {
|
|
it('primary delete', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
const read2 = drizzle.mock();
|
|
|
|
const db = withReplicas(primaryDb, [read1, read2]);
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, 'delete');
|
|
const spyRead1 = vi.spyOn(read1, 'delete');
|
|
const spyRead2 = vi.spyOn(read2, 'delete');
|
|
|
|
const query1 = db.delete(users);
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(1);
|
|
expect(spyRead1).toHaveBeenCalledTimes(0);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
expect(spyPrimary).toHaveBeenCalledWith(users);
|
|
expect(query1.toSQL().sql).toEqual('delete from `users`');
|
|
|
|
const query2 = db.delete(users);
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(2);
|
|
expect(spyRead1).toHaveBeenCalledTimes(0);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
expect(spyPrimary).toHaveBeenNthCalledWith(2, users);
|
|
expect(query2.toSQL().sql).toEqual('delete from `users`');
|
|
|
|
db.$primary.delete({} as any);
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(3);
|
|
expect(spyRead1).toHaveBeenCalledTimes(0);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
});
|
|
});
|
|
|
|
describe('[insert] replicas singlestore', () => {
|
|
it('primary insert', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
const read2 = drizzle.mock();
|
|
|
|
const db = withReplicas(primaryDb, [read1, read2]);
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, 'insert');
|
|
const spyRead1 = vi.spyOn(read1, 'insert');
|
|
const spyRead2 = vi.spyOn(read2, 'insert');
|
|
|
|
const query = db.insert(users).values({ id: 1 });
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(1);
|
|
expect(spyRead1).toHaveBeenCalledTimes(0);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
expect(spyPrimary).toHaveBeenCalledWith(users);
|
|
expect(query.toSQL().sql).toEqual('insert into `users` (`id`) values (?)');
|
|
|
|
db.insert(users);
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(2);
|
|
expect(spyRead1).toHaveBeenCalledTimes(0);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
expect(spyPrimary).toHaveBeenNthCalledWith(2, users);
|
|
|
|
db.$primary.insert({} as any);
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(3);
|
|
expect(spyRead1).toHaveBeenCalledTimes(0);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
});
|
|
});
|
|
|
|
describe('[execute] replicas singlestore', () => {
|
|
it('primary execute', async () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
const read2 = drizzle.mock();
|
|
|
|
const db = withReplicas(primaryDb, [read1, read2]);
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, 'execute');
|
|
const spyRead1 = vi.spyOn(read1, 'execute');
|
|
const spyRead2 = vi.spyOn(read2, 'execute');
|
|
|
|
expect(db.execute(sql``)).rejects.toThrow();
|
|
|
|
// try {
|
|
// db.execute(sql``);
|
|
// } catch { /* empty */ }
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(1);
|
|
expect(spyRead1).toHaveBeenCalledTimes(0);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
|
|
expect(db.execute(sql``)).rejects.toThrow();
|
|
// try {
|
|
// db.execute(sql``);
|
|
// } catch { /* empty */ }
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(2);
|
|
expect(spyRead1).toHaveBeenCalledTimes(0);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
|
|
expect(db.execute(sql``)).rejects.toThrow();
|
|
// try {
|
|
// db.execute(sql``);
|
|
// } catch { /* empty */ }
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(3);
|
|
expect(spyRead1).toHaveBeenCalledTimes(0);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
});
|
|
});
|
|
|
|
describe('[transaction] replicas singlestore', () => {
|
|
it('primary transaction', async () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
const read2 = drizzle.mock();
|
|
|
|
const db = withReplicas(primaryDb, [read1, read2]);
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, 'transaction');
|
|
const spyRead1 = vi.spyOn(read1, 'transaction');
|
|
const spyRead2 = vi.spyOn(read2, 'transaction');
|
|
const txFn1 = async (tx: any) => {
|
|
tx.select().from({} as any);
|
|
};
|
|
|
|
expect(db.transaction(txFn1)).rejects.toThrow();
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(1);
|
|
expect(spyRead1).toHaveBeenCalledTimes(0);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
expect(spyPrimary).toHaveBeenCalledWith(txFn1);
|
|
|
|
const txFn2 = async (tx: any) => {
|
|
tx.select().from({} as any);
|
|
};
|
|
|
|
expect(db.transaction(txFn2)).rejects.toThrow();
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(2);
|
|
expect(spyRead1).toHaveBeenCalledTimes(0);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
expect(spyPrimary).toHaveBeenNthCalledWith(2, txFn2);
|
|
|
|
expect(db.transaction(async (tx) => {
|
|
tx.select().from({} as any);
|
|
})).rejects.toThrow();
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(3);
|
|
expect(spyRead1).toHaveBeenCalledTimes(0);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
});
|
|
});
|
|
|
|
// We are waiting for SingleStore support for `json_array` function
|
|
// describe('[findFirst] read replicas singlestore', () => {
|
|
// // it('primary findFirst', () => {
|
|
// // const primaryDb = drizzle.mock({ schema: { usersTable } });
|
|
// // const read1 = drizzle.mock({ schema: { usersTable } });
|
|
// // const read2 = drizzle.mock({ schema: { usersTable } });
|
|
|
|
// // const db = withReplicas(primaryDb, [read1, read2]);
|
|
|
|
// // const spyPrimary = vi.spyOn(primaryDb['query']['usersTable'], 'findFirst');
|
|
// // const spyRead1 = vi.spyOn(read1['query']['usersTable'], 'findFirst');
|
|
// // const spyRead2 = vi.spyOn(read2['query']['usersTable'], 'findFirst');
|
|
// // const obj = {} as any;
|
|
|
|
// // db.$primary.query.usersTable.findFirst(obj);
|
|
|
|
// // expect(spyPrimary).toHaveBeenCalledTimes(1);
|
|
// // expect(spyRead1).toHaveBeenCalledTimes(0);
|
|
// // expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
// // expect(spyPrimary).toHaveBeenCalledWith(obj);
|
|
// // });
|
|
|
|
// // it('random replica findFirst', () => {
|
|
// // const primaryDb = drizzle.mock({ schema: { usersTable } });
|
|
// // const read1 = drizzle.mock({ schema: { usersTable } });
|
|
// // const read2 = drizzle.mock({ schema: { usersTable } });
|
|
|
|
// // const randomMockReplica = vi.fn().mockReturnValueOnce(read1).mockReturnValueOnce(read2);
|
|
|
|
// // const db = withReplicas(primaryDb, [read1, read2], () => {
|
|
// // return randomMockReplica();
|
|
// // });
|
|
|
|
// // const spyPrimary = vi.spyOn(primaryDb['query']['usersTable'], 'findFirst');
|
|
// // const spyRead1 = vi.spyOn(read1['query']['usersTable'], 'findFirst');
|
|
// // const spyRead2 = vi.spyOn(read2['query']['usersTable'], 'findFirst');
|
|
// // const par1 = {} as any;
|
|
|
|
// // db.query.usersTable.findFirst(par1);
|
|
|
|
// // expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
// // expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
// // expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
// // expect(spyRead1).toHaveBeenCalledWith(par1);
|
|
|
|
// // const query = db.query.usersTable.findFirst();
|
|
// // expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
// // expect(spyRead2).toHaveBeenCalledTimes(1);
|
|
// // expect(query.toSQL().sql).toEqual('select `id`, `name`, `verified` from `users` `usersTable` limit ?');
|
|
// // });
|
|
|
|
// // We are waiting for SingleStore support for `json_array` function
|
|
// // it('single read replica findFirst', () => {
|
|
// // const primaryDb = drizzle.mock({ schema: { usersTable } });
|
|
// // const read1 = drizzle.mock({ schema: { usersTable } });
|
|
|
|
// // const db = withReplicas(primaryDb, [read1]);
|
|
|
|
// // const spyPrimary = vi.spyOn(primaryDb['query']['usersTable'], 'findFirst');
|
|
// // const spyRead1 = vi.spyOn(read1['query']['usersTable'], 'findFirst');
|
|
|
|
// // db.query.usersTable.findFirst();
|
|
|
|
// // expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
// // expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
|
|
// // db.query.usersTable.findFirst();
|
|
// // expect(spyRead1).toHaveBeenCalledTimes(2);
|
|
// // });
|
|
|
|
// // We are waiting for SingleStore support for `json_array` function
|
|
// // it('single read replica findFirst + primary findFirst', () => {
|
|
// // const primaryDb = drizzle.mock({ schema: { usersTable } });
|
|
// // const read1 = drizzle.mock({ schema: { usersTable } });
|
|
|
|
// // const db = withReplicas(primaryDb, [read1]);
|
|
|
|
// // const spyPrimary = vi.spyOn(primaryDb['query']['usersTable'], 'findFirst');
|
|
// // const spyRead1 = vi.spyOn(read1['query']['usersTable'], 'findFirst');
|
|
|
|
// // db.query.usersTable.findFirst();
|
|
|
|
// // expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
// // expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
|
|
// // db.$primary.query.usersTable.findFirst();
|
|
// // expect(spyPrimary).toHaveBeenCalledTimes(1);
|
|
// // expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
// // });
|
|
|
|
// // We are waiting for SingleStore support for `json_array` function
|
|
// // it('always first read findFirst', () => {
|
|
// // const primaryDb = drizzle.mock({ schema: { usersTable } });
|
|
// // const read1 = drizzle.mock({ schema: { usersTable } });
|
|
// // const read2 = drizzle.mock({ schema: { usersTable } });
|
|
|
|
// // const db = withReplicas(primaryDb, [read1, read2], (replicas) => {
|
|
// // return replicas[0]!;
|
|
// // });
|
|
|
|
// // const spyPrimary = vi.spyOn(primaryDb['query']['usersTable'], 'findFirst');
|
|
// // const spyRead1 = vi.spyOn(read1['query']['usersTable'], 'findFirst');
|
|
// // const spyRead2 = vi.spyOn(read2['query']['usersTable'], 'findFirst');
|
|
|
|
// // db.query.usersTable.findFirst();
|
|
|
|
// // expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
// // expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
// // expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
|
|
// // db.query.usersTable.findFirst();
|
|
// // expect(spyRead1).toHaveBeenCalledTimes(2);
|
|
// // expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
// // });
|
|
// });
|
|
|
|
// describe('[findMany] read replicas singlestore', () => {
|
|
// // We are waiting for SingleStore support for `json_array` function
|
|
// // it('primary findMany', () => {
|
|
// // const primaryDb = drizzle.mock({ schema: { usersTable } });
|
|
// // const read1 = drizzle.mock({ schema: { usersTable } });
|
|
// // const read2 = drizzle.mock({ schema: { usersTable } });
|
|
|
|
// // const db = withReplicas(primaryDb, [read1, read2]);
|
|
|
|
// // const spyPrimary = vi.spyOn(primaryDb['query']['usersTable'], 'findMany');
|
|
// // const spyRead1 = vi.spyOn(read1['query']['usersTable'], 'findMany');
|
|
// // const spyRead2 = vi.spyOn(read2['query']['usersTable'], 'findMany');
|
|
// // const obj = {} as any;
|
|
|
|
// // const query = db.$primary.query.usersTable.findMany(obj);
|
|
|
|
// // expect(spyPrimary).toHaveBeenCalledTimes(1);
|
|
// // expect(spyRead1).toHaveBeenCalledTimes(0);
|
|
// // expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
// // expect(spyPrimary).toHaveBeenCalledWith(obj);
|
|
// // expect(query.toSQL().sql).toEqual('select `id`, `name`, `verified` from `users` `usersTable`');
|
|
// // });
|
|
|
|
// // We are waiting for SingleStore support for `json_array` function
|
|
// // it('random replica findMany', () => {
|
|
// // const primaryDb = drizzle.mock({ schema: { usersTable } });
|
|
// // const read1 = drizzle.mock({ schema: { usersTable } });
|
|
// // const read2 = drizzle.mock({ schema: { usersTable } });
|
|
|
|
// // const randomMockReplica = vi.fn().mockReturnValueOnce(read1).mockReturnValueOnce(read2);
|
|
|
|
// // const db = withReplicas(primaryDb, [read1, read2], () => {
|
|
// // return randomMockReplica();
|
|
// // });
|
|
|
|
// // const spyPrimary = vi.spyOn(primaryDb['query']['usersTable'], 'findMany');
|
|
// // const spyRead1 = vi.spyOn(read1['query']['usersTable'], 'findMany');
|
|
// // const spyRead2 = vi.spyOn(read2['query']['usersTable'], 'findMany');
|
|
// // const obj1 = {} as any;
|
|
// // const obj2 = {} as any;
|
|
|
|
// // const query1 = db.query.usersTable.findMany(obj1);
|
|
|
|
// // expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
// // expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
// // expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
// // expect(query1.toSQL().sql).toEqual('select `id`, `name`, `verified` from `users` `usersTable`');
|
|
// // expect(spyRead1).toHaveBeenCalledWith(obj1);
|
|
|
|
// // const query2 = db.query.usersTable.findMany(obj2);
|
|
|
|
// // expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
// // expect(spyRead2).toHaveBeenCalledTimes(1);
|
|
// // expect(query2.toSQL().sql).toEqual('select `id`, `name`, `verified` from `users` `usersTable`');
|
|
// // expect(spyRead2).toHaveBeenCalledWith(obj2);
|
|
// // });
|
|
|
|
// // We are waiting for SingleStore support for `json_array` function
|
|
// // it('single read replica findMany', () => {
|
|
// // const primaryDb = drizzle.mock({ schema: { usersTable } });
|
|
// // const read1 = drizzle.mock({ schema: { usersTable } });
|
|
|
|
// // const db = withReplicas(primaryDb, [read1]);
|
|
|
|
// // const spyPrimary = vi.spyOn(primaryDb['query']['usersTable'], 'findMany');
|
|
// // const spyRead1 = vi.spyOn(read1['query']['usersTable'], 'findMany');
|
|
// // const obj1 = {} as any;
|
|
// // const obj2 = {} as any;
|
|
|
|
// // const query1 = db.query.usersTable.findMany(obj1);
|
|
|
|
// // expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
// // expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
// // expect(spyRead1).toHaveBeenCalledWith(obj1);
|
|
// // expect(query1.toSQL().sql).toEqual('select `id`, `name`, `verified` from `users` `usersTable`');
|
|
|
|
// // const query2 = db.query.usersTable.findMany(obj2);
|
|
// // expect(spyRead1).toHaveBeenCalledTimes(2);
|
|
// // expect(spyRead1).toHaveBeenNthCalledWith(2, obj2);
|
|
// // expect(query2.toSQL().sql).toEqual('select `id`, `name`, `verified` from `users` `usersTable`');
|
|
// // });
|
|
|
|
// // We are waiting for SingleStore support for `json_array` function
|
|
// // it('single read replica findMany + primary findMany', () => {
|
|
// // const primaryDb = drizzle.mock({ schema: { usersTable } });
|
|
// // const read1 = drizzle.mock({ schema: { usersTable } });
|
|
|
|
// // const db = withReplicas(primaryDb, [read1]);
|
|
|
|
// // const spyPrimary = vi.spyOn(primaryDb['query']['usersTable'], 'findMany');
|
|
// // const spyRead1 = vi.spyOn(read1['query']['usersTable'], 'findMany');
|
|
// // const obj1 = {} as any;
|
|
// // const obj2 = {} as any;
|
|
|
|
// // const query1 = db.query.usersTable.findMany(obj1);
|
|
|
|
// // expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
// // expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
// // expect(spyRead1).toHaveBeenCalledWith(obj1);
|
|
// // expect(query1.toSQL().sql).toEqual('select `id`, `name`, `verified` from `users` `usersTable`');
|
|
|
|
// // const query2 = db.$primary.query.usersTable.findMany(obj2);
|
|
|
|
// // expect(spyPrimary).toHaveBeenCalledTimes(1);
|
|
// // expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
// // expect(spyPrimary).toHaveBeenNthCalledWith(1, obj2);
|
|
// // expect(query2.toSQL().sql).toEqual('select `id`, `name`, `verified` from `users` `usersTable`');
|
|
// // });
|
|
|
|
// // We are waiting for SingleStore support for `json_array` function
|
|
// // it('always first read findMany', () => {
|
|
// // const primaryDb = drizzle.mock({ schema: { usersTable } });
|
|
// // const read1 = drizzle.mock({ schema: { usersTable } });
|
|
// // const read2 = drizzle.mock({ schema: { usersTable } });
|
|
|
|
// // const db = withReplicas(primaryDb, [read1, read2], (replicas) => {
|
|
// // return replicas[0]!;
|
|
// // });
|
|
|
|
// // const spyPrimary = vi.spyOn(primaryDb['query']['usersTable'], 'findMany');
|
|
// // const spyRead1 = vi.spyOn(read1['query']['usersTable'], 'findMany');
|
|
// // const spyRead2 = vi.spyOn(read2['query']['usersTable'], 'findMany');
|
|
// // const obj1 = {} as any;
|
|
// // const obj2 = {} as any;
|
|
|
|
// // const query1 = db.query.usersTable.findMany(obj1);
|
|
|
|
// // expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
// // expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
// // expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
// // expect(spyRead1).toHaveBeenCalledWith(obj1);
|
|
// // expect(query1.toSQL().sql).toEqual('select `id`, `name`, `verified` from `users` `usersTable`');
|
|
|
|
// // const query2 = db.query.usersTable.findMany(obj2);
|
|
// // expect(spyRead1).toHaveBeenCalledTimes(2);
|
|
// // expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
// // expect(spyRead1).toHaveBeenNthCalledWith(2, obj2);
|
|
// // expect(query2.toSQL().sql).toEqual('select `id`, `name`, `verified` from `users` `usersTable`');
|
|
// // });
|
|
// });
|
|
|
|
describe('[$count] read replicas postgres', () => {
|
|
it('primary $count', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
const read2 = drizzle.mock();
|
|
|
|
const db = withReplicas(primaryDb, [read1, read2]);
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, '$count');
|
|
const spyRead1 = vi.spyOn(read1, '$count');
|
|
const spyRead2 = vi.spyOn(read2, '$count');
|
|
|
|
db.$primary.$count(users);
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(1);
|
|
expect(spyRead1).toHaveBeenCalledTimes(0);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
});
|
|
|
|
it('random replica $count', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
const read2 = drizzle.mock();
|
|
|
|
const randomMockReplica = vi.fn().mockReturnValueOnce(read1).mockReturnValueOnce(read2);
|
|
|
|
const db = withReplicas(primaryDb, [read1, read2], () => {
|
|
return randomMockReplica();
|
|
});
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, '$count');
|
|
const spyRead1 = vi.spyOn(read1, '$count');
|
|
const spyRead2 = vi.spyOn(read2, '$count');
|
|
|
|
db.$count(users);
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
|
|
db.select().from(users);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
});
|
|
|
|
it('single read replica $count', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
|
|
const db = withReplicas(primaryDb, [read1]);
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, '$count');
|
|
const spyRead1 = vi.spyOn(read1, '$count');
|
|
|
|
db.$count(users);
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
|
|
db.$count(users);
|
|
expect(spyRead1).toHaveBeenCalledTimes(2);
|
|
});
|
|
|
|
it('single read replica $count + primary $count', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
|
|
const db = withReplicas(primaryDb, [read1]);
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, '$count');
|
|
const spyRead1 = vi.spyOn(read1, '$count');
|
|
|
|
db.$count(users);
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
|
|
db.$primary.$count(users);
|
|
expect(spyPrimary).toHaveBeenCalledTimes(1);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('always first read $count', () => {
|
|
const primaryDb = drizzle.mock();
|
|
const read1 = drizzle.mock();
|
|
const read2 = drizzle.mock();
|
|
|
|
const db = withReplicas(primaryDb, [read1, read2], (replicas) => {
|
|
return replicas[0]!;
|
|
});
|
|
|
|
const spyPrimary = vi.spyOn(primaryDb, '$count');
|
|
const spyRead1 = vi.spyOn(read1, '$count');
|
|
const spyRead2 = vi.spyOn(read2, '$count');
|
|
|
|
db.$count(users);
|
|
|
|
expect(spyPrimary).toHaveBeenCalledTimes(0);
|
|
expect(spyRead1).toHaveBeenCalledTimes(1);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
|
|
db.$count(users);
|
|
|
|
expect(spyRead1).toHaveBeenCalledTimes(2);
|
|
expect(spyRead2).toHaveBeenCalledTimes(0);
|
|
});
|
|
});
|