-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).