You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
119 lines
3.7 KiB
119 lines
3.7 KiB
import ConnectionMutable from './ConnectionMutable.ts'
|
|
import {EscapedValue, FieldValueObject, QuerySource} from '../types.ts'
|
|
import {MalformedSQLGrammarError} from './Select.ts'
|
|
import {TableRefBuilder} from './TableRefBuilder.ts'
|
|
import {applyMixins} from '../../../../lib/src/support/mixins.ts'
|
|
import {escape, FieldSet} from '../types.ts'
|
|
import {raw} from '../Builder.ts'
|
|
|
|
// TODO support DEFAULT VALUES
|
|
// TODO support ON CONFLICT
|
|
export class Insert extends ConnectionMutable {
|
|
protected _target?: QuerySource = undefined
|
|
protected _columns: string[] = []
|
|
protected _rows: string[] = []
|
|
protected _fields: string[] = []
|
|
protected _return_all = false
|
|
|
|
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.')
|
|
|
|
if ( this._rows.length < 1 )
|
|
throw new MalformedSQLGrammarError('There are no rows to insert.')
|
|
|
|
const table_ref = this.source_alias_to_table_ref(this._target)
|
|
const returning = this._return_all ? this._columns.join(', ') : this._fields.join(', ')
|
|
const fields = escape(this._columns.map(x => raw(x)))
|
|
|
|
return [
|
|
`INSERT INTO ${this.serialize_table_ref(table_ref)}`,
|
|
` ${fields}`,
|
|
'VALUES',
|
|
` ${this._rows.join(',\n ')}`,
|
|
...(returning.trim() ? [`RETURNING ${returning}`] : [])
|
|
].filter(x => String(x).trim()).join(`\n${indent}`)
|
|
}
|
|
|
|
into(source: QuerySource, alias?: string) {
|
|
if ( !alias ) this._target = source
|
|
else this._target = { ref: source, alias }
|
|
return this
|
|
}
|
|
|
|
columns(...columns: string[]) {
|
|
this._columns = columns
|
|
return this
|
|
}
|
|
|
|
row_raw(...row: EscapedValue[]) {
|
|
if ( row.length !== this._columns.length )
|
|
throw new MalformedSQLGrammarError(`Cannot insert row with ${row.length} values using a query that has ${this._columns.length} columns specified.`)
|
|
|
|
this._rows.push(escape(row))
|
|
return this
|
|
}
|
|
|
|
row(row: FieldValueObject) {
|
|
const columns = []
|
|
const row_raw = []
|
|
|
|
for ( const field in row ) {
|
|
if ( !row.hasOwnProperty(field) ) continue
|
|
columns.push(field)
|
|
row_raw.push(row[field])
|
|
}
|
|
|
|
this.columns(...columns)
|
|
this.row_raw(...row_raw)
|
|
return this
|
|
}
|
|
|
|
rows(rows: FieldValueObject[]) {
|
|
const [initial, ...rest] = rows
|
|
|
|
const columns = []
|
|
const initial_raw = []
|
|
|
|
for ( const field in initial ) {
|
|
if ( !initial.hasOwnProperty(field) ) continue
|
|
columns.push(field)
|
|
initial_raw.push(initial[field])
|
|
}
|
|
|
|
this.columns(...columns)
|
|
this.row_raw(...initial_raw)
|
|
|
|
for ( const row of rest ) {
|
|
const values = []
|
|
for ( const col of columns ) {
|
|
values.push(row[col])
|
|
}
|
|
this.row_raw(...values)
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
}
|
|
|
|
this._return_all = this._fields.length === 0
|
|
return this
|
|
}
|
|
}
|
|
|
|
export interface Insert extends TableRefBuilder {}
|
|
applyMixins(Insert, [TableRefBuilder])
|