@contember/database
Advanced tools
import { QueryBuilder } from './QueryBuilder'; | ||
import { Literal } from '../Literal'; | ||
import { Value } from '../types'; | ||
import { ConditionCallback } from './ConditionBuilder'; | ||
import { ConditionExpression } from './ConditionBuilder'; | ||
import { WindowFunction } from './WindowFunction'; | ||
@@ -11,3 +11,3 @@ import { CaseStatement } from './CaseStatement'; | ||
selectValue(value: Value, type?: string): Literal; | ||
selectCondition(condition: ConditionCallback): Literal | undefined; | ||
selectCondition(condition: ConditionExpression): Literal | undefined; | ||
raw(sql: string, ...bindings: Value[]): Literal; | ||
@@ -14,0 +14,0 @@ window(callback: (windowFunction: WindowFunction<false>) => WindowFunction<true>): Literal; |
@@ -19,3 +19,3 @@ "use strict"; | ||
selectCondition(condition) { | ||
const builder = ConditionBuilder_1.ConditionBuilder.invoke(condition); | ||
const builder = ConditionBuilder_1.ConditionBuilder.process(condition); | ||
return builder.getSql() || undefined; | ||
@@ -22,0 +22,0 @@ } |
@@ -5,3 +5,5 @@ import { Value } from '../types'; | ||
import { SelectBuilder } from './SelectBuilder'; | ||
import { SubQueryExpression } from './internal/Subqueries'; | ||
export declare type ConditionCallback = (builder: ConditionBuilder) => ConditionBuilder; | ||
export declare type ConditionExpression = ConditionBuilder | ConditionCallback; | ||
export declare enum Operator { | ||
@@ -25,19 +27,21 @@ 'notEq' = "!=", | ||
static create(): ConditionBuilder; | ||
static invoke(cb: ConditionCallback): ConditionBuilder; | ||
and(callback: ConditionCallback): ConditionBuilder; | ||
or(callback: ConditionCallback): ConditionBuilder; | ||
not(callback: ConditionCallback): ConditionBuilder; | ||
private invokeCallback; | ||
static process(condition: ConditionExpression): ConditionBuilder; | ||
static not(condition: ConditionExpression): ConditionBuilder; | ||
and(condition: ConditionExpression): ConditionBuilder; | ||
or(condition: ConditionExpression): ConditionBuilder; | ||
not(condition: ConditionExpression): ConditionBuilder; | ||
compare(columnName: QueryBuilder.ColumnIdentifier, operator: Operator, value: Value): ConditionBuilder; | ||
columnsEq(columnName1: QueryBuilder.ColumnIdentifier, columnName2: QueryBuilder.ColumnIdentifier): ConditionBuilder; | ||
compareColumns(columnName1: QueryBuilder.ColumnIdentifier, operator: Operator, columnName2: QueryBuilder.ColumnIdentifier): ConditionBuilder; | ||
private createOperatorSql; | ||
in(columnName: QueryBuilder.ColumnIdentifier, values: Value[] | SelectBuilder<SelectBuilder.Result>): ConditionBuilder; | ||
null(columnName: QueryBuilder.ColumnIdentifier): ConditionBuilder; | ||
exists(subQuery: SubQueryExpression<SelectBuilder>): ConditionBuilder; | ||
isNull(columnName: QueryBuilder.ColumnIdentifier): ConditionBuilder; | ||
raw(sql: string, ...bindings: Value[]): ConditionBuilder; | ||
with(expression?: Literal | null | undefined): ConditionBuilder; | ||
getSql(): Literal | null; | ||
isEmpty(): boolean; | ||
private processConditionExpression; | ||
private static createOperatorSql; | ||
private static createLiteral; | ||
isEmpty(): boolean; | ||
} | ||
//# sourceMappingURL=ConditionBuilder.d.ts.map |
@@ -7,2 +7,3 @@ "use strict"; | ||
const Compiler_1 = require("./Compiler"); | ||
const Subqueries_1 = require("./internal/Subqueries"); | ||
var Operator; | ||
@@ -38,21 +39,16 @@ (function (Operator) { | ||
} | ||
static invoke(cb) { | ||
return cb(ConditionBuilder.create()); | ||
static process(condition) { | ||
return typeof condition === 'function' ? condition(ConditionBuilder.create()) : condition; | ||
} | ||
and(callback) { | ||
return this.invokeCallback(callback, ['and', false]); | ||
static not(condition) { | ||
return ConditionBuilder.create().not(condition); | ||
} | ||
or(callback) { | ||
return this.invokeCallback(callback, ['or', false]); | ||
and(condition) { | ||
return this.processConditionExpression(ConditionBuilder.process(condition), ['and', false]); | ||
} | ||
not(callback) { | ||
return this.invokeCallback(callback, ['and', true]); | ||
or(condition) { | ||
return this.processConditionExpression(ConditionBuilder.process(condition), ['or', false]); | ||
} | ||
invokeCallback(callback, parameters) { | ||
const builder = callback(ConditionBuilder.create()); | ||
const sql = ConditionBuilder.createLiteral(builder.expressions, ...parameters); | ||
if (sql) { | ||
return new ConditionBuilder([...this.expressions, sql]); | ||
} | ||
return this; | ||
not(condition) { | ||
return this.processConditionExpression(ConditionBuilder.process(condition), ['and', true]); | ||
} | ||
@@ -69,3 +65,3 @@ compare(columnName, operator, value) { | ||
} | ||
return this.with(new Literal_1.Literal(this.createOperatorSql(formatUtils_1.toFqnWrap(columnName), '?', operator), [value])); | ||
return this.with(new Literal_1.Literal(ConditionBuilder.createOperatorSql(formatUtils_1.toFqnWrap(columnName), '?', operator), [value])); | ||
} | ||
@@ -76,24 +72,4 @@ columnsEq(columnName1, columnName2) { | ||
compareColumns(columnName1, operator, columnName2) { | ||
return this.with(new Literal_1.Literal(this.createOperatorSql(formatUtils_1.toFqnWrap(columnName1), formatUtils_1.toFqnWrap(columnName2), operator))); | ||
return this.with(new Literal_1.Literal(ConditionBuilder.createOperatorSql(formatUtils_1.toFqnWrap(columnName1), formatUtils_1.toFqnWrap(columnName2), operator))); | ||
} | ||
createOperatorSql(left, right, operator) { | ||
if (!Object.values(Operator).includes(operator)) { | ||
throw new Error(`Operator ${operator} is not supported`); | ||
} | ||
switch (operator) { | ||
case Operator.contains: | ||
return `${left} LIKE '%' || ${right} || '%'`; | ||
case Operator.containsCI: | ||
return `${left} ILIKE '%' || ${right} || '%'`; | ||
case Operator.startsWith: | ||
return `${left} LIKE ${right} || '%'`; | ||
case Operator.startsWithCI: | ||
return `${left} ILIKE ${right} || '%'`; | ||
case Operator.endsWith: | ||
return `${left} LIKE '%' || ${right}`; | ||
case Operator.endsWithCI: | ||
return `${left} ILIKE '%' || ${right}`; | ||
} | ||
return `${left} ${operator} ${right}`; | ||
} | ||
in(columnName, values) { | ||
@@ -112,3 +88,13 @@ if (!Array.isArray(values)) { | ||
} | ||
null(columnName) { | ||
exists(subQuery) { | ||
const context = new Compiler_1.Compiler.Context(Compiler_1.Compiler.SCHEMA_PLACEHOLDER, new Set()); | ||
const query = Subqueries_1.createSubQueryLiteralFactory(subQuery)(context, subQuery => { | ||
if (subQuery.options.select.length === 0) { | ||
return subQuery.select(expr => expr.raw('?::int', 1)); | ||
} | ||
return subQuery; | ||
}); | ||
return this.with(new Literal_1.Literal(`exists (${query.sql})`, query.parameters)); | ||
} | ||
isNull(columnName) { | ||
return this.with(new Literal_1.Literal(`${formatUtils_1.toFqnWrap(columnName)} is null`)); | ||
@@ -128,2 +114,32 @@ } | ||
} | ||
isEmpty() { | ||
return this.expressions.length === 0; | ||
} | ||
processConditionExpression(builder, parameters) { | ||
const sql = ConditionBuilder.createLiteral(builder.expressions, ...parameters); | ||
if (sql) { | ||
return new ConditionBuilder([...this.expressions, sql]); | ||
} | ||
return this; | ||
} | ||
static createOperatorSql(left, right, operator) { | ||
if (!Object.values(Operator).includes(operator)) { | ||
throw new Error(`Operator ${operator} is not supported`); | ||
} | ||
switch (operator) { | ||
case Operator.contains: | ||
return `${left} LIKE '%' || ${right} || '%'`; | ||
case Operator.containsCI: | ||
return `${left} ILIKE '%' || ${right} || '%'`; | ||
case Operator.startsWith: | ||
return `${left} LIKE ${right} || '%'`; | ||
case Operator.startsWithCI: | ||
return `${left} ILIKE ${right} || '%'`; | ||
case Operator.endsWith: | ||
return `${left} LIKE '%' || ${right}`; | ||
case Operator.endsWithCI: | ||
return `${left} ILIKE '%' || ${right}`; | ||
} | ||
return `${left} ${operator} ${right}`; | ||
} | ||
static createLiteral(expressions, operator = 'and', not = false) { | ||
@@ -138,7 +154,4 @@ if (expressions.length === 0) { | ||
} | ||
isEmpty() { | ||
return this.expressions.length === 0; | ||
} | ||
} | ||
exports.ConditionBuilder = ConditionBuilder; | ||
//# sourceMappingURL=ConditionBuilder.js.map |
@@ -5,5 +5,5 @@ import { Compiler } from '../Compiler'; | ||
import { QueryBuilder } from '../QueryBuilder'; | ||
export declare type SubQueryLiteralFactory = (context: Compiler.Context) => Literal; | ||
export declare type SubQueryExpression = SelectBuilder.Callback | Literal | QueryBuilder; | ||
export declare function createSubQueryLiteralFactory(expr: SubQueryExpression): SubQueryLiteralFactory; | ||
export declare type SubQueryLiteralFactory<Builder extends QueryBuilder = QueryBuilder> = (context: Compiler.Context, preprocessor?: (query: SelectBuilder | Builder) => QueryBuilder) => Literal; | ||
export declare type SubQueryExpression<Builder extends QueryBuilder = QueryBuilder> = SelectBuilder.Callback | Literal | Builder; | ||
export declare function createSubQueryLiteralFactory<Builder extends QueryBuilder = QueryBuilder>(expr: SubQueryExpression<Builder>): SubQueryLiteralFactory<Builder>; | ||
//# sourceMappingURL=Subqueries.d.ts.map |
@@ -5,8 +5,9 @@ "use strict"; | ||
const SelectBuilder_1 = require("../SelectBuilder"); | ||
const noop = (value) => value; | ||
function createSubQueryLiteralFactory(expr) { | ||
if (typeof expr === 'function') { | ||
return ctx => expr(SelectBuilder_1.SelectBuilder.create()).createQuery(ctx); | ||
return (ctx, preprocessor) => (preprocessor !== null && preprocessor !== void 0 ? preprocessor : noop)(expr(SelectBuilder_1.SelectBuilder.create())).createQuery(ctx); | ||
} | ||
else if (((expr) => 'createQuery' in expr)(expr)) { | ||
return ctx => expr.createQuery(ctx); | ||
return (ctx, preprocessor) => ((preprocessor !== null && preprocessor !== void 0 ? preprocessor : noop)(expr)).createQuery(ctx); | ||
} | ||
@@ -13,0 +14,0 @@ else { |
import { Literal } from '../../Literal'; | ||
import { ConditionCallback } from '../ConditionBuilder'; | ||
import { ConditionBuilder, ConditionCallback } from '../ConditionBuilder'; | ||
import { Value } from '../../types'; | ||
@@ -23,5 +23,5 @@ declare namespace Where { | ||
}; | ||
type Expression = ValueWhere | ConditionCallback | Literal; | ||
type Expression = ValueWhere | ConditionCallback | ConditionBuilder | Literal; | ||
} | ||
export { Where }; | ||
//# sourceMappingURL=Where.d.ts.map |
@@ -14,11 +14,7 @@ "use strict"; | ||
withWhere(expression) { | ||
if (typeof expression !== 'function') { | ||
return new Statement([...this.values, expression]); | ||
if (typeof expression === 'function' || expression instanceof ConditionBuilder_1.ConditionBuilder) { | ||
const sql = ConditionBuilder_1.ConditionBuilder.process(expression).getSql(); | ||
return sql ? this.withWhere(sql) : this; | ||
} | ||
const builder = ConditionBuilder_1.ConditionBuilder.invoke(expression); | ||
const sql = builder.getSql(); | ||
if (!sql) { | ||
return this; | ||
} | ||
return new Statement([...this.values, sql]); | ||
return new Statement([...this.values, expression]); | ||
} | ||
@@ -25,0 +21,0 @@ compile() { |
@@ -7,3 +7,3 @@ import { With } from './internal/With'; | ||
import { Literal } from '../Literal'; | ||
import { ConditionCallback } from './ConditionBuilder'; | ||
import { ConditionExpression } from './ConditionBuilder'; | ||
import { LockType } from './LockType'; | ||
@@ -64,5 +64,5 @@ import { SubQueryExpression, SubQueryLiteralFactory } from './internal/Subqueries'; | ||
}>; | ||
type JoinCondition = ConditionCallback; | ||
type JoinCondition = ConditionExpression; | ||
} | ||
export { SelectBuilder }; | ||
//# sourceMappingURL=SelectBuilder.d.ts.map |
@@ -87,3 +87,3 @@ "use strict"; | ||
} | ||
const builder = ConditionBuilder_1.ConditionBuilder.invoke(joinCondition); | ||
const builder = ConditionBuilder_1.ConditionBuilder.process(joinCondition); | ||
return builder.getSql() || undefined; | ||
@@ -90,0 +90,0 @@ } |
@@ -40,3 +40,4 @@ "use strict"; | ||
.in('m', wrapper.selectBuilder().select(expr => expr.selectValue(1))) | ||
.null('n') | ||
.exists(it => it) | ||
.isNull('n') | ||
.raw('false')); | ||
@@ -50,4 +51,4 @@ await qb.getResult(wrapper); | ||
and "j" ilike '%' || ? || '%' and "k" ilike ? || '%' and "l" ilike '%' || ? | ||
and "z" = "foo"."x" and "o" in (?, ?, ?) and "m" in (select ?) and "n" is null and false`, | ||
parameters: [1, 2, 3, 4, 5, 6, 'foo\\\\\\%bar', 'lorem\\_ipsum', 'dolor\\%sit', 'X', 'Y', 'Z', 1, 2, 3, 1], | ||
and "z" = "foo"."x" and "o" in (?, ?, ?) and "m" in (select ?) and exists (select ?::int) and "n" is null and false`, | ||
parameters: [1, 2, 3, 4, 5, 6, 'foo\\\\\\%bar', 'lorem\\_ipsum', 'dolor\\%sit', 'X', 'Y', 'Z', 1, 2, 3, 1, 1], | ||
}); | ||
@@ -69,4 +70,4 @@ }); | ||
.in(['bar', 'c'], [1, 2, 3]) | ||
.null(['bar', 'd']) | ||
.not(clause => clause.null(['bar', 'd'])) | ||
.isNull(['bar', 'd']) | ||
.not(clause => clause.isNull(['bar', 'd'])) | ||
.compareColumns(['bar', 'e'], src_1.Operator.lte, ['bar', 'f']))); | ||
@@ -73,0 +74,0 @@ await qb.getResult(wrapper); |
{ | ||
"name": "@contember/database", | ||
"version": "0.12.0-alpha.10", | ||
"version": "0.12.0-alpha.11", | ||
"license": "Apache-2.0", | ||
@@ -11,6 +11,6 @@ "main": "dist/src/index.js", | ||
"dependencies": { | ||
"@contember/queryable": "^0.12.0-alpha.10" | ||
"@contember/queryable": "^0.12.0-alpha.11" | ||
}, | ||
"devDependencies": { | ||
"@contember/database-tester": "^0.12.0-alpha.10", | ||
"@contember/database-tester": "^0.12.0-alpha.11", | ||
"@types/node": "^15.12.5", | ||
@@ -17,0 +17,0 @@ "pg": "^8.5.0", |
import { QueryBuilder } from './QueryBuilder' | ||
import { Literal } from '../Literal' | ||
import { Value } from '../types' | ||
import { ConditionBuilder, ConditionCallback } from './ConditionBuilder' | ||
import { ConditionBuilder, ConditionCallback, ConditionExpression } from './ConditionBuilder' | ||
import { WindowFunction } from './WindowFunction' | ||
@@ -21,4 +21,4 @@ import { CaseStatement } from './CaseStatement' | ||
public selectCondition(condition: ConditionCallback): Literal | undefined { | ||
const builder = ConditionBuilder.invoke(condition) | ||
public selectCondition(condition: ConditionExpression): Literal | undefined { | ||
const builder = ConditionBuilder.process(condition) | ||
return builder.getSql() || undefined | ||
@@ -25,0 +25,0 @@ } |
@@ -7,4 +7,6 @@ import { Value } from '../types' | ||
import { Compiler } from './Compiler' | ||
import { createSubQueryLiteralFactory, SubQueryExpression } from './internal/Subqueries' | ||
export type ConditionCallback = (builder: ConditionBuilder) => ConditionBuilder | ||
export type ConditionExpression = ConditionBuilder | ConditionCallback | ||
@@ -48,25 +50,20 @@ interface Raw { | ||
public static invoke(cb: ConditionCallback): ConditionBuilder { | ||
return cb(ConditionBuilder.create()) | ||
public static process(condition: ConditionExpression): ConditionBuilder { | ||
return typeof condition === 'function' ? condition(ConditionBuilder.create()) : condition | ||
} | ||
and(callback: ConditionCallback): ConditionBuilder { | ||
return this.invokeCallback(callback, ['and', false]) | ||
public static not(condition: ConditionExpression): ConditionBuilder { | ||
return ConditionBuilder.create().not(condition) | ||
} | ||
or(callback: ConditionCallback): ConditionBuilder { | ||
return this.invokeCallback(callback, ['or', false]) | ||
and(condition: ConditionExpression): ConditionBuilder { | ||
return this.processConditionExpression(ConditionBuilder.process(condition), ['and', false]) | ||
} | ||
not(callback: ConditionCallback): ConditionBuilder { | ||
return this.invokeCallback(callback, ['and', true]) | ||
or(condition: ConditionExpression): ConditionBuilder { | ||
return this.processConditionExpression(ConditionBuilder.process(condition), ['or', false]) | ||
} | ||
private invokeCallback(callback: ConditionCallback, parameters: ['and' | 'or', boolean]): ConditionBuilder { | ||
const builder = callback(ConditionBuilder.create()) | ||
const sql = ConditionBuilder.createLiteral(builder.expressions, ...parameters) | ||
if (sql) { | ||
return new ConditionBuilder([...this.expressions, sql]) | ||
} | ||
return this | ||
not(condition: ConditionExpression): ConditionBuilder { | ||
return this.processConditionExpression(ConditionBuilder.process(condition), ['and', true]) | ||
} | ||
@@ -85,3 +82,3 @@ | ||
} | ||
return this.with(new Literal(this.createOperatorSql(toFqnWrap(columnName), '?', operator), [value])) | ||
return this.with(new Literal(ConditionBuilder.createOperatorSql(toFqnWrap(columnName), '?', operator), [value])) | ||
} | ||
@@ -93,35 +90,7 @@ | ||
compareColumns( | ||
columnName1: QueryBuilder.ColumnIdentifier, | ||
operator: Operator, | ||
columnName2: QueryBuilder.ColumnIdentifier, | ||
) { | ||
return this.with(new Literal(this.createOperatorSql(toFqnWrap(columnName1), toFqnWrap(columnName2), operator))) | ||
compareColumns(columnName1: QueryBuilder.ColumnIdentifier, operator: Operator, columnName2: QueryBuilder.ColumnIdentifier) { | ||
return this.with(new Literal(ConditionBuilder.createOperatorSql(toFqnWrap(columnName1), toFqnWrap(columnName2), operator))) | ||
} | ||
private createOperatorSql(left: string, right: string, operator: Operator): string { | ||
if (!Object.values(Operator).includes(operator)) { | ||
throw new Error(`Operator ${operator} is not supported`) | ||
} | ||
switch (operator) { | ||
case Operator.contains: | ||
return `${left} LIKE '%' || ${right} || '%'` | ||
case Operator.containsCI: | ||
return `${left} ILIKE '%' || ${right} || '%'` | ||
case Operator.startsWith: | ||
return `${left} LIKE ${right} || '%'` | ||
case Operator.startsWithCI: | ||
return `${left} ILIKE ${right} || '%'` | ||
case Operator.endsWith: | ||
return `${left} LIKE '%' || ${right}` | ||
case Operator.endsWithCI: | ||
return `${left} ILIKE '%' || ${right}` | ||
} | ||
return `${left} ${operator} ${right}` | ||
} | ||
in( | ||
columnName: QueryBuilder.ColumnIdentifier, | ||
values: Value[] | SelectBuilder<SelectBuilder.Result>, | ||
): ConditionBuilder { | ||
in(columnName: QueryBuilder.ColumnIdentifier, values: Value[] | SelectBuilder<SelectBuilder.Result>): ConditionBuilder { | ||
if (!Array.isArray(values)) { | ||
@@ -140,3 +109,14 @@ // todo: replace placeholder with some kind of callback | ||
null(columnName: QueryBuilder.ColumnIdentifier): ConditionBuilder { | ||
exists(subQuery: SubQueryExpression<SelectBuilder>): ConditionBuilder { | ||
const context = new Compiler.Context(Compiler.SCHEMA_PLACEHOLDER, new Set()) | ||
const query = createSubQueryLiteralFactory<SelectBuilder>(subQuery)(context, subQuery => { | ||
if (subQuery.options.select.length === 0) { | ||
return subQuery.select(expr => expr.raw('?::int', 1)) | ||
} | ||
return subQuery | ||
}) | ||
return this.with(new Literal(`exists (${query.sql})`, query.parameters)) | ||
} | ||
isNull(columnName: QueryBuilder.ColumnIdentifier): ConditionBuilder { | ||
return this.with(new Literal(`${toFqnWrap(columnName)} is null`)) | ||
@@ -160,7 +140,36 @@ } | ||
private static createLiteral( | ||
expressions: Literal[], | ||
operator: 'or' | 'and' = 'and', | ||
not: boolean = false, | ||
): Literal | null { | ||
isEmpty(): boolean { | ||
return this.expressions.length === 0 | ||
} | ||
private processConditionExpression(builder: ConditionBuilder, parameters: ['and' | 'or', boolean]): ConditionBuilder { | ||
const sql = ConditionBuilder.createLiteral(builder.expressions, ...parameters) | ||
if (sql) { | ||
return new ConditionBuilder([...this.expressions, sql]) | ||
} | ||
return this | ||
} | ||
private static createOperatorSql(left: string, right: string, operator: Operator): string { | ||
if (!Object.values(Operator).includes(operator)) { | ||
throw new Error(`Operator ${operator} is not supported`) | ||
} | ||
switch (operator) { | ||
case Operator.contains: | ||
return `${left} LIKE '%' || ${right} || '%'` | ||
case Operator.containsCI: | ||
return `${left} ILIKE '%' || ${right} || '%'` | ||
case Operator.startsWith: | ||
return `${left} LIKE ${right} || '%'` | ||
case Operator.startsWithCI: | ||
return `${left} ILIKE ${right} || '%'` | ||
case Operator.endsWith: | ||
return `${left} LIKE '%' || ${right}` | ||
case Operator.endsWithCI: | ||
return `${left} ILIKE '%' || ${right}` | ||
} | ||
return `${left} ${operator} ${right}` | ||
} | ||
private static createLiteral(expressions: Literal[], operator: 'or' | 'and' = 'and', not: boolean = false): Literal | null { | ||
if (expressions.length === 0) { | ||
@@ -176,6 +185,2 @@ return null | ||
} | ||
isEmpty(): boolean { | ||
return this.expressions.length === 0 | ||
} | ||
} |
@@ -6,10 +6,12 @@ import { Compiler } from '../Compiler' | ||
export type SubQueryLiteralFactory = (context: Compiler.Context) => Literal | ||
export type SubQueryExpression = SelectBuilder.Callback | Literal | QueryBuilder | ||
export type SubQueryLiteralFactory<Builder extends QueryBuilder = QueryBuilder> = (context: Compiler.Context, preprocessor?: (query: SelectBuilder | Builder) => QueryBuilder) => Literal | ||
export type SubQueryExpression<Builder extends QueryBuilder = QueryBuilder> = SelectBuilder.Callback | Literal | Builder | ||
export function createSubQueryLiteralFactory(expr: SubQueryExpression): SubQueryLiteralFactory { | ||
const noop = <T>(value: T): T => value | ||
export function createSubQueryLiteralFactory<Builder extends QueryBuilder = QueryBuilder>(expr: SubQueryExpression<Builder>): SubQueryLiteralFactory<Builder> { | ||
if (typeof expr === 'function') { | ||
return ctx => expr(SelectBuilder.create()).createQuery(ctx) | ||
return (ctx, preprocessor) => (preprocessor ?? noop)(expr(SelectBuilder.create())).createQuery(ctx) | ||
} else if (((expr: any): expr is QueryBuilder => 'createQuery' in expr)(expr)) { | ||
return ctx => expr.createQuery(ctx) | ||
return (ctx, preprocessor) => ((preprocessor ?? noop)(expr)).createQuery(ctx) | ||
} else { | ||
@@ -16,0 +18,0 @@ return () => expr |
@@ -15,11 +15,7 @@ import { wrapIdentifier } from '../../utils' | ||
public withWhere(expression: Expression): Statement { | ||
if (typeof expression !== 'function') { | ||
return new Statement([...this.values, expression]) | ||
if (typeof expression === 'function' || expression instanceof ConditionBuilder) { | ||
const sql = ConditionBuilder.process(expression).getSql() | ||
return sql ? this.withWhere(sql) : this | ||
} | ||
const builder = ConditionBuilder.invoke(expression) | ||
const sql = builder.getSql() | ||
if (!sql) { | ||
return this | ||
} | ||
return new Statement([...this.values, sql]) | ||
return new Statement([...this.values, expression]) | ||
} | ||
@@ -54,5 +50,5 @@ | ||
export type ValueWhere = { [columnName: string]: Value } | ||
export type Expression = ValueWhere | ConditionCallback | Literal | ||
export type Expression = ValueWhere | ConditionCallback | ConditionBuilder | Literal | ||
} | ||
export { Where } |
@@ -8,3 +8,3 @@ import { With } from './internal/With' | ||
import { Literal } from '../Literal' | ||
import { ConditionBuilder, ConditionCallback } from './ConditionBuilder' | ||
import { ConditionBuilder, ConditionCallback, ConditionExpression } from './ConditionBuilder' | ||
import { LockType } from './LockType' | ||
@@ -117,3 +117,3 @@ import { columnExpressionToLiteral, toFqnWrap } from './utils' | ||
} | ||
const builder = ConditionBuilder.invoke(joinCondition) | ||
const builder = ConditionBuilder.process(joinCondition) | ||
@@ -207,5 +207,5 @@ return builder.getSql() || undefined | ||
export type JoinCondition = ConditionCallback | ||
export type JoinCondition = ConditionExpression | ||
} | ||
export { SelectBuilder } |
@@ -47,7 +47,5 @@ import { Client, ConflictActionType, LimitByGroupWrapper, LockType, Operator } from '../../../src' | ||
.in('o', [1, 2, 3]) | ||
.in( | ||
'm', | ||
wrapper.selectBuilder().select(expr => expr.selectValue(1)), | ||
) | ||
.null('n') | ||
.in('m', wrapper.selectBuilder().select(expr => expr.selectValue(1))) | ||
.exists(it => it) | ||
.isNull('n') | ||
.raw('false'), | ||
@@ -63,4 +61,4 @@ ) | ||
and "j" ilike '%' || ? || '%' and "k" ilike ? || '%' and "l" ilike '%' || ? | ||
and "z" = "foo"."x" and "o" in (?, ?, ?) and "m" in (select ?) and "n" is null and false`, | ||
parameters: [1, 2, 3, 4, 5, 6, 'foo\\\\\\%bar', 'lorem\\_ipsum', 'dolor\\%sit', 'X', 'Y', 'Z', 1, 2, 3, 1], | ||
and "z" = "foo"."x" and "o" in (?, ?, ?) and "m" in (select ?) and exists (select ?::int) and "n" is null and false`, | ||
parameters: [1, 2, 3, 4, 5, 6, 'foo\\\\\\%bar', 'lorem\\_ipsum', 'dolor\\%sit', 'X', 'Y', 'Z', 1, 2, 3, 1, 1], | ||
}) | ||
@@ -87,4 +85,4 @@ }) | ||
.in(['bar', 'c'], [1, 2, 3]) | ||
.null(['bar', 'd']) | ||
.not(clause => clause.null(['bar', 'd'])) | ||
.isNull(['bar', 'd']) | ||
.not(clause => clause.isNull(['bar', 'd'])) | ||
.compareColumns(['bar', 'e'], Operator.lte, ['bar', 'f']), | ||
@@ -91,0 +89,0 @@ ), |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
384059
1.13%5295
0.25%