| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 | /* * Copyright (c) 2015-present, Vitaly Tomilov * * See the LICENSE file at the top-level directory of this distribution * for licensing information. * * Removal or modification of this copyright notice is prohibited. */const {TableName} = require('../table-name');const {ColumnSet} = require('../column-set');const npm = {    formatting: require('../../formatting'),    utils: require('../../utils')};/** * @method helpers.insert * @description * Generates an `INSERT` query for either one object or an array of objects. * * @param {object|object[]} data * An insert object with properties for insert values, or an array of such objects. * * When `data` is not a non-null object and not an array, it will throw {@link external:TypeError TypeError} = `Invalid parameter 'data' specified.` * * When `data` is an empty array, it will throw {@link external:TypeError TypeError} = `Cannot generate an INSERT from an empty array.` * * When `data` is an array that contains a non-object value, the method will throw {@link external:Error Error} = * `Invalid insert object at index N.` * * @param {array|helpers.Column|helpers.ColumnSet} [columns] * Set of columns to be inserted. * * It is optional when `data` is a single object, and required when `data` is an array of objects. If not specified for an array * of objects, the method will throw {@link external:TypeError TypeError} = `Parameter 'columns' is required when inserting multiple records.` * * When `columns` is not a {@link helpers.ColumnSet ColumnSet} object, a temporary {@link helpers.ColumnSet ColumnSet} * is created - from the value of `columns` (if it was specified), or from the value of `data` (if it is not an array). * * When the final {@link helpers.ColumnSet ColumnSet} is empty (no columns in it), the method will throw * {@link external:Error Error} = `Cannot generate an INSERT without any columns.` * * @param {helpers.TableName|string|{table,schema}} [table] * Destination table. * * It is normally a required parameter. But when `columns` is passed in as a {@link helpers.ColumnSet ColumnSet} object * with `table` set in it, that will be used when this parameter isn't specified. When neither is available, the method * will throw {@link external:Error Error} = `Table name is unknown.` * * @returns {string} * An `INSERT` query string. * * @see *  {@link helpers.Column Column}, *  {@link helpers.ColumnSet ColumnSet}, *  {@link helpers.TableName TableName} * * @example * * const pgp = require('pg-promise')({ *    capSQL: true // if you want all generated SQL capitalized * }); * * const dataSingle = {val: 123, msg: 'hello'}; * const dataMulti = [{val: 123, msg: 'hello'}, {val: 456, msg: 'world!'}]; * * // Column details can be taken from the data object: * * pgp.helpers.insert(dataSingle, null, 'my-table'); * //=> INSERT INTO "my-table"("val","msg") VALUES(123,'hello') * * @example * * // Column details are required for a multi-row `INSERT`: * * pgp.helpers.insert(dataMulti, ['val', 'msg'], 'my-table'); * //=> INSERT INTO "my-table"("val","msg") VALUES(123,'hello'),(456,'world!') * * @example * * // Column details from a reusable ColumnSet (recommended for performance): * * const cs = new pgp.helpers.ColumnSet(['val', 'msg'], {table: 'my-table'}); * * pgp.helpers.insert(dataMulti, cs); * //=> INSERT INTO "my-table"("val","msg") VALUES(123,'hello'),(456,'world!') * */function insert(data, columns, table, capSQL) {    if (!data || typeof data !== 'object') {        throw new TypeError('Invalid parameter \'data\' specified.');    }    const isArray = Array.isArray(data);    if (isArray && !data.length) {        throw new TypeError('Cannot generate an INSERT from an empty array.');    }    if (columns instanceof ColumnSet) {        if (npm.utils.isNull(table)) {            table = columns.table;        }    } else {        if (isArray && npm.utils.isNull(columns)) {            throw new TypeError('Parameter \'columns\' is required when inserting multiple records.');        }        columns = new ColumnSet(columns || data);    }    if (!columns.columns.length) {        throw new Error('Cannot generate an INSERT without any columns.');    }    if (!table) {        throw new Error('Table name is unknown.');    }    if (!(table instanceof TableName)) {        table = new TableName(table);    }    let query = capSQL ? sql.capCase : sql.lowCase;    const fmOptions = {capSQL};    const format = npm.formatting.as.format;    query = format(query, [table.name, columns.names], fmOptions);    if (isArray) {        return query + data.map((d, index) => {            if (!d || typeof d !== 'object') {                throw new Error(`Invalid insert object at index ${index}.`);            }            return '(' + format(columns.variables, columns.prepare(d), fmOptions) + ')';        }).join();    }    return query + '(' + format(columns.variables, columns.prepare(data), fmOptions) + ')';}const sql = {    lowCase: 'insert into $1^($2^) values',    capCase: 'INSERT INTO $1^($2^) VALUES'};module.exports = {insert};
 |