import { MapToExpression } from '../' import { AnyExpression, condition, Condition } from '../../expressions' import { QueryDefinition, Source } from '../../source' import { sql, Template } from '../../template' import { FieldsConfig, stringifyFields } from '../common/fields' import { FromConfig, stringifyFrom, stringifyTable } from '../common/from' import { stringifyWith, WithConfig } from '../common/with' type InferDeleteReturning = undefined extends T['returning'] ? {} : T['returning'] extends '*' ? T['from'] extends Source ? R : Exclude['table'] extends Source ? L : never : MapToExpression export function DELETE (config: T) { type Ret = InferDeleteReturning const ret = config.returning ? Object.keys(config.returning) : [] return new QueryDefinition<{ [K in keyof Ret]: Ret[K] extends AnyExpression ? Ret[K] : never }>(stringifyDelete(config), ret) } export interface DeleteConfig { with?: WithConfig from: Source | { only?: boolean, table: Source } using?: FromConfig where?: Condition whereCurrentOf?: string returning?: FieldsConfig | '*' } // [ ] // DELETE { FROM [ ONLY ] table [ * ] [ AS alias ] } // [ USING { [, ...] } ] // [ WHERE condition | WHERE CURRENT OF cursorName ] // [ RETURNING { expression [ AS alias ] [, ...] } ] export const stringifyDelete = (config: DeleteConfig): Template => { const WITH = config.with ? sql`WITH ${stringifyWith(config.with)} ` : sql`` const FROM = sql`FROM ${stringifyTable(config.from)}` const USING = config.using ? sql` USING ${stringifyFrom(config.using)}` : sql`` const WHERE = config.where ? sql` WHERE ${condition(config.where)}` : sql`` const CURSOR = config.whereCurrentOf ? sql` WHERE CURRENT OF ${sql.ident(config.whereCurrentOf)}` : sql`` const RETURNING = config.returning ? config.returning === '*' ? sql` RETURNING *` : sql` RETURNING ${stringifyFields(config.returning)}` : sql`` return sql`${WITH}DELETE ${FROM}${USING}${WHERE}${CURSOR}${RETURNING}` }