From 68c844cb8f5d280848ea73785529e883252dfbb2 Mon Sep 17 00:00:00 2001 From: realmikesolo Date: Sun, 28 Apr 2024 18:02:25 +0200 Subject: [PATCH 1/5] add: if chain method --- drizzle-orm/src/sql/sql.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drizzle-orm/src/sql/sql.ts b/drizzle-orm/src/sql/sql.ts index 306f82519..b4b0e7c94 100644 --- a/drizzle-orm/src/sql/sql.ts +++ b/drizzle-orm/src/sql/sql.ts @@ -319,6 +319,16 @@ export class SQL implements SQLWrapper { this.shouldInlineParams = true; return this; } + + /** + * This method is used to conditionally include a part of the query. + * + * @param condition - Condition to check + * @returns SQL if the condition is true, otherwise undefined + */ + if(condition: any): this | undefined { + return condition ? this : undefined; + } } export type GetDecoderResult = T extends Column ? T['_']['data'] : T extends From cd0a1aa52a3cecc55cd79a413a4e01989d5f9f9e Mon Sep 17 00:00:00 2001 From: realmikesolo Date: Mon, 29 Apr 2024 22:40:15 +0200 Subject: [PATCH 2/5] add: test for if method --- integration-tests/tests/pg.test.ts | 46 ++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/integration-tests/tests/pg.test.ts b/integration-tests/tests/pg.test.ts index 3f7305cfa..f8cdb40c5 100644 --- a/integration-tests/tests/pg.test.ts +++ b/integration-tests/tests/pg.test.ts @@ -4125,3 +4125,49 @@ test.serial('test $onUpdateFn and $onUpdate works updating', async (t) => { t.assert(eachUser.updatedAt!.valueOf() > Date.now() - msDelay); } }); + +test.serial('test if method with sql operators', async (t) => { + const { db } = t.context; + + const users = pgTable('users', { + id: serial('id').primaryKey(), + name: text('name').notNull(), + age: integer('age').notNull(), + }); + + await db.execute(sql`drop table if exists ${users}`); + + await db.execute(sql` + create table ${users} ( + id serial primary key, + name text not null, + age integer not null + ) + `); + + await db.insert(users).values([ + { id: 1, name: 'John', age: 20 }, + { id: 2, name: 'Alice', age: 21 }, + { id: 3, name: 'Nick', age: 22 }, + { id: 4, name: 'Lina', age: 23 }, + ]); + + const condition1 = true; + + const [result1] = await db.select().from(users).where(eq(users.id, 1).if(condition1)); + + t.deepEqual(result1, { id: 1, name: 'John', age: 20 }); + + const condition2 = false; + + const result2 = await db.select().from(users).where(eq(users.id, 1).if(condition2)); + + t.deepEqual(result2, [ + { id: 1, name: 'John', age: 20 }, + { id: 2, name: 'Alice', age: 21 }, + { id: 3, name: 'Nick', age: 22 }, + { id: 4, name: 'Lina', age: 23 }, + ]); + + await db.execute(sql`drop table ${users}`); +}); From 394705b741d49cafca2af809f3dcac296358f416 Mon Sep 17 00:00:00 2001 From: realmikesolo Date: Wed, 1 May 2024 13:18:02 +0200 Subject: [PATCH 3/5] make edits according to the review --- drizzle-orm/src/sql/sql.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drizzle-orm/src/sql/sql.ts b/drizzle-orm/src/sql/sql.ts index b4b0e7c94..c680486cc 100644 --- a/drizzle-orm/src/sql/sql.ts +++ b/drizzle-orm/src/sql/sql.ts @@ -324,9 +324,9 @@ export class SQL implements SQLWrapper { * This method is used to conditionally include a part of the query. * * @param condition - Condition to check - * @returns SQL if the condition is true, otherwise undefined + * @returns itself if the condition is `true`, otherwise `undefined` */ - if(condition: any): this | undefined { + if(condition: any | undefined): this | undefined { return condition ? this : undefined; } } From 5868dec4b7dcc62f3dcf454a1c0e34b57b7e7a3b Mon Sep 17 00:00:00 2001 From: realmikesolo Date: Wed, 1 May 2024 13:18:16 +0200 Subject: [PATCH 4/5] add: more tests --- integration-tests/tests/pg.test.ts | 192 ++++++++++++++++++++++++++--- 1 file changed, 173 insertions(+), 19 deletions(-) diff --git a/integration-tests/tests/pg.test.ts b/integration-tests/tests/pg.test.ts index f8cdb40c5..af2febed2 100644 --- a/integration-tests/tests/pg.test.ts +++ b/integration-tests/tests/pg.test.ts @@ -4,6 +4,7 @@ import type { TestFn } from 'ava'; import anyTest from 'ava'; import Docker from 'dockerode'; import { + TransactionRollbackError, and, arrayContained, arrayContains, @@ -18,18 +19,19 @@ import { getTableColumns, gt, gte, + ilike, inArray, lt, max, min, name, + or, placeholder, - type SQL, sql, - type SQLWrapper, sum, sumDistinct, - TransactionRollbackError, + type SQL, + type SQLWrapper, } from 'drizzle-orm'; import { drizzle, type NodePgDatabase } from 'drizzle-orm/node-postgres'; import { migrate } from 'drizzle-orm/node-postgres/migrator'; @@ -54,11 +56,11 @@ import { macaddr, macaddr8, numeric, - type PgColumn, pgEnum, pgMaterializedView, pgTable, pgTableCreator, + uuid as pgUuid, pgView, primaryKey, serial, @@ -69,13 +71,13 @@ import { unionAll, unique, uniqueKeyName, - uuid as pgUuid, varchar, + type PgColumn, } from 'drizzle-orm/pg-core'; import getPort from 'get-port'; import pg from 'pg'; import { v4 as uuid } from 'uuid'; -import { type Equal, Expect, randomString } from './utils.ts'; +import { Expect, randomString, type Equal } from './utils.ts'; const { Client } = pg; @@ -4133,6 +4135,7 @@ test.serial('test if method with sql operators', async (t) => { id: serial('id').primaryKey(), name: text('name').notNull(), age: integer('age').notNull(), + city: text('city').notNull(), }); await db.execute(sql`drop table if exists ${users}`); @@ -4141,32 +4144,183 @@ test.serial('test if method with sql operators', async (t) => { create table ${users} ( id serial primary key, name text not null, - age integer not null + age integer not null, + city text not null ) `); await db.insert(users).values([ - { id: 1, name: 'John', age: 20 }, - { id: 2, name: 'Alice', age: 21 }, - { id: 3, name: 'Nick', age: 22 }, - { id: 4, name: 'Lina', age: 23 }, + { id: 1, name: 'John', age: 20, city: 'New York' }, + { id: 2, name: 'Alice', age: 21, city: 'New York' }, + { id: 3, name: 'Nick', age: 22, city: 'London' }, + { id: 4, name: 'Lina', age: 23, city: 'London' }, ]); const condition1 = true; const [result1] = await db.select().from(users).where(eq(users.id, 1).if(condition1)); - t.deepEqual(result1, { id: 1, name: 'John', age: 20 }); + t.deepEqual(result1, { id: 1, name: 'John', age: 20, city: 'New York' }); - const condition2 = false; + const condition2 = 1; - const result2 = await db.select().from(users).where(eq(users.id, 1).if(condition2)); + const [result2] = await db.select().from(users).where(sql`${users.id} = 1`.if(condition2)); - t.deepEqual(result2, [ - { id: 1, name: 'John', age: 20 }, - { id: 2, name: 'Alice', age: 21 }, - { id: 3, name: 'Nick', age: 22 }, - { id: 4, name: 'Lina', age: 23 }, + t.deepEqual(result2, { id: 1, name: 'John', age: 20, city: 'New York' }); + + const condition3 = 'non-empty string'; + + const result3 = await db.select().from(users).where( + or(eq(users.id, 1).if(condition3), eq(users.id, 2).if(condition3)), + ); + + t.deepEqual(result3, [{ id: 1, name: 'John', age: 20, city: 'New York' }, { + id: 2, + name: 'Alice', + age: 21, + city: 'New York', + }]); + + const condtition4 = false; + + const result4 = await db.select().from(users).where(eq(users.id, 1).if(condtition4)); + + t.deepEqual(result4, [ + { id: 1, name: 'John', age: 20, city: 'New York' }, + { id: 2, name: 'Alice', age: 21, city: 'New York' }, + { id: 3, name: 'Nick', age: 22, city: 'London' }, + { id: 4, name: 'Lina', age: 23, city: 'London' }, + ]); + + const condition5 = undefined; + + const result5 = await db.select().from(users).where(sql`${users.id} = 1`.if(condition5)); + + t.deepEqual(result5, [ + { id: 1, name: 'John', age: 20, city: 'New York' }, + { id: 2, name: 'Alice', age: 21, city: 'New York' }, + { id: 3, name: 'Nick', age: 22, city: 'London' }, + { id: 4, name: 'Lina', age: 23, city: 'London' }, + ]); + + const condition6 = null; + + const result6 = await db.select().from(users).where( + or(eq(users.id, 1).if(condition6), eq(users.id, 2).if(condition6)), + ); + + t.deepEqual(result6, [ + { id: 1, name: 'John', age: 20, city: 'New York' }, + { id: 2, name: 'Alice', age: 21, city: 'New York' }, + { id: 3, name: 'Nick', age: 22, city: 'London' }, + { id: 4, name: 'Lina', age: 23, city: 'London' }, + ]); + + const condition7 = { + term1: 0, + term2: 1, + }; + + const result7 = await db.select().from(users).where( + and(gt(users.age, 20).if(condition7.term1), eq(users.city, 'New York').if(condition7.term2)), + ); + + t.deepEqual(result7, [ + { id: 1, name: 'John', age: 20, city: 'New York' }, + { id: 2, name: 'Alice', age: 21, city: 'New York' }, + ]); + + const condition8 = { + term1: '', + term2: 'non-empty string', + }; + + const result8 = await db.select().from(users).where( + or(lt(users.age, 21).if(condition8.term1), eq(users.city, 'London').if(condition8.term2)), + ); + + t.deepEqual(result8, [ + { id: 3, name: 'Nick', age: 22, city: 'London' }, + { id: 4, name: 'Lina', age: 23, city: 'London' }, + ]); + + const condition9 = { + term1: 1, + term2: true, + }; + + const result9 = await db.select().from(users).where( + and(inArray(users.city, ['New York', 'London']).if(condition9.term1), ilike(users.name, 'a%').if(condition9.term2)), + ); + + t.deepEqual(result9, [ + { id: 2, name: 'Alice', age: 21, city: 'New York' }, + ]); + + const condition10 = { + term1: 4, + term2: 19, + }; + + const result10 = await db.select().from(users).where( + and( + sql`length(${users.name}) <= ${condition10.term1}`.if(condition10.term1), + gt(users.age, condition10.term2).if(condition10.term2 > 20), + ), + ); + + t.deepEqual(result10, [ + { id: 1, name: 'John', age: 20, city: 'New York' }, + { id: 3, name: 'Nick', age: 22, city: 'London' }, + { id: 4, name: 'Lina', age: 23, city: 'London' }, + ]); + + const condition11 = true; + + const result11 = await db.select().from(users).where( + or(eq(users.city, 'New York'), gte(users.age, 22))!.if(condition11), + ); + + t.deepEqual(result11, [ + { id: 1, name: 'John', age: 20, city: 'New York' }, + { id: 2, name: 'Alice', age: 21, city: 'New York' }, + { id: 3, name: 'Nick', age: 22, city: 'London' }, + { id: 4, name: 'Lina', age: 23, city: 'London' }, + ]); + + const condition12 = false; + + const result12 = await db.select().from(users).where( + and(eq(users.city, 'London'), gte(users.age, 23))!.if(condition12), + ); + + t.deepEqual(result12, [ + { id: 1, name: 'John', age: 20, city: 'New York' }, + { id: 2, name: 'Alice', age: 21, city: 'New York' }, + { id: 3, name: 'Nick', age: 22, city: 'London' }, + { id: 4, name: 'Lina', age: 23, city: 'London' }, + ]); + + const condition13 = true; + + const result13 = await db.select().from(users).where(sql`(city = 'New York' or age >= 22)`.if(condition13)); + + t.deepEqual(result13, [ + { id: 1, name: 'John', age: 20, city: 'New York' }, + { id: 2, name: 'Alice', age: 21, city: 'New York' }, + { id: 3, name: 'Nick', age: 22, city: 'London' }, + { id: 4, name: 'Lina', age: 23, city: 'London' }, + ]); + + const condition14 = false; + + const result14 = await db.select().from(users).where(sql`(city = 'London' and age >= 23)`.if(condition14)); + + t.deepEqual(result14, [ + { id: 1, name: 'John', age: 20, city: 'New York' }, + { id: 2, name: 'Alice', age: 21, city: 'New York' }, + { id: 3, name: 'Nick', age: 22, city: 'London' }, + { id: 4, name: 'Lina', age: 23, city: 'London' }, ]); await db.execute(sql`drop table ${users}`); From 8933293d6b23fffda3da5dacaf9c6218b5a6bdb7 Mon Sep 17 00:00:00 2001 From: realmikesolo Date: Wed, 1 May 2024 14:52:42 +0200 Subject: [PATCH 5/5] fix: format errors --- integration-tests/tests/pg.test.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/integration-tests/tests/pg.test.ts b/integration-tests/tests/pg.test.ts index af2febed2..660819050 100644 --- a/integration-tests/tests/pg.test.ts +++ b/integration-tests/tests/pg.test.ts @@ -4,7 +4,6 @@ import type { TestFn } from 'ava'; import anyTest from 'ava'; import Docker from 'dockerode'; import { - TransactionRollbackError, and, arrayContained, arrayContains, @@ -27,11 +26,12 @@ import { name, or, placeholder, + type SQL, sql, + type SQLWrapper, sum, sumDistinct, - type SQL, - type SQLWrapper, + TransactionRollbackError, } from 'drizzle-orm'; import { drizzle, type NodePgDatabase } from 'drizzle-orm/node-postgres'; import { migrate } from 'drizzle-orm/node-postgres/migrator'; @@ -56,11 +56,11 @@ import { macaddr, macaddr8, numeric, + type PgColumn, pgEnum, pgMaterializedView, pgTable, pgTableCreator, - uuid as pgUuid, pgView, primaryKey, serial, @@ -71,13 +71,13 @@ import { unionAll, unique, uniqueKeyName, + uuid as pgUuid, varchar, - type PgColumn, } from 'drizzle-orm/pg-core'; import getPort from 'get-port'; import pg from 'pg'; import { v4 as uuid } from 'uuid'; -import { Expect, randomString, type Equal } from './utils.ts'; +import { type Equal, Expect, randomString } from './utils.ts'; const { Client } = pg;