Packages
postgrex
0.20.0
1.0.0-rc.1
retired
1.0.0-rc.0
retired
0.22.3
0.22.2
0.22.1
0.22.0
0.21.1
0.21.0
0.20.0
0.19.3
0.19.2
0.19.1
0.19.0
0.18.0
0.17.5
0.17.4
0.17.3
0.17.2
0.17.1
0.17.0
0.16.5
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.13
0.15.12
0.15.11
0.15.10
0.15.9
0.15.8
0.15.7
0.15.6
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.3
0.14.2
0.14.1
0.14.0
0.14.0-rc.1
0.14.0-rc.0
0.13.5
0.13.4
0.13.3
0.13.2
0.13.1
0.13.0
0.13.0-rc.0
0.12.2
0.12.1
0.12.0
0.11.2
0.11.1
0.11.0
0.10.0
0.9.1
0.9.0
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.0
0.6.0
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.2
PostgreSQL driver for Elixir
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/postgrex/extensions/multirange.ex
defmodule Postgrex.Extensions.Multirange do
@moduledoc false
import Postgrex.BinaryUtils, warn: false
@behaviour Postgrex.SuperExtension
def init(_), do: nil
def matching(_state), do: [send: "multirange_send"]
def format(_), do: :super_binary
def oids(%Postgrex.TypeInfo{base_type: base_oid}, _) do
[base_oid]
end
def encode(_) do
quote location: :keep do
%Postgrex.Multirange{ranges: ranges}, [_oid], [type] when is_list(ranges) ->
# encode_value/2 defined by TypeModule
bound_encoder = &encode_value(&1, type)
unquote(__MODULE__).encode(ranges, bound_encoder)
other, _, _ ->
raise DBConnection.EncodeError, Postgrex.Utils.encode_msg(other, Postgrex.Multirange)
end
end
def decode(_) do
quote location: :keep do
<<len::int32(), data::binary-size(len)>>, [_oid], [type] ->
<<_num_ranges::int32(), ranges::binary>> = data
# decode_list/2 defined by TypeModule
sub_type_with_mod =
case type do
{extension, sub_oids, sub_types} -> {extension, sub_oids, sub_types, nil}
extension -> {extension, nil}
end
bound_decoder = &decode_list(&1, sub_type_with_mod)
unquote(__MODULE__).decode(ranges, bound_decoder, [])
end
end
## Helpers
def encode(ranges, bound_encoder) do
encoded_ranges =
Enum.map(ranges, fn range ->
%{lower: lower, upper: upper} = range
lower = if is_atom(lower), do: lower, else: bound_encoder.(lower)
upper = if is_atom(upper), do: upper, else: bound_encoder.(upper)
Postgrex.Extensions.Range.encode(range, lower, upper)
end)
num_ranges = length(ranges)
iodata = [<<num_ranges::int32()>> | encoded_ranges]
[<<IO.iodata_length(iodata)::int32()>> | iodata]
end
def decode(<<>>, _bound_decoder, acc), do: %Postgrex.Multirange{ranges: Enum.reverse(acc)}
def decode(<<len::int32(), encoded_range::binary-size(len), rest::binary>>, bound_decoder, acc) do
<<flags, data::binary>> = encoded_range
decoded_range =
case bound_decoder.(data) do
[upper, lower] ->
Postgrex.Extensions.Range.decode(flags, [lower, upper])
empty_or_one ->
Postgrex.Extensions.Range.decode(flags, empty_or_one)
end
decode(rest, bound_decoder, [decoded_range | acc])
end
end