-module(cake@insert). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/cake/insert.gleam"). -export([to_query/1, row/1, bool/1, float/1, int/1, string/1, null/0, date/1, fragment/1, new/0, from_records/4, from_values/3, table/2, get_table/1, modifier/2, no_modifier/1, get_modifier/1, source_records/3, source_values/2, get_source/1, columns/2, get_columns/1, on_conflict_error/1, on_columns_conflict_ignore/3, on_constraint_conflict_ignore/3, on_columns_conflict_update/4, on_constraint_conflict_update/4, get_on_conflict/1, on_duplicate_key_update/2, returning/2, no_returning/1, epilog/2, no_epilog/1, get_epilog/1, comment/2, no_comment/1, get_comment/1]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC( " A DSL to build `INSERT` queries.\n" "\n" " ## Aliases\n" "\n" " ```gleam\n" " import cake/insert as i\n" " import cake/where as w\n" " import cake/fragment as f\n" " ```\n" "\n" " ---\n" "\n" " ## Query Lifecycle\n" "\n" " ```mermaid\n" " flowchart LR\n" " A[i.from_records / i.from_values / i.new] --> B[configure table & columns]\n" " B --> C[on_conflict strategy]\n" " C --> D[returning]\n" " D --> E[i.to_query]\n" " ```\n" "\n" " ---\n" "\n" " ## Constructors\n" "\n" " There are three ways to start building an `INSERT` query.\n" "\n" " ### `from_records(table_name, columns, records, encoder) -> Insert(a)`\n" "\n" " The idiomatic way. Supply a list of typed Gleam records and an encoder function\n" " that maps each record to an `InsertRow`.\n" "\n" " ```gleam\n" " type User {\n" " User(name: String, age: Int)\n" " }\n" "\n" " fn encode_user(u: User) -> i.InsertRow {\n" " i.row([i.string(u.name), i.int(u.age)])\n" " }\n" "\n" " [User(\"Alice\", 30), User(\"Bob\", 25)]\n" " |> i.from_records(\n" " table_name: \"users\",\n" " columns: [\"name\", \"age\"],\n" " encoder: encode_user,\n" " )\n" " |> i.to_query\n" " // INSERT INTO users (name, age) VALUES ($1, $2), ($3, $4)\n" " ```\n" "\n" " ### `from_values(table_name, columns, values) -> Insert(a)`\n" "\n" " Supply pre-built `InsertRow` values directly.\n" "\n" " ```gleam\n" " [\n" " i.row([i.string(\"Alice\"), i.int(30)]),\n" " i.row([i.string(\"Bob\"), i.int(25)]),\n" " ]\n" " |> i.from_values(table_name: \"users\", columns: [\"name\", \"age\"])\n" " |> i.to_query\n" " ```\n" "\n" " ### `new() -> Insert(a)`\n" "\n" " Creates a completely empty `Insert`. Useful when building the query\n" " incrementally.\n" "\n" " ```gleam\n" " i.new()\n" " |> i.table(\"users\")\n" " |> i.columns([\"name\", \"age\"])\n" " |> i.source_values([i.row([i.string(\"Alice\"), i.int(30)])])\n" " |> i.to_query\n" " ```\n" "\n" " ### `to_query(insert: Insert(a)) -> WriteQuery(a)`\n" "\n" " Converts an `Insert` into a `WriteQuery` for execution.\n" "\n" " ---\n" "\n" " ## Row and Value Constructors\n" "\n" " ### `row(values: List(InsertValue)) -> InsertRow`\n" "\n" " Wraps a list of `InsertValue`s into a single `InsertRow`.\n" "\n" " ```gleam\n" " i.row([i.string(\"Alice\"), i.int(30), i.bool(True)])\n" " ```\n" "\n" " ### Value constructors\n" "\n" " | Function | SQL type |\n" "\n" " | Function | SQL type |\n" " | ---------- | ---------------- |\n" " | `bool(value)` | Boolean param |\n" " | `float(value)` | Float param |\n" " | `int(value)` | Integer param |\n" " | `string(value)` | String param |\n" " | `null()` | NULL |\n" " | `date(value)` | Date param |\n" " | `fragment(value)` | Raw SQL fragment |\n" "\n" " ```gleam\n" " // Inserting a UUID via a database cast\n" " import cake/fragment as f\n" "\n" " i.fragment(f.prepared(\"?::uuid\", [f.string(\"0000-0000-4000-a000-a00000000000\")]))\n" " ```\n" "\n" " ---\n" "\n" " ## Setting the Table\n" "\n" " When using `new()` you can configure (or override) the target table:\n" "\n" " ```gleam\n" " i.new() |> i.table(\"users\")\n" " ```\n" "\n" " ---\n" "\n" " ## Configuring the Source\n" "\n" " ### `source_records(insert, records, encoder) -> Insert(a)`\n" "\n" " Attach a list of records and an encoder to an existing `Insert`.\n" "\n" " ### `source_values(insert, rows) -> Insert(a)`\n" "\n" " Attach raw `InsertRow` values to an existing `Insert`.\n" "\n" " ### `columns(insert, columns) -> Insert(a)`\n" "\n" " Set the column list. The number of columns **must** match the number of values\n" " in each `InsertRow`.\n" "\n" " ---\n" "\n" " ## Conflict Strategies\n" "\n" " ```mermaid\n" " flowchart TD\n" " A[Insert] --> B{on conflict}\n" " B -->|error| C[InsertConflictError\\ndefault - raise error]\n" " B -->|ignore columns| D[on_columns_conflict_ignore\\nPG + SQLite]\n" " B -->|ignore constraint| E[on_constraint_conflict_ignore\\nPG + SQLite]\n" " B -->|upsert columns| F[on_columns_conflict_update\\nPG + SQLite]\n" " B -->|upsert constraint| G[on_constraint_conflict_update\\nPG only]\n" " B -->|duplicate key| H[on_duplicate_key_update\\nMySQL + MariaDB]\n" " ```\n" "\n" " ### `on_conflict_error(insert) -> Insert(a)`\n" "\n" " The default. Any uniqueness/constraint violation raises an error.\n" "\n" " ### `on_columns_conflict_ignore(insert, columns, where) -> Insert(a)`\n" "\n" " Silently skip conflicting rows when the conflict is on the given columns.\n" "\n" " > Supported by 🐘 PostgreSQL and 🪶 SQLite.\n" "\n" " ```gleam\n" " i.from_values(\"users\", [\"email\"], [i.row([i.string(\"a@b.com\")])])\n" " |> i.on_columns_conflict_ignore(\n" " columns: [\"email\"],\n" " where: w.none(),\n" " )\n" " // INSERT INTO users (email) VALUES ($1) ON CONFLICT (email) DO NOTHING\n" " ```\n" "\n" " ### `on_constraint_conflict_ignore(insert, constraint, where) -> Insert(a)`\n" "\n" " Same as above but identifies the conflict target by constraint name.\n" "\n" " > Supported by 🐘 PostgreSQL and 🪶 SQLite.\n" "\n" " ### `on_columns_conflict_update(insert, columns, where, update) -> Insert(a)`\n" "\n" " **Upsert** — insert or update on conflict (PostgreSQL / SQLite style).\n" "\n" " Use `excluded.column` in your `Update` expressions to reference the values\n" " that were being inserted.\n" "\n" " > Supported by 🐘 PostgreSQL ✅ and 🪶 SQLite ✅.\n" " > Not supported by 🦭 MariaDB or 🐬 MySQL — use `on_duplicate_key_update` instead.\n" "\n" " ```gleam\n" " import cake/update as u\n" "\n" " i.from_values(\"scores\", [\"username\", \"score\"], [\n" " i.row([i.string(\"alice\"), i.int(100)]),\n" " ])\n" " |> i.on_columns_conflict_update(\n" " columns: [\"username\"],\n" " where: w.none(),\n" " update: u.new()\n" " |> u.set(u.set_expression(\"score\", \"excluded.score\")),\n" " )\n" " // INSERT INTO scores (username, score) VALUES ($1, $2)\n" " // ON CONFLICT (username) DO UPDATE SET score = excluded.score\n" " ```\n" "\n" " ### `on_constraint_conflict_update(insert, constraint, where, update) -> Insert(a)`\n" "\n" " Same as above but targets a named constraint.\n" "\n" " > Supported by 🐘 PostgreSQL only.\n" "\n" " ### `on_duplicate_key_update(insert, update) -> Insert(a)`\n" "\n" " **MySQL / MariaDB upsert** using `ON DUPLICATE KEY UPDATE` syntax.\n" "\n" " Use `VALUES(column)` (not `excluded.column`) in your `Update` expressions.\n" "\n" " > Supported by 🦭 MariaDB ✅ and 🐬 MySQL ✅ only.\n" "\n" " ```gleam\n" " i.from_values(\"scores\", [\"username\", \"score\"], [\n" " i.row([i.string(\"alice\"), i.int(100)]),\n" " ])\n" " |> i.on_duplicate_key_update(\n" " update: u.new()\n" " |> u.set(u.set_expression(\"score\", \"VALUES(score) + scores.score\")),\n" " )\n" " // INSERT INTO scores (username, score) VALUES (?, ?)\n" " // ON DUPLICATE KEY UPDATE score = VALUES(score) + scores.score\n" " ```\n" "\n" " ---\n" "\n" " ## RETURNING\n" "\n" " Fetch column values from the inserted rows (🐘 PostgreSQL and 🪶 SQLite).\n" "\n" " > 🦭 MariaDB and 🐬 MySQL do not support `RETURNING` in `INSERT` queries.\n" "\n" " ```gleam\n" " i.from_values(\"users\", [\"name\"], [i.row([i.string(\"Alice\")])])\n" " |> i.returning([\"id\", \"name\"])\n" " // INSERT INTO users (name) VALUES ($1) RETURNING id, name\n" " ```\n" "\n" " | Function | Effect |\n" "\n" " | Function | Effect |\n" " | ------ | ------ |\n" " | `returning(insert, cols)` | Return the listed columns |\n" " | `no_returning(insert)` | Remove RETURNING clause |\n" "\n" " ---\n" "\n" " ## Modifier\n" "\n" " A raw string modifier inserted after `INSERT` (e.g. `OR IGNORE` for SQLite).\n" "\n" " ```gleam\n" " i.new() |> i.modifier(\"OR IGNORE\")\n" " // INSERT OR IGNORE INTO ...\n" " ```\n" "\n" " ---\n" "\n" " ## Epilog and Comment\n" "\n" " ```gleam\n" " i.new()\n" " |> i.from_values(\"logs\", [\"msg\"], [i.row([i.string(\"hello\")])])\n" " |> i.epilog(\"RETURNING id\")\n" " |> i.comment(\"audit log insert\")\n" " ```\n" "\n" " ---\n" "\n" " ## Full Example\n" "\n" " ```gleam\n" " import cake/insert as i\n" " import cake/update as u\n" " import cake/where as w\n" "\n" " type Product { Product(sku: String, price: Float) }\n" "\n" " fn encode_product(p: Product) -> i.InsertRow {\n" " i.row([i.string(p.sku), i.float(p.price)])\n" " }\n" "\n" " [Product(\"ABC-1\", 9.99), Product(\"ABC-2\", 14.99)]\n" " |> i.from_records(\n" " table_name: \"products\",\n" " columns: [\"sku\", \"price\"],\n" " encoder: encode_product,\n" " )\n" " |> i.on_columns_conflict_update(\n" " columns: [\"sku\"],\n" " where: w.none(),\n" " update: u.new() |> u.set(u.set_expression(\"price\", \"excluded.price\")),\n" " )\n" " |> i.returning([\"id\", \"sku\"])\n" " |> i.to_query\n" " ```\n" "\n" "\n" " \n" " \n" " \n" " \n" " \n" "\n" ). -file("src/cake/insert.gleam", 397). ?DOC(" Creates a `WriteQuery` from an `Insert` query.\n"). -spec to_query(cake@internal@write_query:insert(FPK)) -> cake@internal@write_query:write_query(FPK). to_query(Insert) -> _pipe = Insert, {insert_query, _pipe}. -file("src/cake/insert.gleam", 405). ?DOC(" Create an `InsertRow` from a list of `InsertValue`s.\n"). -spec row(list(cake@internal@write_query:insert_value())) -> cake@internal@write_query:insert_row(). row(Values) -> _pipe = Values, {insert_row, _pipe}. -file("src/cake/insert.gleam", 411). ?DOC(" Create an `InsertValue` from a column `String` and a `Bool` value.\n"). -spec bool(boolean()) -> cake@internal@write_query:insert_value(). bool(Value) -> _pipe = Value, _pipe@1 = {bool_param, _pipe}, {insert_param, _pipe@1}. -file("src/cake/insert.gleam", 417). ?DOC(" Create an `InsertValue` from a column `String` and a `Float` value.\n"). -spec float(float()) -> cake@internal@write_query:insert_value(). float(Value) -> _pipe = Value, _pipe@1 = {float_param, _pipe}, {insert_param, _pipe@1}. -file("src/cake/insert.gleam", 423). ?DOC(" Create an `InsertValue` from a column `String` and an `Int` value.\n"). -spec int(integer()) -> cake@internal@write_query:insert_value(). int(Value) -> _pipe = Value, _pipe@1 = {int_param, _pipe}, {insert_param, _pipe@1}. -file("src/cake/insert.gleam", 429). ?DOC(" Create an `InsertValue` from a column `String` and a `String` value.\n"). -spec string(binary()) -> cake@internal@write_query:insert_value(). string(Value) -> _pipe = Value, _pipe@1 = {string_param, _pipe}, {insert_param, _pipe@1}. -file("src/cake/insert.gleam", 435). ?DOC(" Create a NULL `InsertValue`.\n"). -spec null() -> cake@internal@write_query:insert_value(). null() -> _pipe = null_param, {insert_param, _pipe}. -file("src/cake/insert.gleam", 441). ?DOC(" Create an `InsertValue` from a `calendar.Date`.\n"). -spec date(gleam@time@calendar:date()) -> cake@internal@write_query:insert_value(). date(Value) -> _pipe = Value, _pipe@1 = {date_param, _pipe}, {insert_param, _pipe@1}. -file("src/cake/insert.gleam", 456). ?DOC( " Create an `InsertValue` from a `Fragment`.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import cake/fragment as f\n" " import cake/insert as i\n" "\n" " i.fragment(f.prepared(\"$::uuid\", [f.string(\"0000000000-0000-4000-a000-a00000000000\")]))\n" " ```\n" ). -spec fragment(cake@internal@read_query:fragment()) -> cake@internal@write_query:insert_value(). fragment(Value) -> {insert_fragment, Value}. -file("src/cake/insert.gleam", 464). ?DOC(" Create an empty `INSERT` query.\n"). -spec new() -> cake@internal@write_query:insert(any()). new() -> {insert, no_insert_into_table, no_insert_columns, no_insert_modifier, no_insert_source, insert_conflict_error, no_returning, no_epilog, no_comment}. -file("src/cake/insert.gleam", 481). ?DOC( " Create an `INSERT` query from a list of gleam records.\n" "\n" " The `encoder` function is used to convert each record into an `InsertRow`.\n" ). -spec from_records( binary(), list(binary()), list(FPR), fun((FPR) -> cake@internal@write_query:insert_row()) ) -> cake@internal@write_query:insert(FPR). from_records(Table_name, Columns, Records, Encoder) -> {insert, begin _pipe = Table_name, {insert_into_table, _pipe} end, begin _pipe@1 = Columns, {insert_columns, _pipe@1} end, no_insert_modifier, begin _pipe@2 = Records, {insert_source_records, _pipe@2, Encoder} end, insert_conflict_error, no_returning, no_epilog, no_comment}. -file("src/cake/insert.gleam", 501). ?DOC(" Create an `INSERT` query from a list of `InsertRow`s.\n"). -spec from_values( binary(), list(binary()), list(cake@internal@write_query:insert_row()) ) -> cake@internal@write_query:insert(any()). from_values(Table_name, Columns, Values) -> {insert, begin _pipe = Table_name, {insert_into_table, _pipe} end, begin _pipe@1 = Columns, {insert_columns, _pipe@1} end, no_insert_modifier, begin _pipe@2 = Values, {insert_source_rows, _pipe@2} end, insert_conflict_error, no_returning, no_epilog, no_comment}. -file("src/cake/insert.gleam", 522). ?DOC(" Specify the table to insert into.\n"). -spec table(cake@internal@write_query:insert(FPY), binary()) -> cake@internal@write_query:insert(FPY). table(Insert, Table_name) -> {insert, begin _pipe = Table_name, {insert_into_table, _pipe} end, erlang:element(3, Insert), erlang:element(4, Insert), erlang:element(5, Insert), erlang:element(6, Insert), erlang:element(7, Insert), erlang:element(8, Insert), erlang:element(9, Insert)}. -file("src/cake/insert.gleam", 531). ?DOC(" Get the table name to insert into from an `Insert` query.\n"). -spec get_table(cake@internal@write_query:insert(any())) -> cake@internal@write_query:insert_into_table(). get_table(Insert) -> erlang:element(2, Insert). -file("src/cake/insert.gleam", 539). ?DOC(" Specify a modifier for the `INSERT` query.\n"). -spec modifier(cake@internal@write_query:insert(FQD), binary()) -> cake@internal@write_query:insert(FQD). modifier(Insert, Modifier) -> Modifier@1 = begin _pipe = Modifier, gleam@string:trim(_pipe) end, case Modifier@1 of <<""/utf8>> -> {insert, erlang:element(2, Insert), erlang:element(3, Insert), no_insert_modifier, erlang:element(5, Insert), erlang:element(6, Insert), erlang:element(7, Insert), erlang:element(8, Insert), erlang:element(9, Insert)}; _ -> {insert, erlang:element(2, Insert), erlang:element(3, Insert), begin _pipe@1 = Modifier@1, {insert_modifier, _pipe@1} end, erlang:element(5, Insert), erlang:element(6, Insert), erlang:element(7, Insert), erlang:element(8, Insert), erlang:element(9, Insert)} end. -file("src/cake/insert.gleam", 552). ?DOC(" Specify that no modifier should be used for the given `INSERT` query.\n"). -spec no_modifier(cake@internal@write_query:insert(FQG)) -> cake@internal@write_query:insert(FQG). no_modifier(Insert) -> {insert, erlang:element(2, Insert), erlang:element(3, Insert), no_insert_modifier, erlang:element(5, Insert), erlang:element(6, Insert), erlang:element(7, Insert), erlang:element(8, Insert), erlang:element(9, Insert)}. -file("src/cake/insert.gleam", 558). ?DOC(" Get the modifier from an `Insert` query.\n"). -spec get_modifier(cake@internal@write_query:insert(any())) -> binary(). get_modifier(Insert) -> case erlang:element(4, Insert) of no_insert_modifier -> <<""/utf8>>; {insert_modifier, Keyword} -> Keyword end. -file("src/cake/insert.gleam", 569). ?DOC(" Specify the source records to insert.\n"). -spec source_records( cake@internal@write_query:insert(FQL), list(FQL), fun((FQL) -> cake@internal@write_query:insert_row()) ) -> cake@internal@write_query:insert(FQL). source_records(Insert, Records, Encoder) -> {insert, erlang:element(2, Insert), erlang:element(3, Insert), erlang:element(4, Insert), begin _pipe = Records, {insert_source_records, _pipe, Encoder} end, erlang:element(6, Insert), erlang:element(7, Insert), erlang:element(8, Insert), erlang:element(9, Insert)}. -file("src/cake/insert.gleam", 579). ?DOC(" Specify the source values to insert.\n"). -spec source_values( cake@internal@write_query:insert(FQP), list(cake@internal@write_query:insert_row()) ) -> cake@internal@write_query:insert(FQP). source_values(Insert, Rows) -> {insert, erlang:element(2, Insert), erlang:element(3, Insert), erlang:element(4, Insert), begin _pipe = Rows, {insert_source_rows, _pipe} end, erlang:element(6, Insert), erlang:element(7, Insert), erlang:element(8, Insert), erlang:element(9, Insert)}. -file("src/cake/insert.gleam", 589). ?DOC( " Get the source from an `Insert` query which is either a list of records,\n" " accompanied by an encoder function or a list of `InsertRow`s.\n" ). -spec get_source(cake@internal@write_query:insert(FQT)) -> cake@internal@write_query:insert_source(FQT). get_source(Insert) -> erlang:element(5, Insert). -file("src/cake/insert.gleam", 600). ?DOC( " Specify the columns to insert into.\n" "\n" " NOTICE: You have to specify the columns and ensure their names are\n" " correct, as well as their count which must be equal to the count of\n" " `InsertRows` the encoder function returns or is given as source\n" " values.\n" ). -spec columns(cake@internal@write_query:insert(FQW), list(binary())) -> cake@internal@write_query:insert(FQW). columns(Insert, Columns) -> {insert, erlang:element(2, Insert), begin _pipe = Columns, {insert_columns, _pipe} end, erlang:element(4, Insert), erlang:element(5, Insert), erlang:element(6, Insert), erlang:element(7, Insert), erlang:element(8, Insert), erlang:element(9, Insert)}. -file("src/cake/insert.gleam", 609). ?DOC(" Get the columns to insert into from an `Insert` query.\n"). -spec get_columns(cake@internal@write_query:insert(any())) -> cake@internal@write_query:insert_columns(). get_columns(Insert) -> erlang:element(3, Insert). -file("src/cake/insert.gleam", 619). ?DOC( " This specifies that any conflicts result in the query to fail\n" "\n" " This is the default behaviour.\n" ). -spec on_conflict_error(cake@internal@write_query:insert(FRC)) -> cake@internal@write_query:insert(FRC). on_conflict_error(Insert) -> {insert, erlang:element(2, Insert), erlang:element(3, Insert), erlang:element(4, Insert), erlang:element(5, Insert), insert_conflict_error, erlang:element(7, Insert), erlang:element(8, Insert), erlang:element(9, Insert)}. -file("src/cake/insert.gleam", 628). ?DOC( " This specifies that specific conflicts do not result in an error but instead\n" " are just ignored and not inserted.\n" "\n" " Conflict Target: Columns\n" ). -spec on_columns_conflict_ignore( cake@internal@write_query:insert(FRF), list(binary()), cake@internal@read_query:where() ) -> cake@internal@write_query:insert(FRF). on_columns_conflict_ignore(Insert, Columns, Where) -> {insert, erlang:element(2, Insert), erlang:element(3, Insert), erlang:element(4, Insert), erlang:element(5, Insert), {insert_conflict_ignore, begin _pipe = Columns, {insert_conflict_target, _pipe} end, Where}, erlang:element(7, Insert), erlang:element(8, Insert), erlang:element(9, Insert)}. -file("src/cake/insert.gleam", 647). ?DOC( " This specifies that specific conflicts do not result in an error but instead\n" " are just ignored and not inserted.\n" "\n" " Conflict Target: Constraint\n" ). -spec on_constraint_conflict_ignore( cake@internal@write_query:insert(FRJ), binary(), cake@internal@read_query:where() ) -> cake@internal@write_query:insert(FRJ). on_constraint_conflict_ignore(Insert, Constraint, Where) -> {insert, erlang:element(2, Insert), erlang:element(3, Insert), erlang:element(4, Insert), erlang:element(5, Insert), {insert_conflict_ignore, begin _pipe = Constraint, {insert_conflict_target_constraint, _pipe} end, Where}, erlang:element(7, Insert), erlang:element(8, Insert), erlang:element(9, Insert)}. -file("src/cake/insert.gleam", 683). ?DOC( " Inserts or updates on conflict, also called ´UPSERT´.\n" "\n" " This function generates PostgreSQL/SQLite-specific upsert queries using\n" " `ON CONFLICT ... DO UPDATE` syntax.\n" "\n" " **For MySQL/MariaDB, use `on_duplicate_key_update()` instead.**\n" "\n" " Conflict Target: Columns\n" "\n" " ## Important\n" "\n" " - Use `excluded.column` in UPDATE expressions to reference insert values\n" " - Explicitly specify which columns to check for conflicts\n" " - Supports optional WHERE clause for conditional updates\n" "\n" " ## Database Support\n" "\n" " - **🐘PostgreSQL**: ✅ Fully supported\n" " - **🪶SQLite**: ✅ Fully supported\n" " - **🦭MariaDB**: ❌ Not supported - use `on_duplicate_key_update()`\n" " - **🐬MySQL**: ❌ Not supported - use `on_duplicate_key_update()`\n" ). -spec on_columns_conflict_update( cake@internal@write_query:insert(FRM), list(binary()), cake@internal@read_query:where(), cake@internal@write_query:update(FRM) ) -> cake@internal@write_query:insert(FRM). on_columns_conflict_update(Insert, Columns, Where, Update) -> {insert, erlang:element(2, Insert), erlang:element(3, Insert), erlang:element(4, Insert), erlang:element(5, Insert), {insert_conflict_update, begin _pipe = Columns, {insert_conflict_target, _pipe} end, Where, Update}, erlang:element(7, Insert), erlang:element(8, Insert), erlang:element(9, Insert)}. -file("src/cake/insert.gleam", 716). ?DOC( " Inserts or updates on conflict, also called ´UPSERT´.\n" "\n" " This function generates PostgreSQL-specific upsert queries using\n" " `ON CONFLICT ON CONSTRAINT ... DO UPDATE` syntax.\n" "\n" " **For MySQL/MariaDB, use `on_duplicate_key_update()` instead.**\n" " **For SQLite, use `on_columns_conflict_update()` instead.**\n" "\n" " Conflict Target: Named Constraint\n" "\n" " ## Database Support\n" "\n" " - **🐘PostgreSQL**: ✅ Fully supported\n" " - **🪶SQLite**: ❌ Not supported - use `on_columns_conflict_update()`\n" " - **🦭MariaDB**: ❌ Not supported - use `on_duplicate_key_update()`\n" " - **🐬MySQL**: ❌ Not supported - use `on_duplicate_key_update()`\n" ). -spec on_constraint_conflict_update( cake@internal@write_query:insert(FRR), binary(), cake@internal@read_query:where(), cake@internal@write_query:update(FRR) ) -> cake@internal@write_query:insert(FRR). on_constraint_conflict_update(Insert, Constraint, Where, Update) -> {insert, erlang:element(2, Insert), erlang:element(3, Insert), erlang:element(4, Insert), erlang:element(5, Insert), {insert_conflict_update, begin _pipe = Constraint, {insert_conflict_target_constraint, _pipe} end, Where, Update}, erlang:element(7, Insert), erlang:element(8, Insert), erlang:element(9, Insert)}. -file("src/cake/insert.gleam", 734). ?DOC(" Get the conflict strategy from an `Insert` query.\n"). -spec get_on_conflict(cake@internal@write_query:insert(FRV)) -> cake@internal@write_query:insert_conflict_strategy(FRV). get_on_conflict(Insert) -> erlang:element(6, Insert). -file("src/cake/insert.gleam", 781). ?DOC( " MySQL/MariaDB upsert using `ON DUPLICATE KEY UPDATE` syntax.\n" "\n" " This function generates MySQL/MariaDB-specific upsert queries.\n" " **Only use this when targeting MySQL or MariaDB databases.**\n" "\n" " For PostgreSQL/SQLite, use `on_columns_conflict_update()` or\n" " `on_constraint_conflict_update()` instead.\n" "\n" " ## Important\n" "\n" " - Use `VALUES(column)` (not `excluded.column`) in your UPDATE expressions\n" " - Updates occur on the **first** matched unique/primary key constraint\n" " - No explicit conflict target - relies on existing indexes\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import cake/insert as i\n" " import cake/update as u\n" "\n" " [[i.string(\"user1\"), i.int(100)] |> i.row]\n" " |> i.from_values(table_name: \"scores\", columns: [\"username\", \"score\"])\n" " |> i.on_duplicate_key_update(\n" " update: u.new()\n" " |> u.set(\"score\" |> u.set_expression(\"VALUES(score) + scores.score\")),\n" " )\n" " ```\n" "\n" " Generates:\n" " ```sql\n" " INSERT INTO scores (username, score) VALUES (?, ?)\n" " ON DUPLICATE KEY UPDATE score = VALUES(score) + scores.score\n" " ```\n" "\n" " ## Database Support\n" "\n" " - **🦭MariaDB**: ✅ Supported\n" " - **🐬MySQL**: ✅ Supported\n" " - **🐘PostgreSQL**: ❌ Not supported - use `on_columns_conflict_update()`\n" " - **🪶SQLite**: ❌ Not supported - use `on_columns_conflict_update()`\n" ). -spec on_duplicate_key_update( cake@internal@write_query:insert(FRY), cake@internal@write_query:update(FRY) ) -> cake@internal@write_query:insert(FRY). on_duplicate_key_update(Insert, Update) -> {insert, erlang:element(2, Insert), erlang:element(3, Insert), erlang:element(4, Insert), erlang:element(5, Insert), {insert_duplicate_key_update, Update}, erlang:element(7, Insert), erlang:element(8, Insert), erlang:element(9, Insert)}. -file("src/cake/insert.gleam", 792). ?DOC(" Specify the columns to return after the `INSERT` query.\n"). -spec returning(cake@internal@write_query:insert(FSC), list(binary())) -> cake@internal@write_query:insert(FSC). returning(Insert, Returning) -> case Returning of [] -> {insert, erlang:element(2, Insert), erlang:element(3, Insert), erlang:element(4, Insert), erlang:element(5, Insert), erlang:element(6, Insert), no_returning, erlang:element(8, Insert), erlang:element(9, Insert)}; _ -> {insert, erlang:element(2, Insert), erlang:element(3, Insert), erlang:element(4, Insert), erlang:element(5, Insert), erlang:element(6, Insert), begin _pipe = Returning, {returning, _pipe} end, erlang:element(8, Insert), erlang:element(9, Insert)} end. -file("src/cake/insert.gleam", 804). ?DOC(" Specify that no columns should be returned after the `INSERT` query.\n"). -spec no_returning(cake@internal@write_query:insert(FSG)) -> cake@internal@write_query:insert(FSG). no_returning(Insert) -> {insert, erlang:element(2, Insert), erlang:element(3, Insert), erlang:element(4, Insert), erlang:element(5, Insert), erlang:element(6, Insert), no_returning, erlang:element(8, Insert), erlang:element(9, Insert)}. -file("src/cake/insert.gleam", 812). ?DOC(" Specify an epilog for the `INSERT` query.\n"). -spec epilog(cake@internal@write_query:insert(FSJ), binary()) -> cake@internal@write_query:insert(FSJ). epilog(Insert, Epilog) -> Epilog@1 = begin _pipe = Epilog, gleam@string:trim(_pipe) end, case Epilog@1 of <<""/utf8>> -> {insert, erlang:element(2, Insert), erlang:element(3, Insert), erlang:element(4, Insert), erlang:element(5, Insert), erlang:element(6, Insert), erlang:element(7, Insert), no_epilog, erlang:element(9, Insert)}; _ -> {insert, erlang:element(2, Insert), erlang:element(3, Insert), erlang:element(4, Insert), erlang:element(5, Insert), erlang:element(6, Insert), erlang:element(7, Insert), begin _pipe@1 = (<<" "/utf8, Epilog@1/binary>>), {epilog, _pipe@1} end, erlang:element(9, Insert)} end. -file("src/cake/insert.gleam", 822). ?DOC(" Specify that no epilog should be added to the `INSERT` query.\n"). -spec no_epilog(cake@internal@write_query:insert(FSM)) -> cake@internal@write_query:insert(FSM). no_epilog(Insert) -> {insert, erlang:element(2, Insert), erlang:element(3, Insert), erlang:element(4, Insert), erlang:element(5, Insert), erlang:element(6, Insert), erlang:element(7, Insert), no_epilog, erlang:element(9, Insert)}. -file("src/cake/insert.gleam", 828). ?DOC(" Get the epilog from an `INSERT` query.\n"). -spec get_epilog(cake@internal@write_query:insert(any())) -> cake@internal@read_query:epilog(). get_epilog(Insert) -> erlang:element(8, Insert). -file("src/cake/insert.gleam", 836). ?DOC(" Specify a comment for the `INSERT` query.\n"). -spec comment(cake@internal@write_query:insert(FSR), binary()) -> cake@internal@write_query:insert(FSR). comment(Insert, Comment) -> Comment@1 = begin _pipe = Comment, gleam@string:trim(_pipe) end, case Comment@1 of <<""/utf8>> -> {insert, erlang:element(2, Insert), erlang:element(3, Insert), erlang:element(4, Insert), erlang:element(5, Insert), erlang:element(6, Insert), erlang:element(7, Insert), erlang:element(8, Insert), no_comment}; _ -> {insert, erlang:element(2, Insert), erlang:element(3, Insert), erlang:element(4, Insert), erlang:element(5, Insert), erlang:element(6, Insert), erlang:element(7, Insert), erlang:element(8, Insert), begin _pipe@1 = (<<" "/utf8, Comment@1/binary>>), {comment, _pipe@1} end} end. -file("src/cake/insert.gleam", 846). ?DOC(" Specify that no comment should be added to the `INSERT` query.\n"). -spec no_comment(cake@internal@write_query:insert(FSU)) -> cake@internal@write_query:insert(FSU). no_comment(Insert) -> {insert, erlang:element(2, Insert), erlang:element(3, Insert), erlang:element(4, Insert), erlang:element(5, Insert), erlang:element(6, Insert), erlang:element(7, Insert), erlang:element(8, Insert), no_comment}. -file("src/cake/insert.gleam", 852). ?DOC(" Get the comment from an `INSERT` query.\n"). -spec get_comment(cake@internal@write_query:insert(any())) -> cake@internal@read_query:comment(). get_comment(Insert) -> erlang:element(9, Insert).