import {EscapedValue, isWhereClause, isWhereGroup, WhereStatement} from '../types.ts' import {escape, SQLWhereOperator, WherePreOperator} from '../types.ts' import {WhereBuilderFunction} from "./Select.ts"; export class WhereBuilder { protected _wheres: WhereStatement[] = [] get where_items() { return this._wheres } wheres_to_sql(wheres?: WhereStatement[], level = 0): string { const indent = Array(level * 2).fill(' ').join('') let statements = [] for ( const where of wheres || this._wheres ) { if ( isWhereClause(where) ) { statements.push(`${indent}${statements.length < 1 ? '' : where.preop + ' '}${where.field} ${where.operator} ${where.operand}`) } else if ( isWhereGroup(where) ) { statements.push(`${indent}${statements.length < 1 ? '' : where.preop + ' '}(\n${this.wheres_to_sql(where.items, level + 1)}\n${indent})`) } } return statements.filter(Boolean).join('\n') } private _createWhere(preop: WherePreOperator, field: string | WhereBuilderFunction, operator?: SQLWhereOperator, operand?: any) { if ( typeof field === 'function' ) { const where_builder = new WhereBuilder() field(where_builder) this._wheres.push({ preop, items: where_builder.where_items, }) } else if ( field && operator && typeof operand !== 'undefined' ) { this._wheres.push({ field, operator, operand: escape(operand), preop }) } } where(field: string | WhereBuilderFunction, operator?: SQLWhereOperator, operand?: any) { this._createWhere('AND', field, operator, operand) return this } whereIn(field: string, values: EscapedValue) { this._wheres.push({ field, operator: 'IN', operand: escape(values), preop: 'AND', }) return this } whereNot(field: string | WhereBuilderFunction, operator?: SQLWhereOperator, operand?: EscapedValue) { this._createWhere('AND NOT', field, operator, operand) return this } whereNotIn(field: string, values: EscapedValue) { this._wheres.push({ field, operator: 'NOT IN', operand: escape(values), preop: 'AND' }) return this } orWhere(field: string | WhereBuilderFunction, operator?: SQLWhereOperator, operand?: EscapedValue) { this._createWhere('OR', field, operator, operand) return this } orWhereNot(field: string | WhereBuilderFunction, operator?: SQLWhereOperator, operand?: EscapedValue) { this._createWhere('OR NOT', field, operator, operand) return this } orWhereIn(field: string, values: EscapedValue) { this._wheres.push({ field, operator: 'IN', operand: escape(values), preop: 'OR', }) return this } orWhereNotIn(field: string, values: EscapedValue) { this._wheres.push({ field, operator: 'NOT IN', operand: escape(values), preop: 'OR', }) return this } }