/* oxlint-disable */ import type * as Effect from "effect/Effect" import { applyEffectWrapper, type QueryEffectHKTBase } from "drizzle-orm/effect-core/query-effect" import { entityKind, is } from "drizzle-orm/entity" import type { SelectResultFields } from "drizzle-orm/query-builders/select.types" import type { RunnableQuery } from "drizzle-orm/runnable-query" import type { Query, SQLWrapper } from "drizzle-orm/sql/sql" import { Param, SQL, sql } from "drizzle-orm/sql/sql" import type { SQLiteDialect } from "drizzle-orm/sqlite-core/dialect" import type { IndexColumn } from "drizzle-orm/sqlite-core/indexes" import type { SQLiteInsertConfig, SQLiteInsertSelectQueryBuilder, SQLiteInsertValue, } from "drizzle-orm/sqlite-core/query-builders/insert" import type { SelectedFieldsFlat } from "drizzle-orm/sqlite-core/query-builders/select.types" import type { PreparedQueryConfig } from "drizzle-orm/sqlite-core/session" import { SQLiteTable } from "drizzle-orm/sqlite-core/table" import { extractUsedTable } from "drizzle-orm/sqlite-core/utils" import type { Subquery } from "drizzle-orm/subquery" import { type DrizzleTypeError, haveSameKeys } from "drizzle-orm/utils" import type { SQLiteColumn } from "drizzle-orm/sqlite-core/columns/common" import { QueryBuilder } from "drizzle-orm/sqlite-core/query-builders/query-builder" import type { SQLiteUpdateSetSource } from "drizzle-orm/sqlite-core/query-builders/update" import { getTableColumnsRuntime, mapUpdateSet, orderSelectedFields } from "../../internal/drizzle-utils" import type { SQLiteEffectPreparedQuery, SQLiteEffectSession } from "./session" export type SQLiteEffectInsertWithout< T extends AnySQLiteEffectInsert, TDynamic extends boolean, K extends keyof T & string, > = TDynamic extends true ? T : Omit< SQLiteEffectInsertBase< T["_"]["table"], T["_"]["runResult"], T["_"]["returning"], TDynamic, T["_"]["excludedMethods"] | K, T["_"]["effectHKT"] >, T["_"]["excludedMethods"] | K > export type SQLiteEffectInsertReturning< T extends AnySQLiteEffectInsert, TDynamic extends boolean, TSelectedFields extends SelectedFieldsFlat, > = SQLiteEffectInsertWithout< SQLiteEffectInsertBase< T["_"]["table"], T["_"]["runResult"], SelectResultFields, TDynamic, T["_"]["excludedMethods"], T["_"]["effectHKT"] >, TDynamic, "returning" > export type SQLiteEffectInsertReturningAll< T extends AnySQLiteEffectInsert, TDynamic extends boolean, > = SQLiteEffectInsertWithout< SQLiteEffectInsertBase< T["_"]["table"], T["_"]["runResult"], T["_"]["table"]["$inferSelect"], TDynamic, T["_"]["excludedMethods"], T["_"]["effectHKT"] >, TDynamic, "returning" > export type SQLiteEffectInsertDynamic = SQLiteEffectInsert< T["_"]["table"], T["_"]["runResult"], T["_"]["returning"], T["_"]["effectHKT"] > export type SQLiteEffectInsertOnConflictDoUpdateConfig = { target: IndexColumn | IndexColumn[] /** @deprecated - use either `targetWhere` or `setWhere` */ where?: SQL targetWhere?: SQL setWhere?: SQL set: SQLiteUpdateSetSource } export type SQLiteEffectInsertExecute = T["_"]["returning"] extends undefined ? T["_"]["runResult"] : T["_"]["returning"][] export type SQLiteEffectInsertPrepare< T extends AnySQLiteEffectInsert, TEffectHKT extends QueryEffectHKTBase = T["_"]["effectHKT"], > = SQLiteEffectPreparedQuery< PreparedQueryConfig & { run: T["_"]["runResult"] all: T["_"]["returning"] extends undefined ? DrizzleTypeError<".all() cannot be used without .returning()"> : T["_"]["returning"][] get: T["_"]["returning"] extends undefined ? DrizzleTypeError<".get() cannot be used without .returning()"> : T["_"]["returning"] values: T["_"]["returning"] extends undefined ? DrizzleTypeError<".values() cannot be used without .returning()"> : any[][] execute: SQLiteEffectInsertExecute }, TEffectHKT > export type SQLiteEffectInsert< TTable extends SQLiteTable = SQLiteTable, TRunResult = unknown, TReturning = any, TEffectHKT extends QueryEffectHKTBase = QueryEffectHKTBase, > = SQLiteEffectInsertBase export type AnySQLiteEffectInsert = SQLiteEffectInsertBase export class SQLiteEffectInsertBuilder< TTable extends SQLiteTable, TRunResult, TEffectHKT extends QueryEffectHKTBase = QueryEffectHKTBase, > { static readonly [entityKind]: string = "SQLiteEffectInsertBuilder" constructor( protected table: TTable, protected session: SQLiteEffectSession, protected dialect: SQLiteDialect, private withList?: Subquery[], ) {} values( value: SQLiteInsertValue, ): SQLiteEffectInsertBase values( values: SQLiteInsertValue[], ): SQLiteEffectInsertBase values( values: SQLiteInsertValue | SQLiteInsertValue[], ): SQLiteEffectInsertBase { values = Array.isArray(values) ? values : [values] if (values.length === 0) { throw new Error("values() must be called with at least one value") } const mappedValues = values.map((entry) => { const result: Record = {} const cols = getTableColumnsRuntime(this.table) for (const colKey of Object.keys(entry)) { const colValue = entry[colKey as keyof typeof entry] result[colKey] = is(colValue, SQL) ? colValue : new Param(colValue, cols[colKey]) } return result }) return new SQLiteEffectInsertBase(this.table, mappedValues, this.session, this.dialect, this.withList) } select( selectQuery: (qb: QueryBuilder) => SQLiteInsertSelectQueryBuilder, ): SQLiteEffectInsertBase select( selectQuery: (qb: QueryBuilder) => SQL, ): SQLiteEffectInsertBase select(selectQuery: SQL): SQLiteEffectInsertBase select( selectQuery: SQLiteInsertSelectQueryBuilder, ): SQLiteEffectInsertBase select( selectQuery: | SQL | SQLiteInsertSelectQueryBuilder | ((qb: QueryBuilder) => SQLiteInsertSelectQueryBuilder | SQL), ): SQLiteEffectInsertBase { const select = typeof selectQuery === "function" ? selectQuery(new QueryBuilder()) : selectQuery if (!is(select, SQL) && !haveSameKeys(getTableColumnsRuntime(this.table), select._.selectedFields)) { throw new Error( "Insert select error: selected fields are not the same or are in a different order compared to the table definition", ) } return new SQLiteEffectInsertBase(this.table, select, this.session, this.dialect, this.withList, true) } } export interface SQLiteEffectInsertBase< TTable extends SQLiteTable, TRunResult, TReturning = undefined, TDynamic extends boolean = false, _TExcludedMethods extends string = never, TEffectHKT extends QueryEffectHKTBase = QueryEffectHKTBase, > extends SQLWrapper, RunnableQuery, Effect.Effect< TReturning extends undefined ? TRunResult : TReturning[], TEffectHKT["error"], TEffectHKT["context"] > { readonly _: { readonly dialect: "sqlite" readonly table: TTable readonly resultType: "async" readonly runResult: TRunResult readonly returning: TReturning readonly dynamic: TDynamic readonly excludedMethods: _TExcludedMethods readonly result: TReturning extends undefined ? TRunResult : TReturning[] readonly effectHKT: TEffectHKT } } export class SQLiteEffectInsertBase< TTable extends SQLiteTable, TRunResult, TReturning = undefined, TDynamic extends boolean = false, _TExcludedMethods extends string = never, TEffectHKT extends QueryEffectHKTBase = QueryEffectHKTBase, > implements RunnableQuery, SQLWrapper { static readonly [entityKind]: string = "SQLiteEffectInsert" /** @internal */ config: SQLiteInsertConfig constructor( private table: TTable, values: SQLiteInsertConfig["values"], private effectSession: SQLiteEffectSession, private effectDialect: SQLiteDialect, withList?: Subquery[], select?: boolean, ) { this.config = { table, values: values as any, withList, select } } returning(): SQLiteEffectInsertReturningAll returning( fields: TSelectedFields, ): SQLiteEffectInsertReturning returning( fields: SelectedFieldsFlat = getTableColumnsRuntime(this.config.table), ): SQLiteEffectInsertWithout { this.config.returning = orderSelectedFields(fields) return this as any } onConflictDoNothing(config: { target?: IndexColumn | IndexColumn[]; where?: SQL } = {}): this { if (!this.config.onConflict) this.config.onConflict = [] if (config.target === undefined) { this.config.onConflict.push(sql` on conflict do nothing`) return this } const targetSql = Array.isArray(config.target) ? sql`${config.target}` : sql`${[config.target]}` const whereSql = config.where ? sql` where ${config.where}` : sql`` this.config.onConflict.push(sql` on conflict ${targetSql} do nothing${whereSql}`) return this } onConflictDoUpdate(config: SQLiteEffectInsertOnConflictDoUpdateConfig): this { if (config.where && (config.targetWhere || config.setWhere)) { throw new Error( 'You cannot use both "where" and "targetWhere"/"setWhere" at the same time - "where" is deprecated, use "targetWhere" or "setWhere" instead.', ) } if (!this.config.onConflict) this.config.onConflict = [] const whereSql = config.where ? sql` where ${config.where}` : undefined const targetWhereSql = config.targetWhere ? sql` where ${config.targetWhere}` : undefined const setWhereSql = config.setWhere ? sql` where ${config.setWhere}` : undefined const targetSql = Array.isArray(config.target) ? sql`${config.target}` : sql`${[config.target]}` const setSql = this.effectDialect.buildUpdateSet( this.config.table, mapUpdateSet(this.config.table, config.set as SQLiteUpdateSetSource), ) this.config.onConflict.push( sql` on conflict ${targetSql}${targetWhereSql} do update set ${setSql}${whereSql}${setWhereSql}`, ) return this } /** @internal */ getSQL(): SQL { return this.effectDialect.buildInsertQuery(this.config) } toSQL(): Query { return this.effectDialect.sqlToQuery(this.getSQL()) } /** @internal */ _prepare(isOneTimeQuery = true): SQLiteEffectInsertPrepare { return this.effectSession[isOneTimeQuery ? "prepareOneTimeQuery" : "prepareQuery"]( this.effectDialect.sqlToQuery(this.getSQL()), this.config.returning, this.config.returning ? "all" : "run", undefined, { type: "insert", tables: extractUsedTable(this.config.table), }, ) as SQLiteEffectInsertPrepare } prepare(): SQLiteEffectInsertPrepare { return this._prepare(false) } run: ReturnType["run"] = (placeholderValues) => { return this._prepare().run(placeholderValues) } all: ReturnType["all"] = (placeholderValues) => { return this._prepare().all(placeholderValues) } get: ReturnType["get"] = (placeholderValues) => { return this._prepare().get(placeholderValues) } values: ReturnType["values"] = (placeholderValues) => { return this._prepare().values(placeholderValues) } execute: ReturnType["execute"] = (placeholderValues) => { return this._prepare().execute(placeholderValues) } $dynamic(): SQLiteEffectInsertDynamic { return this as any } } applyEffectWrapper(SQLiteEffectInsertBase)