diff --git a/lib/tds.ex b/lib/tds.ex index c174ee4..445af25 100644 --- a/lib/tds.ex +++ b/lib/tds.ex @@ -126,6 +126,12 @@ defmodule Tds do end end + def proc(pid, statement, params, opts \\ []) do + opts = Keyword.put_new(opts, :proc, statement) + + query(pid, statement, params, opts) + end + @spec execute(conn, Tds.Query.t(), list, [execute_option]) :: {:ok, Tds.Query.t(), Tds.Result.t()} | {:error, Tds.Error.t()} diff --git a/lib/tds/column.ex b/lib/tds/column.ex new file mode 100644 index 0000000..9573f30 --- /dev/null +++ b/lib/tds/column.ex @@ -0,0 +1,9 @@ +defmodule Tds.Column do + @type t :: %__MODULE__{ + name: String.t | nil, + type: Atom | nil, + opts: Keyword.t + } + + defstruct [name: "", type: nil, opts: []] +end diff --git a/lib/tds/messages.ex b/lib/tds/messages.ex index 9a09d2f..5531485 100644 --- a/lib/tds/messages.ex +++ b/lib/tds/messages.ex @@ -540,6 +540,12 @@ defmodule Tds.Messages do encode_rpc_params(params, "") end + defp encode_rpc(proc, params) when is_binary(proc) do + rpc_size = byte_size(proc) + rpc_name = to_little_ucs2(proc) + <> <> rpc_name <> <<0x00, 0x00>> <> encode_rpc_params(params, "") + end + # Finished processing params defp encode_rpc_params([], ret), do: ret diff --git a/lib/tds/protocol.ex b/lib/tds/protocol.ex index 4dc4d2e..4e28279 100644 --- a/lib/tds/protocol.ex +++ b/lib/tds/protocol.ex @@ -186,13 +186,15 @@ defmodule Tds.Protocol do %{sock: _sock} = s ) do params = opts[:parameters] || params + proc = opts[:proc] || nil Process.put(:resultset, Keyword.get(opts, :resultset, false)) - if params != [] do - send_param_query(query, params, s) - else - send_query(statement, s) + cond do + params != [] and is_nil(proc) -> send_param_query(query, params, s) + not is_nil(proc) -> send_proc(proc, params, s) + true -> send_query(statement, s) end + rescue exception -> {:error, exception, s} @@ -629,6 +631,21 @@ defmodule Tds.Protocol do end end + def send_proc(proc, params, s) do + params = Tds.Parameter.prepare_params(params) + msg = msg_rpc(proc: proc, params: params) + + case msg_send(msg, s) do + {:ok, %{result: result} = s} -> + {:ok, result, %{s | state: :ready}} + {:error, err, %{transaction: :started} = s} -> + {:error, err, %{s | transaction: :failed}} + err -> + err + end + end + + @spec send_param_query(Tds.Query.t(), list(), t) :: {:error, any()} | {:ok, %{optional(:result) => none()}} diff --git a/lib/tds/types.ex b/lib/tds/types.ex index d9c2cfe..39a2ff0 100644 --- a/lib/tds/types.ex +++ b/lib/tds/types.ex @@ -4,6 +4,7 @@ defmodule Tds.Types do use Bitwise alias Tds.Parameter + alias Tds.Column @year_1900_days :calendar.date_to_gregorian_days({1900, 1, 1}) @secs_in_min 60 @@ -66,6 +67,7 @@ defmodule Tds.Types do @tds_data_type_nchar 0xEF @tds_data_type_xml 0xF1 @tds_data_type_udt 0xF0 + @tds_data_type_tvp 0xF3 @tds_data_type_text 0x23 @tds_data_type_image 0x22 @tds_data_type_ntext 0x63 @@ -714,9 +716,9 @@ defmodule Tds.Types do size = byte_size(value) <> = value - Decimal.get_context() + Decimal.Context.get() |> Map.put(:precision, precision) - |> Decimal.set_context() + |> Decimal.Context.set() case sign do 0 -> Decimal.new(-1, value, -scale) @@ -763,6 +765,7 @@ defmodule Tds.Types do :date -> encode_date_type(param) :time -> encode_time_type(param) :uuid -> encode_uuid_type(param) + :tvp -> encode_tvp_type(param) _ -> encode_string_type(param) end end @@ -803,6 +806,12 @@ defmodule Tds.Types do {type, data, []} end + def encode_tvp_type(%Parameter{}) do + type = @tds_data_type_tvp + data = <> <> <<0, 0, 0>> + {type, data, []} + end + def encode_uuid_type(%Parameter{value: value}) do length = if value == nil do @@ -887,9 +896,9 @@ defmodule Tds.Types do end def encode_decimal_type(%Parameter{value: value}) do - d_ctx = Decimal.get_context() + d_ctx = Decimal.Context.get() d_ctx = %{d_ctx | precision: 38} - Decimal.set_context(d_ctx) + Decimal.Context.set(d_ctx) value_list = value @@ -942,9 +951,9 @@ defmodule Tds.Types do end def encode_float_type(%Parameter{value: %Decimal{} = value}) do - d_ctx = Decimal.get_context() + d_ctx = Decimal.Context.get() d_ctx = %{d_ctx | precision: 38} - Decimal.set_context(d_ctx) + Decimal.Context.set(d_ctx) value_list = value @@ -1034,6 +1043,8 @@ defmodule Tds.Types do :smalldatetime -> "smalldatetime" + :tvp -> "#{value.name} readonly" + :binary -> encode_binary_descriptor(value) @@ -1129,9 +1140,9 @@ defmodule Tds.Types do end def encode_decimal_descriptor(%Parameter{value: %Decimal{} = dec}) do - d_ctx = Decimal.get_context() + d_ctx = Decimal.Context.get() d_ctx = %{d_ctx | precision: 38} - Decimal.set_context(d_ctx) + Decimal.Context.set(d_ctx) value_list = dec @@ -1194,6 +1205,42 @@ defmodule Tds.Types do @doc """ Data encoding """ + def encode_column_type(%Column{type: type} = col) when type != nil do + case type do + :varchar -> encode_bigvarchar_col_type(col) + :boolean -> encode_binary_type(%Parameter{type: :boolean, value: nil}) + :varbinary -> encode_varbinary_col_type(col) + :int -> encode_integer_type(%Parameter{type: :integer, value: nil}) + :decimal -> encode_decimal_type(%Parameter{type: :decimal, value: nil}) + :float -> encode_float_type(%Parameter{type: :float, value: nil}) + :datetime -> encode_datetime_type(%Parameter{type: :datetime, value: nil}) + :smalldatetime -> encode_smalldatetime_type(%Parameter{type: :smalldatetime, value: nil}) + :datetime2 -> encode_datetime2_type(%Parameter{type: :datetime2, value: nil}) + :datetimeoffset -> encode_datetimeoffset_type(%Parameter{type: :datetimeoffset, value: nil}) + :date -> encode_date_type(%Parameter{type: :datetimeoffset, value: nil}) + :time -> encode_time_type(%Parameter{type: :time, value: nil}) + :uuid -> encode_uuid_type(%Parameter{type: :uuid, value: nil}) + end + end + + def encode_bigvarchar_col_type(%Column{opts: opts} = _col) do + type = @tds_data_type_bigvarchar + length = Keyword.get(opts, :length, 0) + collation = <<0x00, 0x00, 0x00, 0x00, 0x00>> + bin_length = if length <= 8000, do: <<8000::little-unsigned-16>>, else: <<0xFF, 0xFF>> + data = <> <> bin_length <> collation + + {type, data, length: length} + end + + def encode_varbinary_col_type(%Column{opts: opts} = _col) do + type = @tds_data_type_bigvarbinary + length = Keyword.get(opts, :length, 0) + bin_length = if length <= 8000, do: <<8000::little-unsigned-16>>, else: <<0xFF, 0xFF>> + data = <> <> bin_length + + {type, data, length: length} + end # binary def encode_data(@tds_data_type_bigvarbinary, value, attr) @@ -1211,7 +1258,54 @@ defmodule Tds.Types do end end + #tvp + def encode_data(@tds_data_type_tvp, %{columns: nil}, _attrs), + do: <<0xFF :: little-unsigned-16, 0x00, 0x00 >> + + def encode_data(@tds_data_type_tvp, %{columns: columns, rows: rows}, _attrs) do + column_length = <> + {column_attrs, column_meta} = Enum.reduce(columns, {[], <<>>}, fn (%Column{} = param, {attrs, acc_bin}) -> + {bin_type, data, attr} = encode_column_type(param) + bin = acc_bin <> <<0x00 :: little-unsigned-32, 0x00 :: little-unsigned-16 >> <> data <> <<0x00>> + + {[{bin_type, attr} | attrs], bin} + end) + + row_data = Enum.reduce(rows, <<>>, fn (params, row_acc) -> + row_bin = column_attrs + |> Enum.reverse + |> Enum.zip(params) + |> Enum.reduce(<<>>, fn ({{type, attr}, param}, acc) -> + acc <> encode_data(type, param, attr) + end) + + row_acc <> << 0x01 >> <> row_bin + end) + + column_length <> column_meta <> <<0x00>> <> row_data <> <<0x00>> + end + # string + def encode_data(@tds_data_type_bigvarchar, nil, opts) do + length = Keyword.get(opts, :length, 0) + if length <= 8000, + do: <<65535::little-unsigned-16>>, + else: <<@tds_plp_null::little-unsigned-64>> + end + + def encode_data(@tds_data_type_bigvarchar, value, _opts) do + value_size = byte_size(value) + cond do + value_size <= 0 -> + <<0x00::unsigned-64, 0x00::unsigned-32>> + value_size > 8000 -> + encode_plp(value) + true -> + <> <> value + end + end + + def encode_data(@tds_data_type_nvarchar, nil, _), do: <<@tds_plp_null::little-unsigned-64>> @@ -1282,9 +1376,9 @@ defmodule Tds.Types do # decimal def encode_data(@tds_data_type_decimaln, %Decimal{} = value, attr) do - d_ctx = Decimal.get_context() + d_ctx = Decimal.Context.get() d_ctx = %{d_ctx | precision: 38} - Decimal.set_context(d_ctx) + Decimal.Context.set(d_ctx) precision = attr[:precision] d = diff --git a/mix.lock b/mix.lock index abb7285..861299f 100644 --- a/mix.lock +++ b/mix.lock @@ -1,28 +1,31 @@ %{ "binpp": {:hex, :binpp, "1.1.1", "a01060124841ed3a22ed98ddeafc10d14166d2991683d5ce907a3a410559c9ee", [:rebar3], [], "hexpm", "2ef9fb04a1c7a79644c84e8402e1dc5a7f2bf2b182c211329465f3f188e923fa"}, "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, - "certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm", "805abd97539caf89ec6d4732c91e62ba9da0cda51ac462380bbd28ee697a8c42"}, - "connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm", "4a0850c9be22a43af9920a71ab17c051f5f7d45c209e40269a1938832510e4d9"}, + "certifi": {:hex, :certifi, "2.6.1", "dbab8e5e155a0763eea978c913ca280a6b544bfa115633fa20249c3d396d9493", [:rebar3], [], "hexpm", "524c97b4991b3849dd5c17a631223896272c6b0af446778ba4675a1dff53bb7e"}, + "connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"}, "credo": {:hex, :credo, "0.10.2", "03ad3a1eff79a16664ed42fc2975b5e5d0ce243d69318060c626c34720a49512", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "539596b6774069260d5938aa73042a2f5157e1c0215aa35f5a53d83889546d14"}, - "db_connection": {:hex, :db_connection, "2.2.0", "e923e88887cd60f9891fd324ac5e0290954511d090553c415fbf54be4c57ee63", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm", "bdf196feedfa6b83071e808b2b086fb113f8a1c4c7761f6eff6fe4b96aba0086"}, - "decimal": {:hex, :decimal, "1.8.1", "a4ef3f5f3428bdbc0d35374029ffcf4ede8533536fa79896dd450168d9acdf3c", [:mix], [], "hexpm", "3cb154b00225ac687f6cbd4acc4b7960027c757a5152b369923ead9ddbca7aec"}, + "db_connection": {:hex, :db_connection, "2.4.0", "d04b1b73795dae60cead94189f1b8a51cc9e1f911c234cc23074017c43c031e5", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ad416c21ad9f61b3103d254a71b63696ecadb6a917b36f563921e0de00d7d7c8"}, + "decimal": {:hex, :decimal, "1.9.0", "83e8daf59631d632b171faabafb4a9f4242c514b0a06ba3df493951c08f64d07", [:mix], [], "hexpm", "b1f2343568eed6928f3e751cf2dffde95bfaa19dd95d09e8a9ea92ccfd6f7d85"}, "dialyxir": {:hex, :dialyxir, "0.5.1", "b331b091720fd93e878137add264bac4f644e1ddae07a70bf7062c7862c4b952", [:mix], [], "hexpm", "6c32a70ed5d452c6650916555b1f96c79af5fc4bf286997f8b15f213de786f73"}, "earmark": {:hex, :earmark, "1.4.3", "364ca2e9710f6bff494117dbbd53880d84bebb692dafc3a78eb50aa3183f2bfd", [:mix], [], "hexpm", "8cf8a291ebf1c7b9539e3cddb19e9cef066c2441b1640f13c34c1d3cfc825fec"}, - "ex_doc": {:hex, :ex_doc, "0.21.3", "857ec876b35a587c5d9148a2512e952e24c24345552259464b98bfbb883c7b42", [:mix], [{:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "0db1ee8d1547ab4877c5b5dffc6604ef9454e189928d5ba8967d4a58a801f161"}, - "excoveralls": {:hex, :excoveralls, "0.12.2", "a513defac45c59e310ac42fcf2b8ae96f1f85746410f30b1ff2b710a4b6cd44b", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "151c476331d49b45601ffc45f43cb3a8beb396b02a34e3777fea0ad34ae57d89"}, - "hackney": {:hex, :hackney, "1.15.2", "07e33c794f8f8964ee86cebec1a8ed88db5070e52e904b8f12209773c1036085", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.5", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "e0100f8ef7d1124222c11ad362c857d3df7cb5f4204054f9f0f4a728666591fc"}, - "idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "4bdd305eb64e18b0273864920695cb18d7a2021f31a11b9c5fbcd9a253f936e2"}, - "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fdf843bca858203ae1de16da2ee206f53416bbda5dc8c9e78f43243de4bc3afe"}, - "makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "a10c6eb62cca416019663129699769f0c2ccf39428b3bb3c0cb38c718a0c186d"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "d4b316c7222a85bbaa2fd7c6e90e37e953257ad196dc229505137c5e505e9eff"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.13", "0c98163e7d04a15feb62000e1a891489feb29f3d10cb57d4f845c405852bbef8", [:mix], [], "hexpm", "d602c26af3a0af43d2f2645613f65841657ad6efc9f0e361c3b6c06b578214ba"}, + "ex_doc": {:hex, :ex_doc, "0.25.1", "4b736fa38dc76488a937e5ef2944f5474f3eff921de771b25371345a8dc810bc", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "3200b0a69ddb2028365281fbef3753ea9e728683863d8cdaa96580925c891f67"}, + "excoveralls": {:hex, :excoveralls, "0.14.2", "f9f5fd0004d7bbeaa28ea9606251bb643c313c3d60710bad1f5809c845b748f0", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "ca6fd358621cb4d29311b29d4732c4d47dac70e622850979bc54ed9a3e50f3e1"}, + "hackney": {:hex, :hackney, "1.17.4", "99da4674592504d3fb0cfef0db84c3ba02b4508bae2dff8c0108baa0d6e0977c", [:rebar3], [{:certifi, "~>2.6.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "de16ff4996556c8548d512f4dbe22dd58a587bf3332e7fd362430a7ef3986b16"}, + "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, + "jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"}, + "makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.15.1", "b5888c880d17d1cc3e598f05cdb5b5a91b7b17ac4eaf5f297cb697663a1094dd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "db68c173234b07ab2a07f645a5acdc117b9f99d69ebf521821d89690ae6c6ec8"}, + "makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, - "nimble_parsec": {:hex, :nimble_parsec, "0.5.3", "def21c10a9ed70ce22754fdeea0810dafd53c2db3219a0cd54cf5526377af1c6", [:mix], [], "hexpm", "589b5af56f4afca65217a1f3eb3fee7e79b09c40c742fddc1c312b3ac0b3399f"}, - "parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm", "17ef63abde837ad30680ea7f857dd9e7ced9476cdd7b0394432af4bfc241b960"}, - "rustler": {:hex, :rustler, "0.21.0", "68cc4fc015d0b9541865ea78e78e9ef2dd91ee4be80bf543fd15791102a45aca", [:mix], [{:toml, "~> 0.5.2", [hex: :toml, repo: "hexpm", optional: false]}], "hexpm", "e5429378c397f37f1091a35593b153aee1925e197c6842d04648d802edb52f80"}, - "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5", "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b", [:make, :mix, :rebar3], [], "hexpm", "13104d7897e38ed7f044c4de953a6c28597d1c952075eb2e328bc6d6f2bfc496"}, + "nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"}, + "parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"}, + "rustler": {:hex, :rustler, "0.21.1", "5299980be32da997c54382e945bacaa015ed97a60745e1e639beaf6a7b278c65", [:mix], [{:toml, "~> 0.5.2", [hex: :toml, repo: "hexpm", optional: false]}], "hexpm", "6ee1651e10645b2b2f3bb70502bf180341aa058709177e9bc28c105934094bc6"}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"}, "tds_encoding": {:hex, :tds_encoding, "1.0.0", "1784d7aa26c315bb4f62b926cb7f3331bfc4eee15508f3d3ab48bc0ac9802a61", [:mix], [{:rustler, "~> 0.21.0", [hex: :rustler, repo: "hexpm", optional: false]}], "hexpm", "c60a8400232a22444be0757b94e91ea9fe3b6b3faa8d22c7afd38217214c082a"}, + "telemetry": {:hex, :telemetry, "1.0.0", "0f453a102cdf13d506b7c0ab158324c337c41f1cc7548f0bc0e130bbf0ae9452", [:rebar3], [], "hexpm", "73bc09fa59b4a0284efb4624335583c528e07ec9ae76aca96ea0673850aec57a"}, "toml": {:hex, :toml, "0.5.2", "e471388a8726d1ce51a6b32f864b8228a1eb8edc907a0edf2bb50eab9321b526", [:mix], [], "hexpm", "f1e3dabef71fb510d015fad18c0e05e7c57281001141504c6b69d94e99750a07"}, - "tzdata": {:hex, :tzdata, "1.0.3", "73470ad29dde46e350c60a66e6b360d3b99d2d18b74c4c349dbebbc27a09a3eb", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "a6e1ee7003c4d04ecbd21dd3ec690d4c6662db5d3bbdd7262d53cdf5e7c746c1"}, - "unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm", "1d1848c40487cdb0b30e8ed975e34e025860c02e419cb615d255849f3427439d"}, + "tzdata": {:hex, :tzdata, "1.1.0", "72f5babaa9390d0f131465c8702fa76da0919e37ba32baa90d93c583301a8359", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "18f453739b48d3dc5bcf0e8906d2dc112bb40baafe2c707596d89f3c8dd14034"}, + "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, }