import ConnectionExecutable from './ConnectionExecutable.ts' import {escape, EscapedValue, FieldValue, FieldValueObject, QuerySource, WhereStatement, FieldSet} from '../types.ts' import {Collection} from '../../../../lib/src/collection/Collection.ts' import {WhereBuilder} from './WhereBuilder.ts' import {applyMixins} from '../../../../lib/src/support/mixins.ts' import {TableRefBuilder} from './TableRefBuilder.ts' import {MalformedSQLGrammarError} from './Select.ts' import ConnectionMutable from './ConnectionMutable.ts' // TODO FROM // TODO WHERE CURRENT OF export class Update extends ConnectionMutable { protected _target?: QuerySource = undefined protected _only = false protected _sets: Collection = new Collection() protected _wheres: WhereStatement[] = [] protected _fields: string[] = [] sql(level = 0): string { const indent = Array(level * 2).fill(' ').join('') if ( typeof this._target === 'undefined' ) throw new MalformedSQLGrammarError('No table reference has been provided.') const table_ref = this.source_alias_to_table_ref(this._target) const wheres = this.wheres_to_sql(this._wheres, level + 1) const returning_fields = this._fields.join(', ') return [ `UPDATE ${this._only ? 'ONLY ' : ''}${this.serialize_table_ref(table_ref)}`, `SET`, this.serialize_sets(this._sets, level + 1), ...(wheres.trim() ? ['WHERE', wheres] : []), ...(returning_fields.trim() ? [`RETURNING ${returning_fields}`] : []), ].filter(x => String(x).trim()).join(`\n${indent}`) } protected serialize_sets(sets: Collection, level = 0): string { const indent = Array(level * 2).fill(' ').join('') return indent + sets.map(field_value => `${field_value.field} = ${escape(field_value.value)}`).join(`,\n${indent}`) } to(source: QuerySource, alias?: string) { if ( !alias ) this._target = source else this._target = { ref: source, alias } return this } only() { this._only = true return this } set(field: string, value: EscapedValue) { const existing = this._sets.firstWhere('field', '=', field) if ( existing ) { existing.value = value } else { this._sets.push({ field, value }) } return this } data(values: FieldValueObject) { for ( const field in values ) { if ( !values.hasOwnProperty(field) ) continue this.set(field, values[field]) } return this } returning(...fields: FieldSet[]) { for ( const field_set of fields ) { if ( typeof field_set === 'string' ) { if ( !this._fields.includes(field_set) ) this._fields.push(field_set) } else { for ( const field of field_set ) { if ( !this._fields.includes(field) ) this._fields.push(field) } } } return this } } export interface Update extends WhereBuilder, TableRefBuilder {} applyMixins(Update, [WhereBuilder, TableRefBuilder])