import { OperationNodeSource } from '../operation-node/operation-node-source.js' ; import { CompiledQuery } from '../query-compiler/compiled-query.js' ; import { parseSelectExpressionOrList , parseSelectAll , SelectExpression , SelectExpressionOrList , } from '../parser/select-parser.js' ; import { InsertObject , InsertObjectOrList , parseInsertObjectOrList , } from '../parser/insert-values-parser.js' ; import { InsertQueryNode } from '../operation-node/insert-query-node.js' ; import { QueryNode } from '../operation-node/query-node.js' ; import { SingleResultType } from '../util/type-utils.js' ; import { MutationObject , parseUpdateObject , } from '../parser/update-set-parser.js' ; import { preventAwait } from '../util/prevent-await.js' ; import { Compilable } from '../util/compilable.js' ; import { QueryExecutor } from '../query-executor/query-executor.js' ; import { QueryId } from '../util/query-id.js' ; import { freeze } from '../util/object-utils.js' ; import { ParseContext } from '../parser/parse-context.js' ; import { OnDuplicateKeyNode } from '../operation-node/on-duplicate-key-node.js' ; import { InsertResult } from './insert-result.js' ; import { KyselyPlugin } from '../plugin/kysely-plugin.js' ; import { ReturningRow } from '../parser/returning-parser.js' ; import { NoResultError , NoResultErrorConstructor } from './no-result-error.js' ; import { ComplexExpression , parseComplexExpression , } from '../parser/complex-expression-parser.js' ; import { ColumnNode } from '../operation-node/column-node.js' ; import { ReturningInterface } from './returning-interface.js' ; import { OnConflictBuilder , OnConflictDoNothingBuilder , OnConflictUpdateBuilder , } from './on-conflict-builder.js' ; import { OnConflictNode } from '../operation-node/on-conflict-node.js' ; import { Selectable } from '../util/column-type.js' ; export class InsertQueryBuilder < DB , TB extends keyof DB , O > implements ReturningInterface < DB , TB , O > , OperationNodeSource , Compilable { readonly #props : InsertQueryBuilderProps ; constructor ( props ) { this . #props = freeze ( props ) ; } /**
     * Sets the values to insert for an  Kysely . insertInto query.
     *
     * This method takes an object whose keys are column names and values are
     * values to insert. In addition to the column's type, the values can be
     *  Kysely . raw instances or select queries.
     *
     * You must provide all fields you haven't explicitly marked as nullable
     * or optional using  Generated or  ColumnType .
     *
     * The return value of an `insert` query is an instance of  InsertResult . The
     *  InsertResult . insertId field holds the auto incremented primary
     * key if the database returned one.
     *
     * On PostgreSQL and some other dialects, you need to call `returning` to get
     * something out of the query.
     *
     * Also see the  expression method for inserting the result of a select
     * query or any other expression.
     *
     * ### Examples
     *
     * Insert a row into `person`:
     * ```ts
     * const id = await db
     *   .insertInto('person')
     *   .values({
     *     first_name: 'Jennifer',
     *     last_name: 'Aniston'
     *   })
     *   .executeTakeFirstOrThrow()
     * ```
     *
     * The generated SQL (PostgreSQL):
     *
     * ```sql
     * insert into "person" ("first_name", "last_name") values ($1, $2)
     * ```
     *
     * On dialects that support it (for example PostgreSQL) you can insert multiple
     * rows by providing an array. Note that the return value is once again very
     * dialect-specific. Some databases may only return the id of the *last* inserted
     * row and some return nothing at all unless you call `returning`.
     *
     * ```ts
     * await db
     *   .insertInto('person')
     *   .values([{
     *     first_name: 'Jennifer',
     *     last_name: 'Aniston'
     *   }, {
     *     first_name: 'Arnold',
     *     last_name: 'Schwarzenegger',
     *   }])
     *   .execute()
     * ```
     *
     * The generated SQL (PostgreSQL):
     *
     * ```sql
     * insert into "person" ("first_name", "last_name") values (($1, $2), ($3, $4))
     * ```
     *
     * On PostgreSQL you need to chain `returning` to the query to get
     * the inserted row's columns (or any other expression) as the
     * return value:
     *
     * ```ts
     * const row = await db
     *   .insertInto('person')
     *   .values({
     *     first_name: 'Jennifer',
     *     last_name: 'Aniston'
     *   })
     *   .returning('id')
     *   .executeTakeFirstOrThrow()
     *
     * row.id
     * ```
     *
     * The generated SQL (PostgreSQL):
     *
     * ```sql
     * insert into "person" ("first_name", "last_name") values ($1, $2) returning "id"
     * ```
     *
     * In addition to primitives, the values can also be `raw` expressions or
     * select queries:
     *
     * ```ts
     * const result = await db
     *   .insertInto('person')
     *   .values({
     *     first_name: 'Jennifer',
     *     last_name: db.raw('? || ?', ['Ani', 'ston']),
     *     age: db.selectFrom('person').select(raw('avg(age)')),
     *   })
     *   .executeTakeFirst()
     *
     * console.log(result.insertId)
     * ```
     *
     * The generated SQL (PostgreSQL):
     *
     * ```sql
     * insert into "person" ("first_name", "last_name", "age")
     * values ($1, $2 || $3, (select avg(age) from "person"))
     * ```
     *
     * You can also use the callback version of subqueries or raw expressions:
     *
     * ```ts
     * db.with('jennifer', (db) => db
     *   .selectFrom('person')
     *   .where('first_name', '=', 'Jennifer')
     *   .select(['id', 'first_name', 'gender'])
     *   .limit(1)
     * ).insertInto('pet').values({
     *   owner_id: (eb) => eb.selectFrom('jennifer').select('id'),
     *   name: (eb) => eb.selectFrom('jennifer').select('first_name'),
     *   species: 'cat',
     * })
     * ```
      values ( row ) ; values ( row ) ; values ( args ) { const [ columns , values ] = parseInsertObjectOrList ( this . #props . parseContext , args ) ; return new InsertQueryBuilder ( { ... this . #props , queryNode : InsertQueryNode . cloneWith ( this . #props . queryNode , { columns , values , } ) , } ) ; } /**
     * Sets the columns to insert.
     *
     * The  values method sets both the columns and the values and this method
     * is not needed. But if you are using the  expression method, you can use
     * this method to set the columns to insert.
     *
     * ### Examples
     *
     * ```ts
     * db.insertInto('person')
     *   .columns(['first_name'])
     *   .expression((eb) => eb.selectFrom('pet').select('pet.name'))
     * ```
     *
     * The generated SQL (PostgreSQL):
     *
     * ```sql
     * insert into "person" ("first_name")
     * select "pet"."name" from "pet"
     * ```
      columns ( columns ) { return new InsertQueryBuilder ( { ... this . #props , queryNode : InsertQueryNode . cloneWith ( this . #props . queryNode , { columns : freeze ( columns . map ( ColumnNode . create ) ) , } ) , } ) ; } /**
     * Insert an arbitrary expression. For example the result of a select query.
     *
     * ### Examples
     *
     * ```ts
     * db.insertInto('person')
     *   .columns(['first_name'])
     *   .expression((eb) => eb.selectFrom('pet').select('pet.name'))
     * ```
     *
     * The generated SQL (PostgreSQL):
     *
     * ```sql
     * insert into "person" ("first_name")
     * select "pet"."name" from "pet"
     * ```
     */ expression ( expression ) { return new InsertQueryBuilder ( { ... this . #props , queryNode : InsertQueryNode . cloneWith ( this . #props . queryNode , { values : parseComplexExpression ( this . #props . parseContext , expression ) , } ) , } ) ; } /**
     * Changes an `insert into` query to an `insert ignore into` query.
     *
     * If you use the ignore modifier, ignorable errors that occur while executing the
     * insert statement are ignored. For example, without ignore, a row that duplicates
     * an existing unique index or primary key value in the table causes a duplicate-key
     * error and the statement is aborted. With ignore, the row is discarded and no error
     * occurs.
     *
     * This is only supported on some dialects like MySQL. On most dialects you should
     * use the  onConflict method.
     *
     * ### Examples
     *
     * ```ts
     * await db.insertInto('person')
     *   .ignore()
     *   .values(values)
     *   .execute()
     * ```
      ignore ( ) { return new InsertQueryBuilder ( { ... this . #props , queryNode : InsertQueryNode . cloneWith ( this . #props . queryNode , { ignore : true , } ) , } ) ; } /**
     * Adds an `on conflict` clause to the query.
     *
     * `on conflict` is only supported by some dialects like PostgreSQL and SQLite. On MySQL
     * you can use  ignore and  onDuplicateKeyUpdate to achieve similar results.
     *
     * ### Examples
     *
     * ```ts
     * await db
     *   .insertInto('pet')
     *   .values({
     *     name: 'Catto',
     *     species: 'cat',
     *   })
     *   .onConflict((oc) => oc
     *     .column('name')
     *     .doUpdateSet({ species: 'hamster' })
     *   )
     *   .execute()
     * ```
     *
     * The generated SQL (PostgreSQL):
     *
     * ```sql
     * insert into "pet" ("name", "species")
     * values ($1, $2)
     * on conflict ("name")
     * do update set "species" = $3
     * ```
     *
     * You can provide the name of the constraint instead of a column name:
     *
     * ```ts
     * await db
     *   .insertInto('pet')
     *   .values({
     *     name: 'Catto',
     *     species: 'cat',
     *   })
     *   .onConflict((oc) => oc
     *     .constraint('pet_name_key')
     *     .doUpdateSet({ species: 'hamster' })
     *   )
     *   .execute()
     *   .execute()
     * ```
     *
     * The generated SQL (PostgreSQL):
     *
     * ```sql
     * insert into "pet" ("name", "species")
     * values ($1, $2)
     * on conflict on constraint "pet_name_key"
     * do update set "species" = $3
     * ```
     *
     * You can also specify an expression as the conflict target in case
     * the unique index is an expression index:
     *
     * ```ts
     * await db
     *   .insertInto('pet')
     *   .values({
     *     name: 'Catto',
     *     species: 'cat',
     *   })
     *   .onConflict((oc) => oc
     *     .expression(db.raw('lower(name)'))
     *     .doUpdateSet({ species: 'hamster' })
     *   )
     *   .execute()
     * ```
     *
     * The generated SQL (PostgreSQL):
     *
     * ```sql
     * insert into "pet" ("name", "species")
     * values ($1, $2)
     * on conflict (lower(name))
     * do update set "species" = $3
     * ```
     *
     * You can add a filter for the update statement like this:
     *
     * ```ts
     * await db
     *   .insertInto('pet')
     *   .values({
     *     name: 'Catto',
     *     species: 'cat',
     *   })
     *   .onConflict((oc) => oc
     *     .column('name')
     *     .doUpdateSet({ species: 'hamster' })
     *     .where('excluded.name', '!=', 'Catto'')
     *   )
     *   .execute()
     * ```
     *
     * The generated SQL (PostgreSQL):
     *
     * ```sql
     * insert into "pet" ("name", "species")
     * values ($1, $2)
     * on conflict ("name")
     * do update set "species" = $3
     * where "excluded"."name" != $4
     * ```
     *
     * You can create an `on conflict do nothing` clauses like this:
     *
     * ```ts
     * await db
     *   .insertInto('pet')
     *   .values({
     *     name: 'Catto',
     *     species: 'cat',
     *   })
     *   .onConflict((oc) => oc
     *     .column('name')
     *     .doNothing()
     *   )
     *   .execute()
     * ```
     *
     * The generated SQL (PostgreSQL):
     *
     * ```sql
     * insert into "pet" ("name", "species")
     * values ($1, $2)
     * on conflict ("name") do nothing
     * ```
     *
     * You can refer to the columns of the virtual `excluded` table
     * in a type-safe way using a callback and the `ref` method of
     * `ExpressionBuilder`:
     *
     * ```ts
     * db.insertInto('person')
     *   .values(person)
     *   .onConflict(oc => oc
     *     .column('id')
     *     .doUpdateSet({
     *       first_name: (eb) => eb.ref('excluded.first_name'),
     *       last_name: (eb) => eb.ref('excluded.last_name')
     *     })
     *   )
     * ```
      onConflict ( callback ) { return new InsertQueryBuilder ( { ... this . #props , queryNode : InsertQueryNode . cloneWith ( this . #props . queryNode , { onConflict : callback ( new OnConflictBuilder ( { onConflictNode : OnConflictNode . create ( ) , parseContext : this . #props . parseContext , } ) ) . toOperationNode ( ) , } ) , } ) ; } /**
     * Adds `on duplicate key update` to the query.
     *
     * If you specify `on duplicate key update`, and a row is inserted that would cause
     * a duplicate value in a unique index or primary key, an update of the old row occurs.
     *
     * This is only implemented by some dialects like MySQL. On most dialects you should
     * use  onConflict instead.
     *
     * ### Examples
     *
     * ```ts
     * await db
     *   .insertInto('person')
     *   .values(values)
     *   .onDuplicateKeyUpdate({ species: 'hamster' })
     * ```
      onDuplicateKeyUpdate ( updates ) { return new InsertQueryBuilder ( { ... this . #props , queryNode : InsertQueryNode . cloneWith ( this . #props . queryNode , { onDuplicateKey : OnDuplicateKeyNode . create ( parseUpdateObject ( this . #props . parseContext , updates ) ) , } ) , } ) ; } returning < SE extends SelectExpression < DB , TB > > ( selections ) ; returning < SE extends SelectExpression < DB , TB > > ( selection ) ; returning ( selection ) { return new InsertQueryBuilder ( { ... this . #props , queryNode : QueryNode . cloneWithReturning ( this . #props . queryNode , parseSelectExpressionOrList ( this . #props . parseContext , selection ) ) , } ) ; } returningAll ( ) { return new InsertQueryBuilder ( { ... this . #props , queryNode : QueryNode . cloneWithReturning ( this . #props . queryNode , parseSelectAll ( ) ) , } ) ; } /**
     * Simply calls the given function passing `this` as the only argument.
     *
     * This method can be useful when adding optional method calls:
     *
     * ### Examples
     *
     * ```ts
     * db.insertInto('person')
     *   .selectAll()
     *   .call((qb) => {
     *     if (something) {
     *       return qb.onConflict((oc) => oc.column('something').doNothing())
     *     } else {
     *       return qb.onConflict((oc) => oc.column('something_else').doNothing())
     *     }
     *   })
     *   .execute()
     * ```
     */ call < T > ( func ) { return func ( this ) ; } /**
     * Change the output type of the query.
     *
     * You should only use this method as the last resort if the types
     * don't support your use case.
     */ castTo < T > ( ) { return new InsertQueryBuilder ( this . #props ) ; } withPlugin ( plugin ) { return new InsertQueryBuilder ( { ... this . #props , executor : this . #props . executor . withPlugin ( plugin ) , } ) ; } toOperationNode ( ) { return this . #props . executor . transformQuery ( this . #props . queryNode , this . #props . queryId ) ; } compile ( ) { return this . #props . executor . compileQuery ( this . toOperationNode ( ) , this . #props . queryId ) ; } /**
     * Executes the query and returns an array of rows.
     *
     * Also see the  executeTakeFirst and  executeTakeFirstOrThrow methods.
      async execute ( ) { const compildQuery = this . compile ( ) ; const query = compildQuery . query as InsertQueryNode ; const result = await this . #props . executor . executeQuery < O > ( compildQuery , this . #props . queryId ) ; if ( this . #props . parseContext . adapter . supportsReturning && query . returning ) { return result . rows ; } else { return [ new InsertResult ( result . insertId ) as unknown as O ] ; } } /**
     * Executes the query and returns the first result or undefined if
     * the query returned no result.
     */ async executeTakeFirst ( ) { const [ result ] = await this . execute ( ) ; return result as SingleResultType < O > ; } /**
     * Executes the query and returns the first result or throws if
     * the query returned no result.
     *
     * By default an instance of  NoResultError is thrown, but you can
     * provide a custom error class as the only argument to throw a different
     * error.
      async executeTakeFirstOrThrow ( errorConstructor = NoResultError ) { const result = await this . executeTakeFirst ( ) ; if ( result === undefined ) { throw new errorConstructor ( this . toOperationNode ( ) ) ; } return result as O ; } } preventAwait ( InsertQueryBuilder , "don't await InsertQueryBuilder instances directly. To execute the query you need to call `execute` or `executeTakeFirst`." ) ; export interface InsertQueryBuilderProps { readonly queryId : QueryId ; readonly queryNode : InsertQueryNode ; readonly executor : QueryExecutor ; readonly parseContext : ParseContext ; }