UNPKG

drizzle-orm

Version:

Drizzle ORM package for SQL databases

1 lines • 14.7 kB
{"version":3,"sources":["../../../src/mysql-core/query-builders/insert.ts"],"sourcesContent":["import { entityKind, is } from '~/entity.ts';\nimport type { MySqlDialect } from '~/mysql-core/dialect.ts';\nimport type {\n\tAnyMySqlQueryResultHKT,\n\tMySqlPreparedQueryConfig,\n\tMySqlQueryResultHKT,\n\tMySqlQueryResultKind,\n\tMySqlSession,\n\tPreparedQueryHKTBase,\n\tPreparedQueryKind,\n} from '~/mysql-core/session.ts';\nimport type { MySqlTable } from '~/mysql-core/table.ts';\nimport type { TypedQueryBuilder } from '~/query-builders/query-builder.ts';\nimport { QueryPromise } from '~/query-promise.ts';\nimport type { RunnableQuery } from '~/runnable-query.ts';\nimport type { Placeholder, Query, SQLWrapper } from '~/sql/sql.ts';\nimport { Param, SQL, sql } from '~/sql/sql.ts';\nimport type { InferModelFromColumns } from '~/table.ts';\nimport { Columns, Table } from '~/table.ts';\nimport { haveSameKeys, mapUpdateSet } from '~/utils.ts';\nimport type { AnyMySqlColumn } from '../columns/common.ts';\nimport { QueryBuilder } from './query-builder.ts';\nimport type { SelectedFieldsOrdered } from './select.types.ts';\nimport type { MySqlUpdateSetSource } from './update.ts';\n\nexport interface MySqlInsertConfig<TTable extends MySqlTable = MySqlTable> {\n\ttable: TTable;\n\tvalues: Record<string, Param | SQL>[] | MySqlInsertSelectQueryBuilder<TTable> | SQL;\n\tignore: boolean;\n\tonConflict?: SQL;\n\treturning?: SelectedFieldsOrdered;\n\tselect?: boolean;\n}\n\nexport type AnyMySqlInsertConfig = MySqlInsertConfig<MySqlTable>;\n\nexport type MySqlInsertValue<TTable extends MySqlTable> =\n\t& {\n\t\t[Key in keyof TTable['$inferInsert']]: TTable['$inferInsert'][Key] | SQL | Placeholder;\n\t}\n\t& {};\n\nexport type MySqlInsertSelectQueryBuilder<TTable extends MySqlTable> = TypedQueryBuilder<\n\t{ [K in keyof TTable['$inferInsert']]: AnyMySqlColumn | SQL | SQL.Aliased | TTable['$inferInsert'][K] }\n>;\n\nexport class MySqlInsertBuilder<\n\tTTable extends MySqlTable,\n\tTQueryResult extends MySqlQueryResultHKT,\n\tTPreparedQueryHKT extends PreparedQueryHKTBase,\n> {\n\tstatic readonly [entityKind]: string = 'MySqlInsertBuilder';\n\n\tprivate shouldIgnore = false;\n\n\tconstructor(\n\t\tprivate table: TTable,\n\t\tprivate session: MySqlSession,\n\t\tprivate dialect: MySqlDialect,\n\t) {}\n\n\tignore(): this {\n\t\tthis.shouldIgnore = true;\n\t\treturn this;\n\t}\n\n\tvalues(value: MySqlInsertValue<TTable>): MySqlInsertBase<TTable, TQueryResult, TPreparedQueryHKT>;\n\tvalues(values: MySqlInsertValue<TTable>[]): MySqlInsertBase<TTable, TQueryResult, TPreparedQueryHKT>;\n\tvalues(\n\t\tvalues: MySqlInsertValue<TTable> | MySqlInsertValue<TTable>[],\n\t): MySqlInsertBase<TTable, TQueryResult, TPreparedQueryHKT> {\n\t\tvalues = Array.isArray(values) ? values : [values];\n\t\tif (values.length === 0) {\n\t\t\tthrow new Error('values() must be called with at least one value');\n\t\t}\n\t\tconst mappedValues = values.map((entry) => {\n\t\t\tconst result: Record<string, Param | SQL> = {};\n\t\t\tconst cols = this.table[Table.Symbol.Columns];\n\t\t\tfor (const colKey of Object.keys(entry)) {\n\t\t\t\tconst colValue = entry[colKey as keyof typeof entry];\n\t\t\t\tresult[colKey] = is(colValue, SQL) ? colValue : new Param(colValue, cols[colKey]);\n\t\t\t}\n\t\t\treturn result;\n\t\t});\n\n\t\treturn new MySqlInsertBase(this.table, mappedValues, this.shouldIgnore, this.session, this.dialect);\n\t}\n\n\tselect(\n\t\tselectQuery: (qb: QueryBuilder) => MySqlInsertSelectQueryBuilder<TTable>,\n\t): MySqlInsertBase<TTable, TQueryResult, TPreparedQueryHKT>;\n\tselect(selectQuery: (qb: QueryBuilder) => SQL): MySqlInsertBase<TTable, TQueryResult, TPreparedQueryHKT>;\n\tselect(selectQuery: SQL): MySqlInsertBase<TTable, TQueryResult, TPreparedQueryHKT>;\n\tselect(selectQuery: MySqlInsertSelectQueryBuilder<TTable>): MySqlInsertBase<TTable, TQueryResult, TPreparedQueryHKT>;\n\tselect(\n\t\tselectQuery:\n\t\t\t| SQL\n\t\t\t| MySqlInsertSelectQueryBuilder<TTable>\n\t\t\t| ((qb: QueryBuilder) => MySqlInsertSelectQueryBuilder<TTable> | SQL),\n\t): MySqlInsertBase<TTable, TQueryResult, TPreparedQueryHKT> {\n\t\tconst select = typeof selectQuery === 'function' ? selectQuery(new QueryBuilder()) : selectQuery;\n\n\t\tif (\n\t\t\t!is(select, SQL)\n\t\t\t&& !haveSameKeys(this.table[Columns], select._.selectedFields)\n\t\t) {\n\t\t\tthrow new Error(\n\t\t\t\t'Insert select error: selected fields are not the same or are in a different order compared to the table definition',\n\t\t\t);\n\t\t}\n\n\t\treturn new MySqlInsertBase(this.table, select, this.shouldIgnore, this.session, this.dialect, true);\n\t}\n}\n\nexport type MySqlInsertWithout<T extends AnyMySqlInsert, TDynamic extends boolean, K extends keyof T & string> =\n\tTDynamic extends true ? T\n\t\t: Omit<\n\t\t\tMySqlInsertBase<\n\t\t\t\tT['_']['table'],\n\t\t\t\tT['_']['queryResult'],\n\t\t\t\tT['_']['preparedQueryHKT'],\n\t\t\t\tT['_']['returning'],\n\t\t\t\tTDynamic,\n\t\t\t\tT['_']['excludedMethods'] | '$returning'\n\t\t\t>,\n\t\t\tT['_']['excludedMethods'] | K\n\t\t>;\n\nexport type MySqlInsertDynamic<T extends AnyMySqlInsert> = MySqlInsert<\n\tT['_']['table'],\n\tT['_']['queryResult'],\n\tT['_']['preparedQueryHKT'],\n\tT['_']['returning']\n>;\n\nexport type MySqlInsertPrepare<\n\tT extends AnyMySqlInsert,\n\tTReturning extends Record<string, unknown> | undefined = undefined,\n> = PreparedQueryKind<\n\tT['_']['preparedQueryHKT'],\n\tMySqlPreparedQueryConfig & {\n\t\texecute: TReturning extends undefined ? MySqlQueryResultKind<T['_']['queryResult'], never> : TReturning[];\n\t\titerator: never;\n\t},\n\ttrue\n>;\n\nexport type MySqlInsertOnDuplicateKeyUpdateConfig<T extends AnyMySqlInsert> = {\n\tset: MySqlUpdateSetSource<T['_']['table']>;\n};\n\nexport type MySqlInsert<\n\tTTable extends MySqlTable = MySqlTable,\n\tTQueryResult extends MySqlQueryResultHKT = AnyMySqlQueryResultHKT,\n\tTPreparedQueryHKT extends PreparedQueryHKTBase = PreparedQueryHKTBase,\n\tTReturning extends Record<string, unknown> | undefined = Record<string, unknown> | undefined,\n> = MySqlInsertBase<TTable, TQueryResult, TPreparedQueryHKT, TReturning, true, never>;\n\nexport type MySqlInsertReturning<\n\tT extends AnyMySqlInsert,\n\tTDynamic extends boolean,\n> = MySqlInsertBase<\n\tT['_']['table'],\n\tT['_']['queryResult'],\n\tT['_']['preparedQueryHKT'],\n\tInferModelFromColumns<GetPrimarySerialOrDefaultKeys<T['_']['table']['_']['columns']>>,\n\tTDynamic,\n\tT['_']['excludedMethods'] | '$returning'\n>;\n\nexport type AnyMySqlInsert = MySqlInsertBase<any, any, any, any, any, any>;\n\nexport interface MySqlInsertBase<\n\tTTable extends MySqlTable,\n\tTQueryResult extends MySqlQueryResultHKT,\n\tTPreparedQueryHKT extends PreparedQueryHKTBase,\n\tTReturning extends Record<string, unknown> | undefined = undefined,\n\tTDynamic extends boolean = false,\n\tTExcludedMethods extends string = never,\n> extends\n\tQueryPromise<TReturning extends undefined ? MySqlQueryResultKind<TQueryResult, never> : TReturning[]>,\n\tRunnableQuery<TReturning extends undefined ? MySqlQueryResultKind<TQueryResult, never> : TReturning[], 'mysql'>,\n\tSQLWrapper\n{\n\treadonly _: {\n\t\treadonly dialect: 'mysql';\n\t\treadonly table: TTable;\n\t\treadonly queryResult: TQueryResult;\n\t\treadonly preparedQueryHKT: TPreparedQueryHKT;\n\t\treadonly dynamic: TDynamic;\n\t\treadonly excludedMethods: TExcludedMethods;\n\t\treadonly returning: TReturning;\n\t\treadonly result: TReturning extends undefined ? MySqlQueryResultKind<TQueryResult, never> : TReturning[];\n\t};\n}\n\nexport type PrimaryKeyKeys<T extends Record<string, AnyMySqlColumn>> = {\n\t[K in keyof T]: T[K]['_']['isPrimaryKey'] extends true ? T[K]['_']['isAutoincrement'] extends true ? K\n\t\t: T[K]['_']['hasRuntimeDefault'] extends true ? T[K]['_']['isPrimaryKey'] extends true ? K : never\n\t\t: never\n\t\t: T[K]['_']['hasRuntimeDefault'] extends true ? T[K]['_']['isPrimaryKey'] extends true ? K : never\n\t\t: never;\n}[keyof T];\n\nexport type GetPrimarySerialOrDefaultKeys<T extends Record<string, AnyMySqlColumn>> = {\n\t[K in PrimaryKeyKeys<T>]: T[K];\n};\n\nexport class MySqlInsertBase<\n\tTTable extends MySqlTable,\n\tTQueryResult extends MySqlQueryResultHKT,\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\tTPreparedQueryHKT extends PreparedQueryHKTBase,\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\tTReturning extends Record<string, unknown> | undefined = undefined,\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\tTDynamic extends boolean = false,\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\tTExcludedMethods extends string = never,\n> extends QueryPromise<TReturning extends undefined ? MySqlQueryResultKind<TQueryResult, never> : TReturning[]>\n\timplements\n\t\tRunnableQuery<TReturning extends undefined ? MySqlQueryResultKind<TQueryResult, never> : TReturning[], 'mysql'>,\n\t\tSQLWrapper\n{\n\tstatic override readonly [entityKind]: string = 'MySqlInsert';\n\n\tdeclare protected $table: TTable;\n\n\tprivate config: MySqlInsertConfig<TTable>;\n\n\tconstructor(\n\t\ttable: TTable,\n\t\tvalues: MySqlInsertConfig['values'],\n\t\tignore: boolean,\n\t\tprivate session: MySqlSession,\n\t\tprivate dialect: MySqlDialect,\n\t\tselect?: boolean,\n\t) {\n\t\tsuper();\n\t\tthis.config = { table, values: values as any, select, ignore };\n\t}\n\n\t/**\n\t * Adds an `on duplicate key update` clause to the query.\n\t *\n\t * Calling this method will update the row if any unique index conflicts. MySQL will automatically determine the conflict target based on the primary key and unique indexes.\n\t *\n\t * See docs: {@link https://orm.drizzle.team/docs/insert#on-duplicate-key-update}\n\t *\n\t * @param config The `set` clause\n\t *\n\t * @example\n\t * ```ts\n\t * await db.insert(cars)\n\t * .values({ id: 1, brand: 'BMW'})\n\t * .onDuplicateKeyUpdate({ set: { brand: 'Porsche' }});\n\t * ```\n\t *\n\t * While MySQL does not directly support doing nothing on conflict, you can perform a no-op by setting any column's value to itself and achieve the same effect:\n\t *\n\t * ```ts\n\t * import { sql } from 'drizzle-orm';\n\t *\n\t * await db.insert(cars)\n\t * .values({ id: 1, brand: 'BMW' })\n\t * .onDuplicateKeyUpdate({ set: { id: sql`id` } });\n\t * ```\n\t */\n\tonDuplicateKeyUpdate(\n\t\tconfig: MySqlInsertOnDuplicateKeyUpdateConfig<this>,\n\t): MySqlInsertWithout<this, TDynamic, 'onDuplicateKeyUpdate'> {\n\t\tconst setSql = this.dialect.buildUpdateSet(this.config.table, mapUpdateSet(this.config.table, config.set));\n\t\tthis.config.onConflict = sql`update ${setSql}`;\n\t\treturn this as any;\n\t}\n\n\t$returningId(): MySqlInsertWithout<\n\t\tMySqlInsertReturning<this, TDynamic>,\n\t\tTDynamic,\n\t\t'$returningId'\n\t> {\n\t\tconst returning: SelectedFieldsOrdered = [];\n\t\tfor (const [key, value] of Object.entries(this.config.table[Table.Symbol.Columns])) {\n\t\t\tif (value.primary) {\n\t\t\t\treturning.push({ field: value, path: [key] });\n\t\t\t}\n\t\t}\n\t\tthis.config.returning = returning;\n\t\treturn this as any;\n\t}\n\n\t/** @internal */\n\tgetSQL(): SQL {\n\t\treturn this.dialect.buildInsertQuery(this.config).sql;\n\t}\n\n\ttoSQL(): Query {\n\t\tconst { typings: _typings, ...rest } = this.dialect.sqlToQuery(this.getSQL());\n\t\treturn rest;\n\t}\n\n\tprepare(): MySqlInsertPrepare<this, TReturning> {\n\t\tconst { sql, generatedIds } = this.dialect.buildInsertQuery(this.config);\n\t\treturn this.session.prepareQuery(\n\t\t\tthis.dialect.sqlToQuery(sql),\n\t\t\tundefined,\n\t\t\tundefined,\n\t\t\tgeneratedIds,\n\t\t\tthis.config.returning,\n\t\t) as MySqlInsertPrepare<this, TReturning>;\n\t}\n\n\toverride execute: ReturnType<this['prepare']>['execute'] = (placeholderValues) => {\n\t\treturn this.prepare().execute(placeholderValues);\n\t};\n\n\tprivate createIterator = (): ReturnType<this['prepare']>['iterator'] => {\n\t\tconst self = this;\n\t\treturn async function*(placeholderValues) {\n\t\t\tyield* self.prepare().iterator(placeholderValues);\n\t\t};\n\t};\n\n\titerator = this.createIterator();\n\n\t$dynamic(): MySqlInsertDynamic<this> {\n\t\treturn this as any;\n\t}\n}\n"],"mappings":"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","names":["sql"]}