Skip to content

Commit

Permalink
#48 Add support for CASE expression (#122)
Browse files Browse the repository at this point in the history
  • Loading branch information
DrewImm authored Feb 11, 2024
1 parent a4feef5 commit 10f4244
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 1 deletion.
24 changes: 24 additions & 0 deletions src/dml/case-expression.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Expression } from '../expression';

export interface CaseCondition {
when: Expression;
then: Expression;
}

export interface CaseExpressionInterface {
value?: Expression;
case: CaseCondition[];
else?: Expression;
}

export class CaseExpression implements CaseExpressionInterface {
value?: Expression;
case: CaseCondition[];
else?: Expression;

public constructor(expr: CaseExpressionInterface) {
this.value = expr.value;
this.case = expr.case;
this.else = expr.else;
}
}
1 change: 1 addition & 0 deletions src/dml/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export { DatabaseQueryBuilder } from './query-builder';
export { QueryRepository, QueryRepositoryOptions } from './query-repository';

export * from './case-expression';
export * from './delete';
export * from './insert';
export * from './join';
Expand Down
31 changes: 31 additions & 0 deletions src/dml/query-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
} from '../functions/function-token';
import { Subquery } from './subquery';
import { KeyValExpression } from '../expression/key-val-expression';
import { CaseExpression } from './case-expression';

export class DatabaseQueryBuilder extends StatementBuilder {
// ------------------------------------------------------------------------
Expand Down Expand Up @@ -81,6 +82,9 @@ export class DatabaseQueryBuilder extends StatementBuilder {
else if (expr instanceof Subquery) {
this.subquery(expr);
}
else if (expr instanceof CaseExpression) {
this.caseExpression(expr);
}
else {
this.keyValueExpression(expr as KeyValExpression);
}
Expand All @@ -97,6 +101,33 @@ export class DatabaseQueryBuilder extends StatementBuilder {
this.sql.trimEnd(' ');
}

public caseExpression(expr: CaseExpression) {
this.sql.openParens();
this.sql.append('CASE ');

if (expr.value) {
this.expression(expr.value);
this.sql.space();
}

for (const condition of expr.case) {
this.sql.append('WHEN ');
this.expression(condition.when);
this.sql.append('THEN ');
this.expression(condition.then);
}

if (expr.else) {
this.sql.append('ELSE ');
this.expression(expr.else);
}

this.sql.append('END');

this.sql.closeParens();
this.sql.trimEnd(' ');
}

public rawExpression(expr: RawExpressionToken) {
this.sql.append(expr.sql);

Expand Down
2 changes: 2 additions & 0 deletions src/expression/simple-expression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Literal } from './literal';
import { DatabaseFunctionToken } from '../functions';
import { MathToken } from './math';
import { RawExpressionToken } from './raw';
import { CaseExpression } from '../dml/case-expression';

export type SimpleExpression =
| Literal
Expand All @@ -12,4 +13,5 @@ export type SimpleExpression =
| MathToken
| DatabaseFunctionToken
| Subquery
| CaseExpression
| SimpleExpression[];
51 changes: 50 additions & 1 deletion test/spec/dml/query-builder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
raw,
times,
} from '../../../src/expression';
import { Subquery } from '../../../src/dml';
import { CaseExpression, Subquery } from '../../../src/dml';

describe('Query Builder', () => {
describe('Select', () => {
Expand Down Expand Up @@ -185,6 +185,55 @@ describe('Query Builder', () => {
);
});

it('can select case expression', () => {
const { sql, params } = new DatabaseQueryBuilder()
.select({
columns: [
{
query: new CaseExpression({
case: [
{ when: [4, gt(5)], then: 'four' },
{ when: [5, gt(4)], then: 'five' },
],
else: 'hmm',
}),
as: 'val',
},
],
})
.toDatabaseQuery();

expect(sql).toEqual(
'SELECT (CASE WHEN (? > ?) THEN ? WHEN (? > ?) THEN ? ELSE ? END) AS "val"'
);
expect(params).toEqual([4, 5, 'four', 5, 4, 'five', 'hmm']);
});

it('can select case expression with value', () => {
const { sql, params } = new DatabaseQueryBuilder()
.select({
columns: [
{
query: new CaseExpression({
value: 5,
case: [
{ when: 4, then: 'four' },
{ when: 5, then: 'five' },
],
else: 'hmm',
}),
as: 'val',
},
],
})
.toDatabaseQuery();

expect(sql).toEqual(
'SELECT (CASE ? WHEN ? THEN ? WHEN ? THEN ? ELSE ? END) AS "val"'
);
expect(params).toEqual([5, 4, 'four', 5, 'five', 'hmm']);
});

it('can left join', () => {
const { sql } = new DatabaseQueryBuilder()
.select({
Expand Down

0 comments on commit 10f4244

Please sign in to comment.