-module(sqlode@internal@model). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/sqlode/internal/model.gleam"). -export([parse_engine/1, engine_to_string/1, parse_type_mapping/1, type_mapping_to_string/1, parse_runtime/1, runtime_to_string/1, empty_overrides/0, is_result_command/1, parse_query_command/1, query_command_to_string/1, parse_sql_type/1, parse_sql_type_for_engine/2]). -export_type([engine/0, runtime/0, type_mapping/0, codec_hooks/0, type_override/0, column_rename/0, overrides/0, gleam_output/0, sql_block/0, config/0, macro/0, parsed_query/0, scalar_type/0, enum_kind/0, enum_def/0, normalized_type/0, column/0, table/0, catalog/0, query_param/0, result_column/0, embedded_column/0, result_item/0, analyzed_query/0]). -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(false). -type engine() :: postgre_s_q_l | my_s_q_l | s_q_lite. -type runtime() :: raw | native. -type type_mapping() :: string_mapping | rich_mapping | strong_mapping. -type codec_hooks() :: {codec_hooks, binary(), binary()}. -type type_override() :: {db_type_override, binary(), binary(), gleam@option:option(boolean()), gleam@option:option(codec_hooks())} | {column_override, binary(), binary(), binary(), gleam@option:option(codec_hooks())}. -type column_rename() :: {column_rename, binary(), binary(), binary()}. -type overrides() :: {overrides, list(type_override()), list(column_rename())}. -type gleam_output() :: {gleam_output, binary(), runtime(), type_mapping(), boolean(), boolean(), boolean(), boolean(), boolean(), gleam@option:option(integer())}. -type sql_block() :: {sql_block, gleam@option:option(binary()), engine(), list(binary()), list(binary()), gleam_output(), overrides()}. -type config() :: {config, integer(), list(sql_block())}. -type macro() :: {macro_arg, integer(), binary()} | {macro_narg, integer(), binary()} | {macro_slice, integer(), binary()}. -type parsed_query() :: {parsed_query, binary(), binary(), sqlode@runtime:query_command(), binary(), binary(), integer(), list(macro())}. -type scalar_type() :: int_type | float_type | bool_type | string_type | bytes_type | date_time_type | date_type | time_type | uuid_type | json_type | decimal_type | {enum_type, binary()} | {set_type, binary()} | {custom_type, binary(), gleam@option:option(binary()), scalar_type(), gleam@option:option(codec_hooks())} | {array_type, scalar_type()}. -type enum_kind() :: postgres_enum | my_sql_enum | my_sql_set. -type enum_def() :: {enum_def, binary(), list(binary()), enum_kind()}. -type normalized_type() :: {normalized_type, binary(), boolean()}. -type column() :: {column, binary(), scalar_type(), boolean()}. -type table() :: {table, binary(), list(column())}. -type catalog() :: {catalog, list(table()), list(enum_def())}. -type query_param() :: {query_param, integer(), binary(), scalar_type(), boolean(), boolean()}. -type result_column() :: {result_column, binary(), scalar_type(), boolean(), gleam@option:option(binary())}. -type embedded_column() :: {embedded_column, binary(), binary(), list(column())}. -type result_item() :: {scalar_result, result_column()} | {embedded_result, embedded_column()}. -type analyzed_query() :: {analyzed_query, parsed_query(), list(query_param()), list(result_item())}. -file("src/sqlode/internal/model.gleam", 12). ?DOC(false). -spec parse_engine(binary()) -> {ok, engine()} | {error, binary()}. parse_engine(Value) -> case Value of <<"postgresql"/utf8>> -> {ok, postgre_s_q_l}; <<"mysql"/utf8>> -> {ok, my_s_q_l}; <<"sqlite"/utf8>> -> {ok, s_q_lite}; _ -> {error, <<"must be one of: postgresql, mysql, sqlite"/utf8>>} end. -file("src/sqlode/internal/model.gleam", 21). ?DOC(false). -spec engine_to_string(engine()) -> binary(). engine_to_string(Engine) -> case Engine of postgre_s_q_l -> <<"postgresql"/utf8>>; my_s_q_l -> <<"mysql"/utf8>>; s_q_lite -> <<"sqlite"/utf8>> end. -file("src/sqlode/internal/model.gleam", 40). ?DOC(false). -spec parse_type_mapping(binary()) -> {ok, type_mapping()} | {error, binary()}. parse_type_mapping(Value) -> case Value of <<"string"/utf8>> -> {ok, string_mapping}; <<"rich"/utf8>> -> {ok, rich_mapping}; <<"strong"/utf8>> -> {ok, strong_mapping}; _ -> {error, <<"must be one of: string, rich, strong"/utf8>>} end. -file("src/sqlode/internal/model.gleam", 49). ?DOC(false). -spec type_mapping_to_string(type_mapping()) -> binary(). type_mapping_to_string(Mapping) -> case Mapping of string_mapping -> <<"string"/utf8>>; rich_mapping -> <<"rich"/utf8>>; strong_mapping -> <<"strong"/utf8>> end. -file("src/sqlode/internal/model.gleam", 57). ?DOC(false). -spec parse_runtime(binary()) -> {ok, runtime()} | {error, binary()}. parse_runtime(Value) -> case Value of <<"raw"/utf8>> -> {ok, raw}; <<"based"/utf8>> -> {error, <<"\"based\" is not yet supported; use \"raw\" or \"native\" instead"/utf8>>}; <<"native"/utf8>> -> {ok, native}; _ -> {error, <<"must be one of: raw, native"/utf8>>} end. -file("src/sqlode/internal/model.gleam", 67). ?DOC(false). -spec runtime_to_string(runtime()) -> binary(). runtime_to_string(Runtime) -> case Runtime of raw -> <<"raw"/utf8>>; native -> <<"native"/utf8>> end. -file("src/sqlode/internal/model.gleam", 125). ?DOC(false). -spec empty_overrides() -> overrides(). empty_overrides() -> {overrides, [], []}. -file("src/sqlode/internal/model.gleam", 179). ?DOC(false). -spec is_result_command(sqlode@runtime:query_command()) -> boolean(). is_result_command(Command) -> case Command of query_one -> true; query_many -> true; query_batch_one -> true; query_batch_many -> true; _ -> false end. -file("src/sqlode/internal/model.gleam", 189). ?DOC(false). -spec parse_query_command(binary()) -> {ok, sqlode@runtime:query_command()} | {error, binary()}. parse_query_command(Value) -> case Value of <<":one"/utf8>> -> {ok, query_one}; <<":many"/utf8>> -> {ok, query_many}; <<":exec"/utf8>> -> {ok, query_exec}; <<":execresult"/utf8>> -> {ok, query_exec_result}; <<":execrows"/utf8>> -> {ok, query_exec_rows}; <<":execlastid"/utf8>> -> {ok, query_exec_last_id}; <<":batchone"/utf8>> -> {ok, query_batch_one}; <<":batchmany"/utf8>> -> {ok, query_batch_many}; <<":batchexec"/utf8>> -> {ok, query_batch_exec}; <<":copyfrom"/utf8>> -> {ok, query_copy_from}; _ -> {error, <<"must be one of: :one, :many, :exec, :execresult, :execrows, :execlastid, :batchone, :batchmany, :batchexec, :copyfrom"/utf8>>} end. -file("src/sqlode/internal/model.gleam", 210). ?DOC(false). -spec query_command_to_string(sqlode@runtime:query_command()) -> binary(). query_command_to_string(Command) -> case Command of query_one -> <<"QueryOne"/utf8>>; query_many -> <<"QueryMany"/utf8>>; query_exec -> <<"QueryExec"/utf8>>; query_exec_result -> <<"QueryExecResult"/utf8>>; query_exec_rows -> <<"QueryExecRows"/utf8>>; query_exec_last_id -> <<"QueryExecLastId"/utf8>>; query_batch_one -> <<"QueryBatchOne"/utf8>>; query_batch_many -> <<"QueryBatchMany"/utf8>>; query_batch_exec -> <<"QueryBatchExec"/utf8>>; query_copy_from -> <<"QueryCopyFrom"/utf8>> end. -file("src/sqlode/internal/model.gleam", 367). ?DOC(false). -spec strip_mysql_signedness(binary()) -> binary(). strip_mysql_signedness(Text) -> _pipe = Text, _pipe@1 = gleam@string:replace( _pipe, <<" unsigned zerofill"/utf8>>, <<""/utf8>> ), _pipe@2 = gleam@string:replace( _pipe@1, <<" zerofill unsigned"/utf8>>, <<""/utf8>> ), _pipe@3 = gleam@string:replace(_pipe@2, <<" unsigned"/utf8>>, <<""/utf8>>), _pipe@4 = gleam@string:replace(_pipe@3, <<" signed"/utf8>>, <<""/utf8>>), _pipe@5 = gleam@string:replace(_pipe@4, <<" zerofill"/utf8>>, <<""/utf8>>), gleam@string:trim(_pipe@5). -file("src/sqlode/internal/model.gleam", 377). ?DOC(false). -spec detect_tinyint_one(binary()) -> boolean(). detect_tinyint_one(Text) -> case gleam@string:split_once(Text, <<"("/utf8>>) of {ok, {Head, Rest}} -> case {gleam@string:trim(Head) =:= <<"tinyint"/utf8>>, gleam@string:split_once(Rest, <<")"/utf8>>)} of {true, {ok, {Arg, _}}} -> gleam@string:trim(Arg) =:= <<"1"/utf8>>; {_, _} -> false end; {error, nil} -> false end. -file("src/sqlode/internal/model.gleam", 388). ?DOC(false). -spec is_mysql_decimal_text(binary()) -> boolean(). is_mysql_decimal_text(Text) -> Base = case gleam@string:split_once(Text, <<"("/utf8>>) of {ok, {Head, _}} -> gleam@string:trim(Head); {error, nil} -> gleam@string:trim(Text) end, (((Base =:= <<"decimal"/utf8>>) orelse (Base =:= <<"numeric"/utf8>>)) orelse (Base =:= <<"dec"/utf8>>)) orelse (Base =:= <<"fixed"/utf8>>). -file("src/sqlode/internal/model.gleam", 429). ?DOC(false). -spec strip_array_suffix(binary(), boolean()) -> {binary(), boolean()}. strip_array_suffix(Text, Seen) -> Trimmed = gleam@string:trim_end(Text), case gleam_stdlib:string_ends_with(Trimmed, <<"[]"/utf8>>) of true -> strip_array_suffix(gleam@string:drop_end(Trimmed, 2), true); false -> case gleam_stdlib:string_ends_with(Trimmed, <<" array"/utf8>>) of true -> strip_array_suffix(gleam@string:drop_end(Trimmed, 6), true); false -> {Trimmed, Seen} end end. -file("src/sqlode/internal/model.gleam", 441). ?DOC(false). -spec strip_modifier(binary()) -> binary(). strip_modifier(Text) -> After_open = case gleam@string:split_once(Text, <<"("/utf8>>) of {ok, {Head, _}} -> Head; {error, nil} -> Text end, case gleam@string:split_once(After_open, <<")"/utf8>>) of {ok, {Head@1, _}} -> Head@1; {error, nil} -> After_open end. -file("src/sqlode/internal/model.gleam", 456). ?DOC(false). -spec collapse_whitespace(binary()) -> binary(). collapse_whitespace(Text) -> _pipe = Text, _pipe@1 = gleam@string:split(_pipe, <<" "/utf8>>), _pipe@2 = gleam@list:filter(_pipe@1, fun(Part) -> Part /= <<""/utf8>> end), gleam@string:join(_pipe@2, <<" "/utf8>>). -file("src/sqlode/internal/model.gleam", 415). ?DOC(false). -spec normalize_type_text(binary()) -> normalized_type(). normalize_type_text(Type_text) -> Lowered = begin _pipe = Type_text, _pipe@1 = string:lowercase(_pipe), gleam@string:trim(_pipe@1) end, {Without_array, Is_array} = strip_array_suffix(Lowered, false), Without_modifier = strip_modifier(Without_array), Base = begin _pipe@2 = Without_modifier, _pipe@3 = collapse_whitespace(_pipe@2), gleam@string:trim(_pipe@3) end, {normalized_type, Base, Is_array}. -file("src/sqlode/internal/model.gleam", 463). ?DOC(false). -spec classify_builtin_type(binary()) -> {ok, scalar_type()} | {error, nil}. classify_builtin_type(Base) -> case Base of <<"int"/utf8>> -> {ok, int_type}; <<"int2"/utf8>> -> {ok, int_type}; <<"int4"/utf8>> -> {ok, int_type}; <<"int8"/utf8>> -> {ok, int_type}; <<"integer"/utf8>> -> {ok, int_type}; <<"smallint"/utf8>> -> {ok, int_type}; <<"bigint"/utf8>> -> {ok, int_type}; <<"mediumint"/utf8>> -> {ok, int_type}; <<"tinyint"/utf8>> -> {ok, int_type}; <<"serial"/utf8>> -> {ok, int_type}; <<"serial2"/utf8>> -> {ok, int_type}; <<"serial4"/utf8>> -> {ok, int_type}; <<"serial8"/utf8>> -> {ok, int_type}; <<"smallserial"/utf8>> -> {ok, int_type}; <<"bigserial"/utf8>> -> {ok, int_type}; <<"year"/utf8>> -> {ok, int_type}; <<"float"/utf8>> -> {ok, float_type}; <<"float4"/utf8>> -> {ok, float_type}; <<"float8"/utf8>> -> {ok, float_type}; <<"real"/utf8>> -> {ok, float_type}; <<"double"/utf8>> -> {ok, float_type}; <<"double precision"/utf8>> -> {ok, float_type}; <<"numeric"/utf8>> -> {ok, float_type}; <<"decimal"/utf8>> -> {ok, float_type}; <<"dec"/utf8>> -> {ok, float_type}; <<"money"/utf8>> -> {ok, float_type}; <<"smallmoney"/utf8>> -> {ok, float_type}; <<"bool"/utf8>> -> {ok, bool_type}; <<"boolean"/utf8>> -> {ok, bool_type}; <<"bytea"/utf8>> -> {ok, bytes_type}; <<"blob"/utf8>> -> {ok, bytes_type}; <<"longblob"/utf8>> -> {ok, bytes_type}; <<"mediumblob"/utf8>> -> {ok, bytes_type}; <<"tinyblob"/utf8>> -> {ok, bytes_type}; <<"binary"/utf8>> -> {ok, bytes_type}; <<"varbinary"/utf8>> -> {ok, bytes_type}; <<"uuid"/utf8>> -> {ok, uuid_type}; <<"uniqueidentifier"/utf8>> -> {ok, uuid_type}; <<"json"/utf8>> -> {ok, json_type}; <<"jsonb"/utf8>> -> {ok, json_type}; <<"timestamp"/utf8>> -> {ok, date_time_type}; <<"timestamptz"/utf8>> -> {ok, date_time_type}; <<"timestamp with time zone"/utf8>> -> {ok, date_time_type}; <<"timestamp without time zone"/utf8>> -> {ok, date_time_type}; <<"datetime"/utf8>> -> {ok, date_time_type}; <<"datetime2"/utf8>> -> {ok, date_time_type}; <<"date"/utf8>> -> {ok, date_type}; <<"time"/utf8>> -> {ok, time_type}; <<"timetz"/utf8>> -> {ok, time_type}; <<"time with time zone"/utf8>> -> {ok, time_type}; <<"time without time zone"/utf8>> -> {ok, time_type}; <<"interval"/utf8>> -> {ok, time_type}; <<"text"/utf8>> -> {ok, string_type}; <<"char"/utf8>> -> {ok, string_type}; <<"character"/utf8>> -> {ok, string_type}; <<"character varying"/utf8>> -> {ok, string_type}; <<"varchar"/utf8>> -> {ok, string_type}; <<"bpchar"/utf8>> -> {ok, string_type}; <<"nchar"/utf8>> -> {ok, string_type}; <<"nvarchar"/utf8>> -> {ok, string_type}; <<"clob"/utf8>> -> {ok, string_type}; <<"nclob"/utf8>> -> {ok, string_type}; <<"longtext"/utf8>> -> {ok, string_type}; <<"mediumtext"/utf8>> -> {ok, string_type}; <<"tinytext"/utf8>> -> {ok, string_type}; <<"string"/utf8>> -> {ok, string_type}; <<"name"/utf8>> -> {ok, string_type}; <<"citext"/utf8>> -> {ok, string_type}; <<"inet"/utf8>> -> {ok, string_type}; <<"cidr"/utf8>> -> {ok, string_type}; <<"macaddr"/utf8>> -> {ok, string_type}; <<"macaddr8"/utf8>> -> {ok, string_type}; <<"tsvector"/utf8>> -> {ok, string_type}; <<"tsquery"/utf8>> -> {ok, string_type}; <<"point"/utf8>> -> {ok, string_type}; <<"line"/utf8>> -> {ok, string_type}; <<"lseg"/utf8>> -> {ok, string_type}; <<"box"/utf8>> -> {ok, string_type}; <<"path"/utf8>> -> {ok, string_type}; <<"polygon"/utf8>> -> {ok, string_type}; <<"circle"/utf8>> -> {ok, string_type}; <<"xml"/utf8>> -> {ok, string_type}; <<"bit"/utf8>> -> {ok, string_type}; <<"bit varying"/utf8>> -> {ok, string_type}; <<"varbit"/utf8>> -> {ok, string_type}; _ -> {error, nil} end. -file("src/sqlode/internal/model.gleam", 400). ?DOC(false). -spec classify_normalized_base(binary()) -> {ok, scalar_type()} | {error, nil}. classify_normalized_base(Base) -> case classify_builtin_type(Base) of {ok, T} -> {ok, T}; {error, nil} -> case gleam@string:split_once(Base, <<" "/utf8>>) of {ok, {First_word, _}} -> classify_builtin_type(First_word); {error, nil} -> {error, nil} end end. -file("src/sqlode/internal/model.gleam", 314). ?DOC(false). -spec parse_sql_type(binary()) -> {ok, scalar_type()} | {error, nil}. parse_sql_type(Type_text) -> Normalized = normalize_type_text(Type_text), case classify_normalized_base(erlang:element(2, Normalized)) of {ok, Element_type} -> case erlang:element(3, Normalized) of true -> {ok, {array_type, Element_type}}; false -> {ok, Element_type} end; {error, nil} -> {error, nil} end. -file("src/sqlode/internal/model.gleam", 351). ?DOC(false). -spec classify_mysql_type_text(binary()) -> {ok, scalar_type()} | {error, nil}. classify_mysql_type_text(Type_text) -> Lowered = begin _pipe = Type_text, _pipe@1 = string:lowercase(_pipe), gleam@string:trim(_pipe@1) end, Stripped = strip_mysql_signedness(Lowered), case detect_tinyint_one(Stripped) of true -> {ok, bool_type}; false -> case is_mysql_decimal_text(Stripped) of true -> {ok, decimal_type}; false -> parse_sql_type(Stripped) end end. -file("src/sqlode/internal/model.gleam", 337). ?DOC(false). -spec parse_sql_type_for_engine(binary(), engine()) -> {ok, scalar_type()} | {error, nil}. parse_sql_type_for_engine(Type_text, Engine) -> case Engine of my_s_q_l -> case classify_mysql_type_text(Type_text) of {ok, T} -> {ok, T}; {error, nil} -> parse_sql_type(Type_text) end; postgre_s_q_l -> parse_sql_type(Type_text); s_q_lite -> parse_sql_type(Type_text) end.