-module(based@sql). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/based/sql.gleam"). -export(['query'/1, params/2, table/1, table_as/2, column/1, count/1, sum/1, avg/1, max/1, min/1, column_for/2, column_as/2, adapter/0, on_placeholder/2, on_value/2, on_identifier/2, on_null/2, on_int/2, on_text/2, value/3, rows/1, list/1, inner_join/3, left_join/3, right_join/3, full_join/3, asc/1, desc/1, eq/3, not_eq/3, gt/3, lt/3, gt_eq/3, lt_eq/3, between/4, like/3, not_like/3, in/3, is_null/1, is_not_null/1, is_true/1, is_false/1, 'or'/2, 'and'/2, 'not'/1, exists/1, raw/1, from/1, select/2, insert/1, update/2, delete/1, from_subquery/2, where/2, returning/2, order_by/2, group_by/2, limit/2, offset/2, distinct/1, having/2, for_update/1, values/2, on_conflict/4, set/3, cte/2, cte_columns/2, with/2, recursive/1, union/1, union_all/1, to_query/2, to_string/2]). -export_type(['query'/1, table/0, aggregate/0, column/0, adapter/1, rows/2, operand/1, condition/1, join/1, order/0, conflict_action/0, on_conflict/1, kind/2, select/0, insert/0, update/0, delete/0, subquery/0, union/0, union_all/0, union_type/0, from/2, table_or_subquery/1, select_query/1, insert_query/1, update_query/1, delete_query/1, union_query/1, builder/2, cte/1, set/1, sql_builder/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 type-safe SQL query builder for Gleam.\n" "\n" " Queries are built using a pipeline API that starts with a table source and\n" " chains modifiers to construct SELECT, INSERT, UPDATE, and DELETE statements.\n" " Phantom types ensure that only valid modifiers can be applied to each query\n" " kind at compile time.\n" "\n" " ## Quick example\n" "\n" " ```gleam\n" " import based/sql\n" "\n" " let adapter = sql.adapter()\n" "\n" " let query =\n" " sql.from(sql.table(\"users\"))\n" " |> sql.select([sql.column(\"name\"), sql.column(\"email\")])\n" " |> sql.where([sql.column(\"active\") |> sql.is_true()])\n" " |> sql.order_by([sql.asc(sql.column(\"name\"))])\n" " |> sql.limit(10)\n" " |> sql.to_query(adapter)\n" "\n" " query.sql\n" " // -> \"SELECT name, email FROM users WHERE active IS TRUE ORDER BY name ASC LIMIT 10\"\n" "\n" " query.values\n" " // -> []\n" " ```\n" "\n" " ## Custom adapters\n" "\n" " Use `adapter()` with builder functions to configure how queries are\n" " rendered for a specific database backend. This controls placeholder style,\n" " identifier quoting, and value type mapping.\n" "\n" " ```gleam\n" " let mysql_adapter =\n" " sql.adapter()\n" " |> sql.on_null(fn() { mysql.null })\n" " |> sql.on_int(fn(i) { mysql.int(i) })\n" " |> sql.on_text(fn(s) { mysql.text(s) })\n" " |> sql.on_placeholder(fn(_) { \"?\" })\n" " |> sql.on_value(mysql_value_to_string)\n" " |> sql.on_identifier(fn(name) { \"`\" <> name <> \"`\" })\n" " ```\n" "\n" " ## Phantom types\n" "\n" " The `Builder(kind, v)` type uses phantom types to restrict which modifier\n" " functions can be called. For example, `join` only accepts `Builder(Select, v)`,\n" " and `set` only accepts `Builder(Update, v)`. This helps callers avoid\n" " building invalid SQL queries. It is possible to call functions that do\n" " not modify the provided `Builder`. Passing `Builder(Insert, v)`\n" " to `sql.where` will not modify the query builder.\n" "\n" ). -type 'query'(DKX) :: {'query', binary(), list(DKX)}. -opaque table() :: {table, binary(), gleam@option:option(binary())}. -type aggregate() :: count | sum | avg | max | min. -opaque column() :: {column, gleam@option:option(table()), binary(), gleam@option:option(binary()), gleam@option:option(aggregate())} | {all, gleam@option:option(table())}. -opaque adapter(DKY) :: {adapter, fun((integer()) -> binary()), fun((DKY) -> binary()), fun((binary()) -> binary()), fun(() -> DKY), fun((integer()) -> DKY), fun((binary()) -> DKY)}. -opaque rows(DKZ, DLA) :: {rows, list(binary()), list(fun((DKZ) -> DLA)), list(DKZ)}. -type operand(DLB) :: {column_ref, column()} | {value_ref, DLB} | null_ref | {sub_query, builder(select(), DLB)} | {any_query, builder(select(), DLB)} | {all_query, builder(select(), DLB)}. -opaque condition(DLC) :: {equal, operand(DLC), operand(DLC)} | {not_equal, operand(DLC), operand(DLC)} | {greater_than, operand(DLC), operand(DLC)} | {less_than, operand(DLC), operand(DLC)} | {greater_than_or_equal, operand(DLC), operand(DLC)} | {less_than_or_equal, operand(DLC), operand(DLC)} | {between, operand(DLC), operand(DLC), operand(DLC)} | {like, operand(DLC), operand(DLC)} | {not_like, operand(DLC), operand(DLC)} | {in, operand(DLC), list(operand(DLC))} | {is_null, operand(DLC)} | {is_not_null, operand(DLC)} | {is_true, operand(DLC)} | {is_false, operand(DLC)} | {'and', condition(DLC), condition(DLC)} | {'or', condition(DLC), condition(DLC)} | {'not', condition(DLC)} | {exists, builder(select(), DLC)} | {raw, binary()}. -type join(DLD) :: {inner_join, table(), list(condition(DLD))} | {left_join, table(), list(condition(DLD))} | {right_join, table(), list(condition(DLD))} | {full_join, table(), list(condition(DLD))}. -opaque order() :: {asc, column()} | {desc, column()}. -type conflict_action() :: do_nothing | {do_update, list({binary(), binary()})}. -type on_conflict(DLE) :: {on_conflict, binary(), conflict_action(), list(condition(DLE))}. -opaque kind(DLF, DLG) :: {kind, fun((DLF) -> operand(DLG))}. -type select() :: any(). -type insert() :: any(). -type update() :: any(). -type delete() :: any(). -type subquery() :: any(). -type union() :: any(). -type union_all() :: any(). -type union_type() :: union | union_all. -opaque from(DLH, DLI) :: {from_table, table()} | {from_sub_query, builder(select(), DLI), binary()} | {gleam_phantom, DLH}. -type table_or_subquery(DLJ) :: {select_from_table, table()} | {select_from_sub_query, builder(select(), DLJ), binary()}. -type select_query(DLK) :: {select_query, list(column()), table_or_subquery(DLK), list(list(condition(DLK))), list(join(DLK)), list(order()), gleam@option:option(integer()), gleam@option:option(integer()), list(column()), boolean(), list(list(condition(DLK))), boolean()}. -type insert_query(DLL) :: {insert_query, table(), list(binary()), list(list(DLL)), list(column()), gleam@option:option(on_conflict(DLL))}. -type update_query(DLM) :: {update_query, table(), list(set(DLM)), list(list(condition(DLM))), list(column()), list(order()), gleam@option:option(integer()), gleam@option:option(integer())}. -type delete_query(DLN) :: {delete_query, table(), list(list(condition(DLN))), list(column())}. -type union_query(DLO) :: {union_query, list(builder(select(), DLO)), union_type()}. -opaque builder(DLP, DLQ) :: {select_builder, select_query(DLQ), list(cte(DLQ)), boolean()} | {insert_builder, insert_query(DLQ), list(cte(DLQ)), boolean()} | {update_builder, update_query(DLQ), list(cte(DLQ)), boolean()} | {delete_builder, delete_query(DLQ), list(cte(DLQ)), boolean()} | {union_builder, union_query(DLQ), list(cte(DLQ)), boolean()} | {gleam_phantom, DLP}. -opaque cte(DLR) :: {cte, binary(), list(binary()), fun((adapter(DLR)) -> sql_builder(DLR))}. -opaque set(DLS) :: {set, binary(), operand(DLS)}. -type sql_builder(DLT) :: {sql_builder, binary(), list(list(DLT))}. -file("src/based/sql.gleam", 81). ?DOC(" Creates a `Query` from a raw SQL string with no parameters.\n"). -spec 'query'(binary()) -> 'query'(any()). 'query'(Sql) -> {'query', Sql, []}. -file("src/based/sql.gleam", 86). ?DOC(" Sets the parameter values on a `Query`.\n"). -spec params('query'(DLW), list(DLW)) -> 'query'(DLW). params(Query, Values) -> {'query', erlang:element(2, Query), Values}. -file("src/based/sql.gleam", 96). ?DOC(" Creates a table reference.\n"). -spec table(binary()) -> table(). table(Name) -> {table, Name, none}. -file("src/based/sql.gleam", 101). ?DOC(" Sets an alias on a table.\n"). -spec table_as(table(), binary()) -> table(). table_as(Table, Alias) -> {table, erlang:element(2, Table), {some, Alias}}. -file("src/based/sql.gleam", 126). ?DOC(" Creates a plain column reference.\n"). -spec column(binary()) -> column(). column(Name) -> {column, none, Name, none, none}. -file("src/based/sql.gleam", 131). ?DOC(" Creates a column wrapped in `COUNT(...)`.\n"). -spec count(binary()) -> column(). count(Name) -> {column, none, Name, none, {some, count}}. -file("src/based/sql.gleam", 136). ?DOC(" Creates a column wrapped in `SUM(...)`.\n"). -spec sum(binary()) -> column(). sum(Name) -> {column, none, Name, none, {some, sum}}. -file("src/based/sql.gleam", 141). ?DOC(" Creates a column wrapped in `AVG(...)`.\n"). -spec avg(binary()) -> column(). avg(Name) -> {column, none, Name, none, {some, avg}}. -file("src/based/sql.gleam", 146). ?DOC(" Creates a column wrapped in `MAX(...)`.\n"). -spec max(binary()) -> column(). max(Name) -> {column, none, Name, none, {some, max}}. -file("src/based/sql.gleam", 151). ?DOC(" Creates a column wrapped in `MIN(...)`.\n"). -spec min(binary()) -> column(). min(Name) -> {column, none, Name, none, {some, min}}. -file("src/based/sql.gleam", 156). ?DOC(" Qualifies a column with a table name.\n"). -spec column_for(column(), table()) -> column(). column_for(Column, Table) -> case Column of {column, _, _, _, _} -> {column, {some, Table}, erlang:element(3, Column), erlang:element(4, Column), erlang:element(5, Column)}; {all, _} -> {all, {some, Table}} end. -file("src/based/sql.gleam", 164). ?DOC(" Sets an alias on a column. No-ops on `star`.\n"). -spec column_as(column(), binary()) -> column(). column_as(Column, Alias) -> case Column of {column, _, _, _, _} -> {column, erlang:element(2, Column), erlang:element(3, Column), {some, Alias}, erlang:element(5, Column)}; {all, _} -> Column end. -file("src/based/sql.gleam", 198). ?DOC( " Creates a new adapter with unconfigured value handlers.\n" "\n" " Defaults to `\"?\"` placeholders and does not quote identifiers.\n" " The `on_value`, `on_null`, `on_int`, and `on_text` handlers\n" " will panic if left unconfigured.\n" "\n" " Configure the returned adapter using the `on_*` builder functions\n" " before passing it to `to_query` or `to_string`.\n" ). -spec adapter() -> adapter(any()). adapter() -> {adapter, fun(_) -> <<"?"/utf8>> end, fun(_) -> erlang:error(#{gleam_error => panic, message => <<"sql.Adapter not configured (on_value)"/utf8>>, file => <>, module => <<"based/sql"/utf8>>, function => <<"adapter"/utf8>>, line => 201}) end, fun gleam@function:identity/1, fun() -> erlang:error(#{gleam_error => panic, message => <<"sql.Adapter not configured (on_null)"/utf8>>, file => <>, module => <<"based/sql"/utf8>>, function => <<"adapter"/utf8>>, line => 203}) end, fun(_) -> erlang:error(#{gleam_error => panic, message => <<"sql.Adapter not configured (on_int)"/utf8>>, file => <>, module => <<"based/sql"/utf8>>, function => <<"adapter"/utf8>>, line => 204}) end, fun(_) -> erlang:error(#{gleam_error => panic, message => <<"sql.Adapter not configured (on_text)"/utf8>>, file => <>, module => <<"based/sql"/utf8>>, function => <<"adapter"/utf8>>, line => 205}) end}. -file("src/based/sql.gleam", 210). ?DOC(" Sets the placeholder format function.\n"). -spec on_placeholder(adapter(DMC), fun((integer()) -> binary())) -> adapter(DMC). on_placeholder(Adapter, Handle_placeholder) -> {adapter, Handle_placeholder, erlang:element(3, Adapter), erlang:element(4, Adapter), erlang:element(5, Adapter), erlang:element(6, Adapter), erlang:element(7, Adapter)}. -file("src/based/sql.gleam", 218). ?DOC(" Sets the function used to render a value as a literal SQL string.\n"). -spec on_value(adapter(DMF), fun((DMF) -> binary())) -> adapter(DMF). on_value(Adapter, Handle_value) -> {adapter, erlang:element(2, Adapter), Handle_value, erlang:element(4, Adapter), erlang:element(5, Adapter), erlang:element(6, Adapter), erlang:element(7, Adapter)}. -file("src/based/sql.gleam", 226). ?DOC(" Sets the identifier quoting function.\n"). -spec on_identifier(adapter(DMI), fun((binary()) -> binary())) -> adapter(DMI). on_identifier(Adapter, Handle_identifier) -> {adapter, erlang:element(2, Adapter), erlang:element(3, Adapter), Handle_identifier, erlang:element(5, Adapter), erlang:element(6, Adapter), erlang:element(7, Adapter)}. -file("src/based/sql.gleam", 234). ?DOC(" Sets the function that produces the null representation for type `v`.\n"). -spec on_null(adapter(DML), fun(() -> DML)) -> adapter(DML). on_null(Adapter, Handle_null) -> {adapter, erlang:element(2, Adapter), erlang:element(3, Adapter), erlang:element(4, Adapter), Handle_null, erlang:element(6, Adapter), erlang:element(7, Adapter)}. -file("src/based/sql.gleam", 242). ?DOC( " Sets the function that wraps an `Int` into the value type `v`.\n" "\n" " Adapter packages use this to convert Gleam `Int` values into\n" " their value type `v`.\n" ). -spec on_int(adapter(DMO), fun((integer()) -> DMO)) -> adapter(DMO). on_int(Adapter, Handle_int) -> {adapter, erlang:element(2, Adapter), erlang:element(3, Adapter), erlang:element(4, Adapter), erlang:element(5, Adapter), Handle_int, erlang:element(7, Adapter)}. -file("src/based/sql.gleam", 250). ?DOC( " Sets the function that wraps a `String` into the value type `v`.\n" "\n" " Adapter packages use this to convert Gleam `String` values into\n" " their value type `v`.\n" ). -spec on_text(adapter(DMR), fun((binary()) -> DMR)) -> adapter(DMR). on_text(Adapter, Handle_text) -> {adapter, erlang:element(2, Adapter), erlang:element(3, Adapter), erlang:element(4, Adapter), erlang:element(5, Adapter), erlang:element(6, Adapter), Handle_text}. -file("src/based/sql.gleam", 278). ?DOC(" Adds a column to the rows being inserted, with a function to extract the SQL value.\n"). -spec value(rows(DMU, DMV), binary(), fun((DMU) -> DMV)) -> rows(DMU, DMV). value(Rows, Column, Extract) -> {rows, [Column | erlang:element(2, Rows)], [Extract | erlang:element(3, Rows)], erlang:element(4, Rows)}. -file("src/based/sql.gleam", 292). ?DOC( " Creates a new `Rows` with the given values. Pipe through `value` to add\n" " columns and extractors.\n" ). -spec rows(list(DNA)) -> rows(DNA, any()). rows(Values) -> {rows, [], [], Values}. -file("src/based/sql.gleam", 903). ?DOC( " Creates a kind that maps an arbitrary type to a value using a conversion\n" " function. Useful for `in` clauses with custom types.\n" ). -spec list(fun((DVH) -> DVI)) -> kind(DVH, DVI). list(Map) -> {kind, fun(X) -> {value_ref, Map(X)} end}. -file("src/based/sql.gleam", 375). -spec prepend_join(builder(select(), DOH), join(DOH)) -> builder(select(), DOH). prepend_join(Builder, J) -> case Builder of {select_builder, Query, Ctes, Recursive} -> Joins = gleam@list:prepend(erlang:element(5, Query), J), _pipe = {select_query, erlang:element(2, Query), erlang:element(3, Query), erlang:element(4, Query), Joins, erlang:element(6, Query), erlang:element(7, Query), erlang:element(8, Query), erlang:element(9, Query), erlang:element(10, Query), erlang:element(11, Query), erlang:element(12, Query)}, {select_builder, _pipe, Ctes, Recursive}; _ -> Builder end. -file("src/based/sql.gleam", 340). ?DOC(" Adds an `INNER JOIN` clause to a SELECT query.\n"). -spec inner_join(builder(select(), DNF), table(), list(condition(DNF))) -> builder(select(), DNF). inner_join(Builder, Table, On) -> prepend_join(Builder, {inner_join, Table, On}). -file("src/based/sql.gleam", 349). ?DOC(" Adds a `LEFT JOIN` clause to a SELECT query.\n"). -spec left_join(builder(select(), DNM), table(), list(condition(DNM))) -> builder(select(), DNM). left_join(Builder, Table, On) -> prepend_join(Builder, {left_join, Table, On}). -file("src/based/sql.gleam", 358). ?DOC(" Adds a `RIGHT JOIN` clause to a SELECT query.\n"). -spec right_join(builder(select(), DNT), table(), list(condition(DNT))) -> builder(select(), DNT). right_join(Builder, Table, On) -> prepend_join(Builder, {right_join, Table, On}). -file("src/based/sql.gleam", 367). ?DOC(" Adds a `FULL JOIN` clause to a SELECT query.\n"). -spec full_join(builder(select(), DOA), table(), list(condition(DOA))) -> builder(select(), DOA). full_join(Builder, Table, On) -> prepend_join(Builder, {full_join, Table, On}). -file("src/based/sql.gleam", 394). ?DOC(" Returns an ascending `Order` for the column.\n"). -spec asc(column()) -> order(). asc(Column) -> {asc, Column}. -file("src/based/sql.gleam", 399). ?DOC(" Returns a descending `Order` for the column.\n"). -spec desc(column()) -> order(). desc(Column) -> {desc, Column}. -file("src/based/sql.gleam", 538). ?DOC(" Creates an equality condition.\n"). -spec eq(column(), DON, kind(DON, DOO)) -> condition(DOO). eq(Column, Input, Kind) -> {equal, {column_ref, Column}, (erlang:element(2, Kind))(Input)}. -file("src/based/sql.gleam", 543). ?DOC(" Creates an inequality condition.\n"). -spec not_eq(column(), DOS, kind(DOS, DOT)) -> condition(DOT). not_eq(Column, Input, Kind) -> {not_equal, {column_ref, Column}, (erlang:element(2, Kind))(Input)}. -file("src/based/sql.gleam", 548). ?DOC(" Creates a greater-than condition.\n"). -spec gt(column(), DOX, kind(DOX, DOY)) -> condition(DOY). gt(Column, Input, Kind) -> {greater_than, {column_ref, Column}, (erlang:element(2, Kind))(Input)}. -file("src/based/sql.gleam", 553). ?DOC(" Creates a less-than condition.\n"). -spec lt(column(), DPC, kind(DPC, DPD)) -> condition(DPD). lt(Column, Input, Kind) -> {less_than, {column_ref, Column}, (erlang:element(2, Kind))(Input)}. -file("src/based/sql.gleam", 558). ?DOC(" Creates a greater-than-or-equal condition.\n"). -spec gt_eq(column(), DPH, kind(DPH, DPI)) -> condition(DPI). gt_eq(Column, Input, Kind) -> {greater_than_or_equal, {column_ref, Column}, (erlang:element(2, Kind))(Input)}. -file("src/based/sql.gleam", 563). ?DOC(" Creates a less-than-or-equal condition.\n"). -spec lt_eq(column(), DPM, kind(DPM, DPN)) -> condition(DPN). lt_eq(Column, Input, Kind) -> {less_than_or_equal, {column_ref, Column}, (erlang:element(2, Kind))(Input)}. -file("src/based/sql.gleam", 568). ?DOC(" Creates a BETWEEN condition.\n"). -spec between(column(), DPR, DPR, kind(DPR, DPS)) -> condition(DPS). between(Column, Low, High, Kind) -> {between, {column_ref, Column}, (erlang:element(2, Kind))(Low), (erlang:element(2, Kind))(High)}. -file("src/based/sql.gleam", 578). ?DOC(" Creates a LIKE condition.\n"). -spec like(column(), DPW, kind(DPW, DPX)) -> condition(DPX). like(Column, Input, Kind) -> {like, {column_ref, Column}, (erlang:element(2, Kind))(Input)}. -file("src/based/sql.gleam", 583). ?DOC(" Creates a NOT LIKE condition.\n"). -spec not_like(column(), DQB, kind(DQB, DQC)) -> condition(DQC). not_like(Column, Input, Kind) -> {not_like, {column_ref, Column}, (erlang:element(2, Kind))(Input)}. -file("src/based/sql.gleam", 588). ?DOC(" Creates an IN condition.\n"). -spec in(column(), list(DQG), kind(DQG, DQI)) -> condition(DQI). in(Column, Values, Kind) -> {in, {column_ref, Column}, gleam@list:map(Values, erlang:element(2, Kind))}. -file("src/based/sql.gleam", 593). ?DOC(" Creates an IS NULL condition.\n"). -spec is_null(column()) -> condition(any()). is_null(Column) -> {is_null, {column_ref, Column}}. -file("src/based/sql.gleam", 598). ?DOC(" Creates an IS NOT NULL condition.\n"). -spec is_not_null(column()) -> condition(any()). is_not_null(Column) -> {is_not_null, {column_ref, Column}}. -file("src/based/sql.gleam", 603). ?DOC(" Creates an IS TRUE condition.\n"). -spec is_true(column()) -> condition(any()). is_true(Column) -> {is_true, {column_ref, Column}}. -file("src/based/sql.gleam", 608). ?DOC(" Creates an IS FALSE condition.\n"). -spec is_false(column()) -> condition(any()). is_false(Column) -> {is_false, {column_ref, Column}}. -file("src/based/sql.gleam", 613). ?DOC(" Combines two conditions with OR.\n"). -spec 'or'(condition(DQU), condition(DQU)) -> condition(DQU). 'or'(Left, Right) -> {'or', Left, Right}. -file("src/based/sql.gleam", 618). ?DOC(" Combines two conditions with AND.\n"). -spec 'and'(condition(DQY), condition(DQY)) -> condition(DQY). 'and'(Left, Right) -> {'and', Left, Right}. -file("src/based/sql.gleam", 623). ?DOC(" Negates a condition.\n"). -spec 'not'(condition(DRC)) -> condition(DRC). 'not'(Condition) -> {'not', Condition}. -file("src/based/sql.gleam", 628). ?DOC(" Creates an EXISTS condition.\n"). -spec exists(builder(select(), DRF)) -> condition(DRF). exists(Builder) -> {exists, Builder}. -file("src/based/sql.gleam", 638). ?DOC( " Creates a raw SQL condition.\n" "\n" " **Warning:** The given SQL string is embedded directly in the query\n" " without any escaping or parameterization. Never pass untrusted user\n" " input to this function — doing so may expose your application to SQL\n" " injection attacks.\n" ). -spec raw(binary()) -> condition(any()). raw(Sql) -> {raw, Sql}. -file("src/based/sql.gleam", 646). ?DOC( " Starts building a query from a table. This is the entry point for SELECT\n" " and DELETE queries.\n" "\n" " Pass into `select` or `delete` to choose the query kind.\n" ). -spec from(table()) -> from(table(), any()). from(Table) -> {from_table, Table}. -file("src/based/sql.gleam", 651). ?DOC(" Converts a `From` into a SELECT query with the given columns.\n"). -spec select(from(any(), DRP), list(column())) -> builder(select(), DRP). select(From, Columns) -> From@1 = case From of {from_table, Table} -> {select_from_table, Table}; {from_sub_query, Builder, Alias} -> {select_from_sub_query, Builder, Alias} end, _pipe = {select_query, Columns, From@1, [], [], [], none, none, [], false, [], false}, {select_builder, _pipe, [], false}. -file("src/based/sql.gleam", 674). ?DOC(" Creates a new INSERT query builder for the given table.\n"). -spec insert(table()) -> builder(insert(), any()). insert(Tbl) -> _pipe = {insert_query, Tbl, [], [], [], none}, {insert_builder, _pipe, [], false}. -file("src/based/sql.gleam", 686). ?DOC(" Creates a new UPDATE query builder for the given table.\n"). -spec update(table(), list(set(DRY))) -> builder(update(), DRY). update(Tbl, Sets) -> _pipe = {update_query, Tbl, Sets, [], [], [], none, none}, {update_builder, _pipe, [], false}. -file("src/based/sql.gleam", 700). ?DOC(" Converts a `From` into a DELETE query.\n"). -spec delete(from(table(), DSD)) -> builder(delete(), DSD). delete(From) -> case From of {from_table, Table} -> _pipe = {delete_query, Table, [], []}, {delete_builder, _pipe, [], false}; _ -> erlang:error(#{gleam_error => panic, message => <<"unreachable: delete requires FromTable"/utf8>>, file => <>, module => <<"based/sql"/utf8>>, function => <<"delete"/utf8>>, line => 706}) end. -file("src/based/sql.gleam", 711). ?DOC(" Creates a `From` that selects from a subquery instead of a table.\n"). -spec from_subquery(builder(select(), DSI), binary()) -> from(subquery(), DSI). from_subquery(Builder, Alias) -> {from_sub_query, Builder, Alias}. -file("src/based/sql.gleam", 721). ?DOC( " Adds a WHERE condition to the query.\n" "\n" " Applies to SELECT, UPDATE, and DELETE queries. No-ops on other builder types.\n" ). -spec where(builder(DSN, DSO), list(condition(DSO))) -> builder(DSN, DSO). where(Builder, Conditions) -> case Builder of {select_builder, Query, Ctes, Recursive} -> _pipe = {select_query, erlang:element(2, Query), erlang:element(3, Query), gleam@list:prepend(erlang:element(4, Query), Conditions), erlang:element(5, Query), erlang:element(6, Query), erlang:element(7, Query), erlang:element(8, Query), erlang:element(9, Query), erlang:element(10, Query), erlang:element(11, Query), erlang:element(12, Query)}, {select_builder, _pipe, Ctes, Recursive}; {update_builder, Query@1, Ctes@1, Recursive@1} -> _pipe@1 = {update_query, erlang:element(2, Query@1), erlang:element(3, Query@1), gleam@list:prepend(erlang:element(4, Query@1), Conditions), erlang:element(5, Query@1), erlang:element(6, Query@1), erlang:element(7, Query@1), erlang:element(8, Query@1)}, {update_builder, _pipe@1, Ctes@1, Recursive@1}; {delete_builder, Query@2, Ctes@2, Recursive@2} -> _pipe@2 = {delete_query, erlang:element(2, Query@2), gleam@list:prepend(erlang:element(3, Query@2), Conditions), erlang:element(4, Query@2)}, {delete_builder, _pipe@2, Ctes@2, Recursive@2}; _ -> Builder end. -file("src/based/sql.gleam", 740). ?DOC(" Adds a RETURNING clause. Applies to INSERT, UPDATE, and DELETE queries.\n"). -spec returning(builder(DSV, DSW), list(column())) -> builder(DSV, DSW). returning(Builder, Columns) -> case Builder of {insert_builder, Query, Ctes, Recursive} -> _pipe = {insert_query, erlang:element(2, Query), erlang:element(3, Query), erlang:element(4, Query), Columns, erlang:element(6, Query)}, {insert_builder, _pipe, Ctes, Recursive}; {update_builder, Query@1, Ctes@1, Recursive@1} -> _pipe@1 = {update_query, erlang:element(2, Query@1), erlang:element(3, Query@1), erlang:element(4, Query@1), Columns, erlang:element(6, Query@1), erlang:element(7, Query@1), erlang:element(8, Query@1)}, {update_builder, _pipe@1, Ctes@1, Recursive@1}; {delete_builder, Query@2, Ctes@2, Recursive@2} -> _pipe@2 = {delete_query, erlang:element(2, Query@2), erlang:element(3, Query@2), Columns}, {delete_builder, _pipe@2, Ctes@2, Recursive@2}; _ -> Builder end. -file("src/based/sql.gleam", 756). ?DOC(" Sets the ORDER BY clause. Applies to SELECT and UPDATE queries.\n"). -spec order_by(builder(DTC, DTD), list(order())) -> builder(DTC, DTD). order_by(Builder, Order_by) -> case Builder of {select_builder, Query, Ctes, Recursive} -> _pipe = {select_query, erlang:element(2, Query), erlang:element(3, Query), erlang:element(4, Query), erlang:element(5, Query), Order_by, erlang:element(7, Query), erlang:element(8, Query), erlang:element(9, Query), erlang:element(10, Query), erlang:element(11, Query), erlang:element(12, Query)}, {select_builder, _pipe, Ctes, Recursive}; {update_builder, Query@1, Ctes@1, Recursive@1} -> _pipe@1 = {update_query, erlang:element(2, Query@1), erlang:element(3, Query@1), erlang:element(4, Query@1), erlang:element(5, Query@1), Order_by, erlang:element(7, Query@1), erlang:element(8, Query@1)}, {update_builder, _pipe@1, Ctes@1, Recursive@1}; _ -> Builder end. -file("src/based/sql.gleam", 769). ?DOC(" Adds a GROUP BY clause to a SELECT query.\n"). -spec group_by(builder(select(), DTJ), list(column())) -> builder(select(), DTJ). group_by(Builder, Columns) -> case Builder of {select_builder, Query, Ctes, Recursive} -> _pipe = {select_query, erlang:element(2, Query), erlang:element(3, Query), erlang:element(4, Query), erlang:element(5, Query), erlang:element(6, Query), erlang:element(7, Query), erlang:element(8, Query), lists:append(erlang:element(9, Query), Columns), erlang:element(10, Query), erlang:element(11, Query), erlang:element(12, Query)}, {select_builder, _pipe, Ctes, Recursive}; _ -> erlang:error(#{gleam_error => panic, message => <<"unreachable: group_by called on non-Select builder"/utf8>>, file => <>, module => <<"based/sql"/utf8>>, function => <<"group_by"/utf8>>, line => 777}) end. -file("src/based/sql.gleam", 782). ?DOC(" Adds a LIMIT clause. Applies to SELECT and UPDATE queries.\n"). -spec limit(builder(DTP, DTQ), integer()) -> builder(DTP, DTQ). limit(Builder, N) -> case Builder of {select_builder, Query, Ctes, Recursive} -> _pipe = {select_query, erlang:element(2, Query), erlang:element(3, Query), erlang:element(4, Query), erlang:element(5, Query), erlang:element(6, Query), {some, N}, erlang:element(8, Query), erlang:element(9, Query), erlang:element(10, Query), erlang:element(11, Query), erlang:element(12, Query)}, {select_builder, _pipe, Ctes, Recursive}; {update_builder, Query@1, Ctes@1, Recursive@1} -> _pipe@1 = {update_query, erlang:element(2, Query@1), erlang:element(3, Query@1), erlang:element(4, Query@1), erlang:element(5, Query@1), erlang:element(6, Query@1), {some, N}, erlang:element(8, Query@1)}, {update_builder, _pipe@1, Ctes@1, Recursive@1}; _ -> Builder end. -file("src/based/sql.gleam", 793). ?DOC(" Adds an OFFSET clause. Applies to SELECT and UPDATE queries.\n"). -spec offset(builder(DTV, DTW), integer()) -> builder(DTV, DTW). offset(Builder, N) -> case Builder of {select_builder, Query, Ctes, Recursive} -> _pipe = {select_query, erlang:element(2, Query), erlang:element(3, Query), erlang:element(4, Query), erlang:element(5, Query), erlang:element(6, Query), erlang:element(7, Query), {some, N}, erlang:element(9, Query), erlang:element(10, Query), erlang:element(11, Query), erlang:element(12, Query)}, {select_builder, _pipe, Ctes, Recursive}; {update_builder, Query@1, Ctes@1, Recursive@1} -> _pipe@1 = {update_query, erlang:element(2, Query@1), erlang:element(3, Query@1), erlang:element(4, Query@1), erlang:element(5, Query@1), erlang:element(6, Query@1), erlang:element(7, Query@1), {some, N}}, {update_builder, _pipe@1, Ctes@1, Recursive@1}; _ -> Builder end. -file("src/based/sql.gleam", 804). ?DOC(" Adds DISTINCT to a SELECT query.\n"). -spec distinct(builder(select(), DUB)) -> builder(select(), DUB). distinct(Builder) -> case Builder of {select_builder, Query, Ctes, Recursive} -> _pipe = {select_query, erlang:element(2, Query), erlang:element(3, Query), erlang:element(4, Query), erlang:element(5, Query), erlang:element(6, Query), erlang:element(7, Query), erlang:element(8, Query), erlang:element(9, Query), true, erlang:element(11, Query), erlang:element(12, Query)}, {select_builder, _pipe, Ctes, Recursive}; _ -> erlang:error(#{gleam_error => panic, message => <<"unreachable: distinct called on non-Select builder"/utf8>>, file => <>, module => <<"based/sql"/utf8>>, function => <<"distinct"/utf8>>, line => 808}) end. -file("src/based/sql.gleam", 813). ?DOC(" Adds a HAVING clause to a SELECT query.\n"). -spec having(builder(select(), DUG), list(condition(DUG))) -> builder(select(), DUG). having(Builder, Conditions) -> case Builder of {select_builder, Query, Ctes, Recursive} -> _pipe = {select_query, erlang:element(2, Query), erlang:element(3, Query), erlang:element(4, Query), erlang:element(5, Query), erlang:element(6, Query), erlang:element(7, Query), erlang:element(8, Query), erlang:element(9, Query), erlang:element(10, Query), gleam@list:prepend(erlang:element(11, Query), Conditions), erlang:element(12, Query)}, {select_builder, _pipe, Ctes, Recursive}; _ -> erlang:error(#{gleam_error => panic, message => <<"unreachable: having called on non-Select builder"/utf8>>, file => <>, module => <<"based/sql"/utf8>>, function => <<"having"/utf8>>, line => 821}) end. -file("src/based/sql.gleam", 826). ?DOC(" Adds `FOR UPDATE` to a SELECT query for row-level locking.\n"). -spec for_update(builder(select(), DUN)) -> builder(select(), DUN). for_update(Builder) -> case Builder of {select_builder, Query, Ctes, Recursive} -> _pipe = {select_query, erlang:element(2, Query), erlang:element(3, Query), erlang:element(4, Query), erlang:element(5, Query), erlang:element(6, Query), erlang:element(7, Query), erlang:element(8, Query), erlang:element(9, Query), erlang:element(10, Query), erlang:element(11, Query), true}, {select_builder, _pipe, Ctes, Recursive}; _ -> erlang:error(#{gleam_error => panic, message => <<"unreachable: for_update called on non-Select builder"/utf8>>, file => <>, module => <<"based/sql"/utf8>>, function => <<"for_update"/utf8>>, line => 830}) end. -file("src/based/sql.gleam", 835). ?DOC(" Sets the rows to be inserted.\n"). -spec values(builder(insert(), DUS), rows(any(), DUS)) -> builder(insert(), DUS). values(Builder, Rows) -> Columns = lists:reverse(erlang:element(2, Rows)), Extractors = lists:reverse(erlang:element(3, Rows)), Value_rows = begin _pipe = erlang:element(4, Rows), gleam@list:map(_pipe, fun(Item) -> _pipe@1 = Extractors, gleam@list:map(_pipe@1, fun(Extract) -> Extract(Item) end) end) end, case Builder of {insert_builder, Query, Ctes, Recursive} -> _pipe@2 = {insert_query, erlang:element(2, Query), Columns, Value_rows, erlang:element(5, Query), erlang:element(6, Query)}, {insert_builder, _pipe@2, Ctes, Recursive}; _ -> erlang:error(#{gleam_error => panic, message => <<"unreachable: values called on non-Insert builder"/utf8>>, file => <>, module => <<"based/sql"/utf8>>, function => <<"values"/utf8>>, line => 852}) end. -file("src/based/sql.gleam", 857). ?DOC(" Adds an ON CONFLICT clause to an INSERT query (upsert).\n"). -spec on_conflict( builder(insert(), DVA), binary(), conflict_action(), list(condition(DVA)) ) -> builder(insert(), DVA). on_conflict(Builder, Target, Action, Wheres) -> case Builder of {insert_builder, Query, Ctes, Recursive} -> _pipe = {insert_query, erlang:element(2, Query), erlang:element(3, Query), erlang:element(4, Query), erlang:element(5, Query), {some, {on_conflict, Target, Action, Wheres}}}, {insert_builder, _pipe, Ctes, Recursive}; _ -> erlang:error(#{gleam_error => panic, message => <<"unreachable: on_conflict called on non-Insert builder"/utf8>>, file => <>, module => <<"based/sql"/utf8>>, function => <<"on_conflict"/utf8>>, line => 874}) end. -file("src/based/sql.gleam", 912). ?DOC(" Sets a column to a value in an UPDATE query. Can be called multiple times.\n"). -spec set(binary(), DVL, kind(DVL, DVM)) -> set(DVM). set(Column, Input, Kind) -> {set, Column, (erlang:element(2, Kind))(Input)}. -file("src/based/sql.gleam", 1152). -spec append_for_update(sql_builder(DYW), boolean()) -> sql_builder(DYW). append_for_update(Builder, For_update) -> case For_update of true -> _pipe = erlang:element(2, Builder), _pipe@1 = based@internal@fmt:for_update(_pipe), {sql_builder, _pipe@1, erlang:element(3, Builder)}; false -> Builder end. -file("src/based/sql.gleam", 1138). -spec append_offset(sql_builder(DYS), gleam@option:option(integer())) -> sql_builder(DYS). append_offset(Builder, Offset_val) -> case Offset_val of none -> Builder; {some, N} -> _pipe = erlang:element(2, Builder), _pipe@1 = based@internal@fmt:offset(_pipe, N), {sql_builder, _pipe@1, erlang:element(3, Builder)} end. -file("src/based/sql.gleam", 1127). -spec append_limit(sql_builder(DYO), gleam@option:option(integer())) -> sql_builder(DYO). append_limit(Builder, Limit_val) -> case Limit_val of none -> Builder; {some, N} -> _pipe = erlang:element(2, Builder), _pipe@1 = based@internal@fmt:limit(_pipe, N), {sql_builder, _pipe@1, erlang:element(3, Builder)} end. -file("src/based/sql.gleam", 1658). -spec build_table_ref(table(), adapter(any())) -> binary(). build_table_ref(Tbl, Adapter) -> case erlang:element(3, Tbl) of none -> (erlang:element(4, Adapter))(erlang:element(2, Tbl)); {some, A} -> (erlang:element(4, Adapter))(A) end. -file("src/based/sql.gleam", 1597). -spec build_column(column(), adapter(any())) -> binary(). build_column(Column, Adapter) -> case Column of {all, Table} -> case Table of {some, Tbl} -> <<(build_table_ref(Tbl, Adapter))/binary, ".*"/utf8>>; none -> <<"*"/utf8>> end; {column, Table@1, Name, Alias, Func} -> Col_ref = case Name of <<"*"/utf8>> -> case Table@1 of {some, Tbl@1} -> <<(build_table_ref(Tbl@1, Adapter))/binary, ".*"/utf8>>; none -> <<"*"/utf8>> end; _ -> case Table@1 of {some, Tbl@2} -> <<<<(build_table_ref(Tbl@2, Adapter))/binary, "."/utf8>>/binary, ((erlang:element(4, Adapter))(Name))/binary>>; none -> (erlang:element(4, Adapter))(Name) end end, Col_ref@1 = case Func of none -> Col_ref; {some, count} -> based@internal@fmt:count(Col_ref); {some, sum} -> based@internal@fmt:sum(Col_ref); {some, avg} -> based@internal@fmt:avg(Col_ref); {some, max} -> based@internal@fmt:max(Col_ref); {some, min} -> based@internal@fmt:min(Col_ref) end, case Alias of none -> Col_ref@1; {some, A} -> based@internal@fmt:alias_as( Col_ref@1, (erlang:element(4, Adapter))(A) ) end end. -file("src/based/sql.gleam", 1665). -spec build_order_by(list(order()), adapter(any())) -> binary(). build_order_by(Orders, Adapter) -> _pipe = Orders, _pipe@5 = gleam@list:map(_pipe, fun(O) -> case O of {asc, Column} -> _pipe@1 = Column, _pipe@2 = build_column(_pipe@1, Adapter), based@internal@fmt:asc(_pipe@2); {desc, Column@1} -> _pipe@3 = Column@1, _pipe@4 = build_column(_pipe@3, Adapter), based@internal@fmt:desc(_pipe@4) end end), gleam@string:join(_pipe@5, <<", "/utf8>>). -file("src/based/sql.gleam", 1112). -spec append_order_by(sql_builder(DYJ), list(order()), adapter(DYJ)) -> sql_builder(DYJ). append_order_by(Builder, Orders, Adapter) -> case Orders of [] -> Builder; _ -> _pipe = erlang:element(2, Builder), _pipe@1 = based@internal@fmt:order_by( _pipe, build_order_by(Orders, Adapter) ), {sql_builder, _pipe@1, erlang:element(3, Builder)} end. -file("src/based/sql.gleam", 1641). -spec build_columns(list(column()), adapter(any())) -> binary(). build_columns(Columns, Adapter) -> _pipe = Columns, _pipe@1 = gleam@list:map(_pipe, fun(C) -> build_column(C, Adapter) end), gleam@string:join(_pipe@1, <<", "/utf8>>). -file("src/based/sql.gleam", 1097). -spec append_group_by(sql_builder(DYE), list(column()), adapter(DYE)) -> sql_builder(DYE). append_group_by(Builder, Group_by, Adapter) -> case Group_by of [] -> Builder; Cols -> _pipe = erlang:element(2, Builder), _pipe@1 = based@internal@fmt:group_by( _pipe, build_columns(Cols, Adapter) ), {sql_builder, _pipe@1, erlang:element(3, Builder)} end. -file("src/based/sql.gleam", 1647). -spec build_table(table(), adapter(any())) -> binary(). build_table(Tbl, Adapter) -> case erlang:element(3, Tbl) of none -> (erlang:element(4, Adapter))(erlang:element(2, Tbl)); {some, A} -> based@internal@fmt:alias_as( (erlang:element(4, Adapter))(erlang:element(2, Tbl)), (erlang:element(4, Adapter))(A) ) end. -file("src/based/sql.gleam", 1407). -spec build_operand(operand(EAX), adapter(EAX)) -> {binary(), list(list(EAX))}. build_operand(Operand, Adapter) -> case Operand of {column_ref, Column} -> {build_column(Column, Adapter), []}; {value_ref, Value} -> {<<":param:"/utf8>>, [[Value]]}; null_ref -> {<<":param:"/utf8>>, [[(erlang:element(5, Adapter))()]]}; {sub_query, Query} -> {sql_builder, Sql, Vals} = build_single_select(Query, Adapter), {based@internal@fmt:subquery(Sql), Vals}; {any_query, Query@1} -> {sql_builder, Sql@1, Vals@1} = build_single_select(Query@1, Adapter), {based@internal@fmt:any(Sql@1), Vals@1}; {all_query, Query@2} -> {sql_builder, Sql@2, Vals@2} = build_single_select(Query@2, Adapter), {based@internal@fmt:all(Sql@2), Vals@2} end. -file("src/based/sql.gleam", 1510). -spec build_binary_condition( operand(EBH), fun((binary(), binary()) -> binary()), operand(EBH), adapter(EBH) ) -> {binary(), list(list(EBH))}. build_binary_condition(Left, Op, Right, Adapter) -> {Ls, Lv} = build_operand(Left, Adapter), {Rs, Rv} = build_operand(Right, Adapter), {Op(Ls, Rs), gleam@list:prepend(Lv, lists:append(Rv))}. -file("src/based/sql.gleam", 1430). -spec build_condition(condition(EBC), adapter(EBC)) -> {binary(), list(list(EBC))}. build_condition(Condition, Adapter) -> case Condition of {equal, Left, Right} -> build_binary_condition( Left, fun based@internal@fmt:eq/2, Right, Adapter ); {not_equal, Left@1, Right@1} -> build_binary_condition( Left@1, fun based@internal@fmt:not_eq/2, Right@1, Adapter ); {greater_than, Left@2, Right@2} -> build_binary_condition( Left@2, fun based@internal@fmt:gt/2, Right@2, Adapter ); {less_than, Left@3, Right@3} -> build_binary_condition( Left@3, fun based@internal@fmt:lt/2, Right@3, Adapter ); {greater_than_or_equal, Left@4, Right@4} -> build_binary_condition( Left@4, fun based@internal@fmt:gt_eq/2, Right@4, Adapter ); {less_than_or_equal, Left@5, Right@5} -> build_binary_condition( Left@5, fun based@internal@fmt:lt_eq/2, Right@5, Adapter ); {between, Operand, Low, High} -> {Os, Ov} = build_operand(Operand, Adapter), {Ls, Lv} = build_operand(Low, Adapter), {Hs, Hv} = build_operand(High, Adapter), {based@internal@fmt:between(Os, Ls, Hs), lists:append([Ov, Lv, Hv])}; {like, Operand@1, Pattern} -> build_binary_condition( Operand@1, fun based@internal@fmt:like/2, Pattern, Adapter ); {not_like, Operand@2, Pattern@1} -> build_binary_condition( Operand@2, fun based@internal@fmt:not_like/2, Pattern@1, Adapter ); {in, Operand@3, Vals} -> {Os@1, Ov@1} = build_operand(Operand@3, Adapter), {Val_strings, All_vals} = gleam@list:fold( Vals, {[], []}, fun(Acc, V) -> {Strings, Collected} = Acc, {Vs, Vv} = build_operand(V, Adapter), {gleam@list:prepend(Strings, Vs), lists:append(Collected, Vv)} end ), Val_strings@1 = begin _pipe = Val_strings, _pipe@1 = lists:reverse(_pipe), gleam@string:join(_pipe@1, <<", "/utf8>>) end, {based@internal@fmt:in_(Os@1, Val_strings@1), lists:append(Ov@1, All_vals)}; {is_null, Operand@4} -> {Os@2, Ov@2} = build_operand(Operand@4, Adapter), {based@internal@fmt:is_null(Os@2), Ov@2}; {is_not_null, Operand@5} -> {Os@3, Ov@3} = build_operand(Operand@5, Adapter), {based@internal@fmt:is_not_null(Os@3), Ov@3}; {is_true, Operand@6} -> {Os@4, Ov@4} = build_operand(Operand@6, Adapter), {based@internal@fmt:is_true(Os@4), Ov@4}; {is_false, Operand@7} -> {Os@5, Ov@5} = build_operand(Operand@7, Adapter), {based@internal@fmt:is_false(Os@5), Ov@5}; {'and', Left@6, Right@6} -> {Ls@1, Lv@1} = build_condition(Left@6, Adapter), {Rs, Rv} = build_condition(Right@6, Adapter), {based@internal@fmt:and_op(Ls@1, Rs), lists:append(Lv@1, Rv)}; {'or', Left@7, Right@7} -> {Ls@2, Lv@2} = build_condition(Left@7, Adapter), {Rs@1, Rv@1} = build_condition(Right@7, Adapter), {based@internal@fmt:or_op(Ls@2, Rs@1), lists:append(Lv@2, Rv@1)}; {'not', Condition@1} -> {Cs, Cv} = build_condition(Condition@1, Adapter), {based@internal@fmt:'not'(Cs), Cv}; {exists, Query} -> {sql_builder, Sql, Vals@1} = build_single_select(Query, Adapter), {based@internal@fmt:exists(Sql), Vals@1}; {raw, Sql@1} -> {Sql@1, []} end. -file("src/based/sql.gleam", 1053). -spec append_having(sql_builder(DXR), list(list(condition(DXR))), adapter(DXR)) -> sql_builder(DXR). append_having(Builder, Having, Adapter) -> Having@1 = begin _pipe = Having, _pipe@1 = lists:reverse(_pipe), lists:append(_pipe@1) end, case Having@1 of [] -> Builder; [Single] -> {Hs, Hv} = build_condition(Single, Adapter), _pipe@2 = erlang:element(2, Builder), _pipe@3 = based@internal@fmt:having(_pipe@2, Hs), {sql_builder, _pipe@3, gleam@list:prepend(erlang:element(3, Builder), lists:append(Hv))}; [First | Rest] -> {Hs@1, Hv@1} = begin _pipe@4 = Rest, _pipe@5 = gleam@list:fold( _pipe@4, First, fun(Field@0, Field@1) -> {'and', Field@0, Field@1} end ), build_condition(_pipe@5, Adapter) end, _pipe@6 = erlang:element(2, Builder), _pipe@7 = based@internal@fmt:having(_pipe@6, Hs@1), {sql_builder, _pipe@7, gleam@list:prepend( erlang:element(3, Builder), lists:append(Hv@1) )} end. -file("src/based/sql.gleam", 1021). -spec append_where(sql_builder(DXK), list(list(condition(DXK))), adapter(DXK)) -> sql_builder(DXK). append_where(Builder, Wheres, Adapter) -> Wheres@1 = begin _pipe = Wheres, _pipe@1 = lists:reverse(_pipe), lists:append(_pipe@1) end, case Wheres@1 of [] -> Builder; [Where] -> {Ws, Wv} = build_condition(Where, Adapter), _pipe@2 = erlang:element(2, Builder), _pipe@3 = based@internal@fmt:where(_pipe@2, Ws), {sql_builder, _pipe@3, gleam@list:prepend(erlang:element(3, Builder), lists:append(Wv))}; [First | Rest] -> {Ws@1, Wv@1} = begin _pipe@4 = Rest, _pipe@5 = gleam@list:fold( _pipe@4, First, fun(Field@0, Field@1) -> {'and', Field@0, Field@1} end ), build_condition(_pipe@5, Adapter) end, _pipe@6 = erlang:element(2, Builder), _pipe@7 = based@internal@fmt:where(_pipe@6, Ws@1), {sql_builder, _pipe@7, gleam@list:prepend( erlang:element(3, Builder), lists:append(Wv@1) )} end. -file("src/based/sql.gleam", 1522). -spec build_join(sql_builder(EBN), join(EBN), adapter(EBN)) -> sql_builder(EBN). build_join(Builder, Join, Adapter) -> {Join_fn, Tbl, On_conditions} = case Join of {inner_join, Table, On} -> {fun based@internal@fmt:inner_join/2, Table, On}; {left_join, Table@1, On@1} -> {fun based@internal@fmt:left_join/2, Table@1, On@1}; {right_join, Table@2, On@2} -> {fun based@internal@fmt:right_join/2, Table@2, On@2}; {full_join, Table@3, On@3} -> {fun based@internal@fmt:full_join/2, Table@3, On@3} end, {On_sql, On_vals} = case On_conditions of [] -> {<<""/utf8>>, []}; [Single] -> build_condition(Single, Adapter); [First | Rest] -> _pipe = Rest, _pipe@1 = gleam@list:fold( _pipe, First, fun(Field@0, Field@1) -> {'and', Field@0, Field@1} end ), build_condition(_pipe@1, Adapter) end, Sql = begin _pipe@2 = erlang:element(2, Builder), _pipe@3 = Join_fn(_pipe@2, build_table(Tbl, Adapter)), based@internal@fmt:on(_pipe@3, On_sql) end, {sql_builder, Sql, gleam@list:prepend(erlang:element(3, Builder), lists:append(On_vals))}. -file("src/based/sql.gleam", 1085). -spec append_joins(sql_builder(DXY), list(join(DXY)), adapter(DXY)) -> sql_builder(DXY). append_joins(Builder, Joins, Adapter) -> _pipe = Joins, _pipe@1 = lists:reverse(_pipe), gleam@list:fold( _pipe@1, Builder, fun(Builder1, Join) -> build_join(Builder1, Join, Adapter) end ). -file("src/based/sql.gleam", 1264). -spec build_select(select_query(DZV), adapter(DZV)) -> sql_builder(DZV). build_select(Query, Adapter) -> Select_fn = case erlang:element(10, Query) of true -> fun based@internal@fmt:select_distinct/1; false -> fun based@internal@fmt:select/1 end, Select_start = begin _pipe = erlang:element(2, Query), _pipe@1 = build_columns(_pipe, Adapter), Select_fn(_pipe@1) end, Builder@1 = case erlang:element(3, Query) of {select_from_table, Table} -> _pipe@2 = Table, _pipe@3 = build_table(_pipe@2, Adapter), {sql_builder, _pipe@3, []}; {select_from_sub_query, Query@1, Alias} -> Builder = build_single_select(Query@1, Adapter), _pipe@4 = erlang:element(2, Builder), _pipe@5 = based@internal@fmt:enclose(_pipe@4), _pipe@6 = based@internal@fmt:alias_as( _pipe@5, (erlang:element(4, Adapter))(Alias) ), {sql_builder, _pipe@6, erlang:element(3, Builder)} end, _pipe@7 = based@internal@fmt:from( Select_start, erlang:element(2, Builder@1) ), _pipe@8 = {sql_builder, _pipe@7, erlang:element(3, Builder@1)}, _pipe@9 = append_joins(_pipe@8, erlang:element(5, Query), Adapter), _pipe@10 = append_where(_pipe@9, erlang:element(4, Query), Adapter), _pipe@11 = append_group_by(_pipe@10, erlang:element(9, Query), Adapter), _pipe@12 = append_having(_pipe@11, erlang:element(11, Query), Adapter), _pipe@13 = append_order_by(_pipe@12, erlang:element(6, Query), Adapter), _pipe@14 = append_limit(_pipe@13, erlang:element(7, Query)), _pipe@15 = append_offset(_pipe@14, erlang:element(8, Query)), append_for_update(_pipe@15, erlang:element(12, Query)). -file("src/based/sql.gleam", 1586). -spec build_single_select(builder(select(), ECC), adapter(ECC)) -> sql_builder(ECC). build_single_select(Builder, Adapter) -> case Builder of {select_builder, Query, _, _} -> build_select(Query, Adapter); _ -> erlang:error(#{gleam_error => panic, message => <<"unreachable: build_single_select called with non-Select builder"/utf8>>, file => <>, module => <<"based/sql"/utf8>>, function => <<"build_single_select"/utf8>>, line => 1593}) end. -file("src/based/sql.gleam", 1552). -spec build_union(union_query(EBS), adapter(EBS)) -> sql_builder(EBS). build_union(Query, Adapter) -> Union_fn = case erlang:element(3, Query) of union -> fun based@internal@fmt:union/2; union_all -> fun based@internal@fmt:union_all/2 end, {Sql_parts, Values} = begin _pipe = erlang:element(2, Query), gleam@list:fold( _pipe, {[], []}, fun(Acc, Q) -> {Parts, Vals} = Acc, Builder = build_single_select(Q, Adapter), {gleam@list:prepend(Parts, erlang:element(2, Builder)), gleam@list:prepend(Vals, erlang:element(3, Builder))} end ) end, Values@1 = begin _pipe@1 = lists:append(Values), lists:reverse(_pipe@1) end, Sql = case Sql_parts of [] -> <<""/utf8>>; [First | Rest] -> gleam@list:fold(Rest, First, Union_fn) end, {sql_builder, Sql, Values@1}. -file("src/based/sql.gleam", 1163). -spec append_returning(sql_builder(DYZ), list(column()), adapter(DYZ)) -> sql_builder(DYZ). append_returning(Builder, Returning, Adapter) -> case Returning of [] -> Builder; Cols -> _pipe = erlang:element(2, Builder), _pipe@1 = based@internal@fmt:returning( _pipe, build_columns(Cols, Adapter) ), {sql_builder, _pipe@1, erlang:element(3, Builder)} end. -file("src/based/sql.gleam", 1398). -spec build_delete(delete_query(EAT), adapter(EAT)) -> sql_builder(EAT). build_delete(Query, Adapter) -> _pipe = erlang:element(2, Query), _pipe@1 = build_table(_pipe, Adapter), _pipe@2 = based@internal@fmt:delete(_pipe@1), _pipe@3 = {sql_builder, _pipe@2, []}, _pipe@4 = append_where(_pipe@3, erlang:element(3, Query), Adapter), append_returning(_pipe@4, erlang:element(4, Query), Adapter). -file("src/based/sql.gleam", 1370). -spec append_sets(sql_builder(EAN), list(set(EAN)), adapter(EAN)) -> sql_builder(EAN). append_sets(Builder, Sets, Adapter) -> {Sets_sql, Values@2} = begin gleam@list:fold( Sets, {[], []}, fun(_use0, Set) -> {Sql, Values} = _use0, {Set_string, Operand_values} = build_operand( erlang:element(3, Set), Adapter ), Values@1 = gleam@list:prepend(Values, Operand_values), Sql@1 = begin _pipe = erlang:element(2, Set), _pipe@1 = (erlang:element(4, Adapter))(_pipe), _pipe@2 = based@internal@fmt:eq(_pipe@1, Set_string), gleam@list:prepend(Sql, _pipe@2) end, {Sql@1, Values@1} end ) end, Sets_sql@1 = begin _pipe@3 = Sets_sql, _pipe@4 = lists:reverse(_pipe@3), gleam@string:join(_pipe@4, <<", "/utf8>>) end, Values@3 = begin _pipe@5 = Values@2, _pipe@6 = lists:reverse(_pipe@5), _pipe@7 = lists:append(_pipe@6), lists:append(_pipe@7) end, _pipe@8 = erlang:element(2, Builder), _pipe@9 = based@internal@fmt:set(_pipe@8, Sets_sql@1), {sql_builder, _pipe@9, gleam@list:prepend(erlang:element(3, Builder), Values@3)}. -file("src/based/sql.gleam", 1357). -spec build_update(update_query(EAJ), adapter(EAJ)) -> sql_builder(EAJ). build_update(Query, Adapter) -> _pipe = erlang:element(2, Query), _pipe@1 = build_table(_pipe, Adapter), _pipe@2 = based@internal@fmt:update(_pipe@1), _pipe@3 = {sql_builder, _pipe@2, []}, _pipe@4 = append_sets(_pipe@3, erlang:element(3, Query), Adapter), _pipe@5 = append_where(_pipe@4, erlang:element(4, Query), Adapter), _pipe@6 = append_order_by(_pipe@5, erlang:element(6, Query), Adapter), _pipe@7 = append_limit(_pipe@6, erlang:element(7, Query)), _pipe@8 = append_offset(_pipe@7, erlang:element(8, Query)), append_returning(_pipe@8, erlang:element(5, Query), Adapter). -file("src/based/sql.gleam", 1328). -spec append_on_conflict( sql_builder(EAD), gleam@option:option(on_conflict(EAD)), adapter(EAD) ) -> sql_builder(EAD). append_on_conflict(Builder, On_conflict, Adapter) -> case On_conflict of none -> Builder; {some, {on_conflict, Target, Action, Conflict_wheres}} -> Sql = begin _pipe = erlang:element(2, Builder), based@internal@fmt:on_conflict( _pipe, (erlang:element(4, Adapter))(Target) ) end, _pipe@3 = case Action of do_nothing -> based@internal@fmt:do_nothing(Sql); {do_update, Sets} -> _pipe@1 = Sets, _pipe@2 = gleam@list:map( _pipe@1, fun(Pair) -> {Col_name, Val_expr} = Pair, based@internal@fmt:eq( (erlang:element(4, Adapter))(Col_name), Val_expr ) end ), based@internal@fmt:do_update(Sql, _pipe@2) end, _pipe@4 = {sql_builder, _pipe@3, erlang:element(3, Builder)}, append_where(_pipe@4, [Conflict_wheres], Adapter) end. -file("src/based/sql.gleam", 1303). -spec build_insert(insert_query(DZZ), adapter(DZZ)) -> sql_builder(DZZ). build_insert(Query, Adapter) -> {Placeholders, Values} = begin gleam@list:fold( erlang:element(4, Query), {[], []}, fun(_use0, Row) -> {Rows, Vals} = _use0, Row_placeholders = begin _pipe = Row, _pipe@1 = gleam@list:map( _pipe, fun(_) -> <<":param:"/utf8>> end ), _pipe@2 = gleam@string:join(_pipe@1, <<", "/utf8>>), based@internal@fmt:enclose(_pipe@2) end, {gleam@list:prepend(Rows, Row_placeholders), gleam@list:prepend(Vals, Row)} end ) end, Columns = gleam@list:map( erlang:element(3, Query), erlang:element(4, Adapter) ), Sql = begin _pipe@3 = erlang:element(2, Query), _pipe@4 = build_table(_pipe@3, Adapter), based@internal@fmt:insert(_pipe@4, Columns, Placeholders) end, _pipe@5 = {sql_builder, Sql, Values}, _pipe@6 = append_on_conflict(_pipe@5, erlang:element(6, Query), Adapter), append_returning(_pipe@6, erlang:element(5, Query), Adapter). -file("src/based/sql.gleam", 1576). -spec build_inner(builder(any(), EBX), adapter(EBX)) -> sql_builder(EBX). build_inner(Builder, Adapter) -> case Builder of {select_builder, Query, _, _} -> build_select(Query, Adapter); {insert_builder, Query@1, _, _} -> build_insert(Query@1, Adapter); {update_builder, Query@2, _, _} -> build_update(Query@2, Adapter); {delete_builder, Query@3, _, _} -> build_delete(Query@3, Adapter); {union_builder, Query@4, _, _} -> build_union(Query@4, Adapter) end. -file("src/based/sql.gleam", 917). ?DOC(" Creates a Common Table Expression (CTE).\n"). -spec cte(binary(), builder(any(), DVR)) -> cte(DVR). cte(Name, Builder) -> {cte, Name, [], fun(_capture) -> build_inner(Builder, _capture) end}. -file("src/based/sql.gleam", 922). ?DOC(" Sets explicit column names on a CTE.\n"). -spec cte_columns(cte(DVV), list(binary())) -> cte(DVV). cte_columns(C, Cols) -> {cte, erlang:element(2, C), Cols, erlang:element(4, C)}. -file("src/based/sql.gleam", 927). ?DOC(" Attaches CTEs to a query as a `WITH` clause.\n"). -spec with(builder(DVZ, DWA), list(cte(DWA))) -> builder(DVZ, DWA). with(Builder, Ctes) -> case Builder of {select_builder, _, _, _} -> {select_builder, erlang:element(2, Builder), Ctes, erlang:element(4, Builder)}; {insert_builder, _, _, _} -> {insert_builder, erlang:element(2, Builder), Ctes, erlang:element(4, Builder)}; {update_builder, _, _, _} -> {update_builder, erlang:element(2, Builder), Ctes, erlang:element(4, Builder)}; {delete_builder, _, _, _} -> {delete_builder, erlang:element(2, Builder), Ctes, erlang:element(4, Builder)}; {union_builder, _, _, _} -> {union_builder, erlang:element(2, Builder), Ctes, erlang:element(4, Builder)} end. -file("src/based/sql.gleam", 938). ?DOC(" Marks the query's WITH clause as `WITH RECURSIVE`.\n"). -spec recursive(builder(DWH, DWI)) -> builder(DWH, DWI). recursive(Builder) -> case Builder of {select_builder, _, _, _} -> {select_builder, erlang:element(2, Builder), erlang:element(3, Builder), true}; {insert_builder, _, _, _} -> {insert_builder, erlang:element(2, Builder), erlang:element(3, Builder), true}; {update_builder, _, _, _} -> {update_builder, erlang:element(2, Builder), erlang:element(3, Builder), true}; {delete_builder, _, _, _} -> {delete_builder, erlang:element(2, Builder), erlang:element(3, Builder), true}; {union_builder, _, _, _} -> {union_builder, erlang:element(2, Builder), erlang:element(3, Builder), true} end. -file("src/based/sql.gleam", 949). ?DOC(" Combines SELECT queries with `UNION`.\n"). -spec union(list(builder(select(), DWN))) -> builder(union(), DWN). union(Selects) -> {union_builder, {union_query, Selects, union}, [], false}. -file("src/based/sql.gleam", 958). ?DOC(" Combines SELECT queries with `UNION ALL`.\n"). -spec union_all(list(builder(select(), DWT))) -> builder(union_all(), DWT). union_all(Selects) -> {union_builder, {union_query, Selects, union_all}, [], false}. -file("src/based/sql.gleam", 1001). -spec placeholders(binary(), fun((integer()) -> binary())) -> binary(). placeholders(St, Mapper) -> _pipe = gleam@string:split(St, <<":param:"/utf8>>), _pipe@1 = gleam@list:index_fold(_pipe, [], fun(Acc, St1, Idx) -> case Idx of 0 -> [St1 | Acc]; Idx@1 -> Ph = Mapper(Idx@1), [St1, Ph | Acc] end end), _pipe@2 = lists:reverse(_pipe@1), gleam@string:join(_pipe@2, <<""/utf8>>). -file("src/based/sql.gleam", 1222). -spec build_ctes(list(cte(DZQ)), boolean(), adapter(DZQ)) -> sql_builder(DZQ). build_ctes(Ctes, Recursive, Adapter) -> case Ctes of [] -> {sql_builder, <<""/utf8>>, []}; _ -> {Cte_parts, All_vals} = begin gleam@list:fold( Ctes, {[], []}, fun(_use0, Cte) -> {Parts, Vals} = _use0, Sql_builder = (erlang:element(4, Cte))(Adapter), Col_part = case erlang:element(3, Cte) of [] -> <<""/utf8>>; Cols -> based@internal@fmt:enclose( gleam@string:join(Cols, <<", "/utf8>>) ) end, Values = gleam@list:prepend( Vals, erlang:element(3, Sql_builder) ), Parts@1 = begin _pipe = erlang:element(2, Cte), _pipe@1 = gleam@string:append(_pipe, Col_part), _pipe@2 = based@internal@fmt:cte( _pipe@1, erlang:element(2, Sql_builder) ), gleam@list:prepend(Parts, _pipe@2) end, {Parts@1, Values} end ) end, Ctes_sql = begin _pipe@3 = Cte_parts, _pipe@4 = lists:reverse(_pipe@3), gleam@string:join(_pipe@4, <<", "/utf8>>) end, Prefix = case Recursive of true -> based@internal@fmt:with_recursive(Ctes_sql); false -> based@internal@fmt:with_cte(Ctes_sql) end, {sql_builder, <>, lists:append(All_vals)} end. -file("src/based/sql.gleam", 1208). -spec apply_ctes(sql_builder(DZK), list(cte(DZK)), boolean(), adapter(DZK)) -> sql_builder(DZK). apply_ctes(Builder, Ctes, Recursive, Adapter) -> Cte_builder = build_ctes(Ctes, Recursive, Adapter), {sql_builder, <<(erlang:element(2, Cte_builder))/binary, (based@internal@fmt:terminate(erlang:element(2, Builder)))/binary>>, lists:append(erlang:element(3, Builder), erlang:element(3, Cte_builder))}. -file("src/based/sql.gleam", 1178). -spec build_query(builder(any(), DZF), adapter(DZF)) -> sql_builder(DZF). build_query(Builder, Adapter) -> case Builder of {select_builder, Query, Ctes, Recursive} -> _pipe = Query, _pipe@1 = build_select(_pipe, Adapter), apply_ctes(_pipe@1, Ctes, Recursive, Adapter); {insert_builder, Query@1, Ctes@1, Recursive@1} -> _pipe@2 = Query@1, _pipe@3 = build_insert(_pipe@2, Adapter), apply_ctes(_pipe@3, Ctes@1, Recursive@1, Adapter); {update_builder, Query@2, Ctes@2, Recursive@2} -> _pipe@4 = Query@2, _pipe@5 = build_update(_pipe@4, Adapter), apply_ctes(_pipe@5, Ctes@2, Recursive@2, Adapter); {delete_builder, Query@3, Ctes@3, Recursive@3} -> _pipe@6 = Query@3, _pipe@7 = build_delete(_pipe@6, Adapter), apply_ctes(_pipe@7, Ctes@3, Recursive@3, Adapter); {union_builder, Query@4, Ctes@4, Recursive@4} -> _pipe@8 = Query@4, _pipe@9 = build_union(_pipe@8, Adapter), apply_ctes(_pipe@9, Ctes@4, Recursive@4, Adapter) end. -file("src/based/sql.gleam", 970). ?DOC( " Serializes a query builder into a `Query(v)` with parameterized placeholders.\n" "\n" " Returns a `Query` record with `.sql` containing the SQL string with\n" " placeholders and `.values` containing the parameter values in order.\n" ). -spec to_query(builder(any(), DXA), adapter(DXA)) -> 'query'(DXA). to_query(Builder, Adapter) -> {sql_builder, Sql, Values} = build_query(Builder, Adapter), Sql@1 = placeholders(Sql, erlang:element(2, Adapter)), Values@1 = begin _pipe = Values, _pipe@1 = lists:reverse(_pipe), lists:append(_pipe@1) end, {'query', Sql@1, Values@1}. -file("src/based/sql.gleam", 982). ?DOC( " Serializes a query builder into a plain SQL string with values inlined.\n" "\n" " Values are formatted using the adapter's `on_value` handler. This is useful\n" " for debugging and logging — use `to_query` for actual database execution.\n" ). -spec to_string(builder(any(), DXG), adapter(DXG)) -> binary(). to_string(Builder, Adapter) -> {sql_builder, Sql, Values} = build_query(Builder, Adapter), Values@1 = begin _pipe = Values, _pipe@1 = lists:reverse(_pipe), lists:append(_pipe@1) end, Values_by_idx = begin _pipe@2 = Values@1, _pipe@3 = gleam@list:index_map( _pipe@2, fun(Val, Idx) -> {Idx + 1, Val} end ), maps:from_list(_pipe@3) end, With = fun(Idx@1) -> _pipe@4 = Values_by_idx, _pipe@5 = gleam_stdlib:map_get(_pipe@4, Idx@1), _pipe@6 = gleam@result:map(_pipe@5, erlang:element(3, Adapter)), gleam@result:unwrap(_pipe@6, <<""/utf8>>) end, placeholders(Sql, With).