Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add if method to conditionally include part of the query #2233

Merged
merged 5 commits into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions drizzle-orm/src/sql/sql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,16 @@ export class SQL<T = unknown> 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 itself if the condition is `true`, otherwise `undefined`
*/
if(condition: any | undefined): this | undefined {
return condition ? this : undefined;
}
}

export type GetDecoderResult<T> = T extends Column ? T['_']['data'] : T extends
Expand Down
200 changes: 200 additions & 0 deletions integration-tests/tests/pg.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ import {
getTableColumns,
gt,
gte,
ilike,
inArray,
lt,
max,
min,
name,
or,
placeholder,
type SQL,
sql,
Expand Down Expand Up @@ -4125,3 +4127,201 @@ 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(),
city: text('city').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,
city text not null
)
`);

await db.insert(users).values([
{ 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, city: 'New York' });

const condition2 = 1;

const [result2] = await db.select().from(users).where(sql`${users.id} = 1`.if(condition2));

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}`);
});