Current section
Files
Jump to
Current section
Files
src/sqlode@internal@model.erl
-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
one ->
true;
many ->
true;
batch_one ->
true;
batch_many ->
true;
_ ->
false
end.
-file("src/sqlode/internal/model.gleam", 186).
?DOC(false).
-spec parse_query_command(binary()) -> {ok, sqlode@runtime:query_command()} |
{error, binary()}.
parse_query_command(Value) ->
case Value of
<<":one"/utf8>> ->
{ok, one};
<<":many"/utf8>> ->
{ok, many};
<<":exec"/utf8>> ->
{ok, exec};
<<":execresult"/utf8>> ->
{ok, exec_result};
<<":execrows"/utf8>> ->
{ok, exec_rows};
<<":execlastid"/utf8>> ->
{ok, exec_last_id};
<<":batchone"/utf8>> ->
{ok, batch_one};
<<":batchmany"/utf8>> ->
{ok, batch_many};
<<":batchexec"/utf8>> ->
{ok, batch_exec};
<<":copyfrom"/utf8>> ->
{ok, 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", 207).
?DOC(false).
-spec query_command_to_string(sqlode@runtime:query_command()) -> binary().
query_command_to_string(Command) ->
case Command of
one ->
<<"One"/utf8>>;
many ->
<<"Many"/utf8>>;
exec ->
<<"Exec"/utf8>>;
exec_result ->
<<"ExecResult"/utf8>>;
exec_rows ->
<<"ExecRows"/utf8>>;
exec_last_id ->
<<"ExecLastId"/utf8>>;
batch_one ->
<<"BatchOne"/utf8>>;
batch_many ->
<<"BatchMany"/utf8>>;
batch_exec ->
<<"BatchExec"/utf8>>;
copy_from ->
<<"CopyFrom"/utf8>>
end.
-file("src/sqlode/internal/model.gleam", 364).
?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", 374).
?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", 385).
?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", 426).
?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", 438).
?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", 453).
?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", 412).
?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", 460).
?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", 397).
?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", 311).
?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", 348).
?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", 334).
?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.