|
@@ -16,6 +16,13 @@
|
|
|
|
|
|
-define(datetime, (get(datetime_mod))).
|
|
-define(datetime, (get(datetime_mod))).
|
|
|
|
|
|
|
|
+-define(INET, 2).
|
|
|
|
+-define(INET6, 3).
|
|
|
|
+-define(IP_SIZE, 4).
|
|
|
|
+-define(IP6_SIZE, 16).
|
|
|
|
+-define(MAX_IP_MASK, 32).
|
|
|
|
+-define(MAX_IP6_MASK, 128).
|
|
|
|
+
|
|
new_codec([]) -> #codec{}.
|
|
new_codec([]) -> #codec{}.
|
|
|
|
|
|
update_type_cache(TypeInfos, Codec) ->
|
|
update_type_cache(TypeInfos, Codec) ->
|
|
@@ -67,6 +74,8 @@ encode({array, Type}, L, Codec) when is_list(L) -> encode_array(Type, type2oid(T
|
|
encode(hstore, {L}, _) when is_list(L) -> encode_hstore(L);
|
|
encode(hstore, {L}, _) when is_list(L) -> encode_hstore(L);
|
|
encode(point, {X,Y}, _) -> encode_point({X,Y});
|
|
encode(point, {X,Y}, _) -> encode_point({X,Y});
|
|
encode(geometry, Data, _) -> encode_geometry(Data);
|
|
encode(geometry, Data, _) -> encode_geometry(Data);
|
|
|
|
+encode(cidr, B, Codec) -> encode(bytea, encode_net(B), Codec);
|
|
|
|
+encode(inet, B, Codec) -> encode(bytea, encode_net(B), Codec);
|
|
encode(Type, L, Codec) when is_list(L) -> encode(Type, list_to_binary(L), Codec);
|
|
encode(Type, L, Codec) when is_list(L) -> encode(Type, list_to_binary(L), Codec);
|
|
encode(_Type, _Value, _) -> {error, unsupported}.
|
|
encode(_Type, _Value, _) -> {error, unsupported}.
|
|
|
|
|
|
@@ -87,6 +96,8 @@ decode(timestamptz = Type, B, _) -> ?datetime:decode(Type, B);
|
|
decode(interval = Type, B, _) -> ?datetime:decode(Type, B);
|
|
decode(interval = Type, B, _) -> ?datetime:decode(Type, B);
|
|
decode(uuid, B, _) -> decode_uuid(B);
|
|
decode(uuid, B, _) -> decode_uuid(B);
|
|
decode(hstore, Hstore, _) -> decode_hstore(Hstore);
|
|
decode(hstore, Hstore, _) -> decode_hstore(Hstore);
|
|
|
|
+decode(inet, B, _) -> decode_net(B);
|
|
|
|
+decode(cidr, B, _) -> decode_net(B);
|
|
decode({array, _Type}, B, Codec) -> decode_array(B, Codec);
|
|
decode({array, _Type}, B, Codec) -> decode_array(B, Codec);
|
|
decode(point, B, _) -> decode_point(B);
|
|
decode(point, B, _) -> decode_point(B);
|
|
decode(geometry, B, _) -> ewkb:decode_geometry(B);
|
|
decode(geometry, B, _) -> ewkb:decode_geometry(B);
|
|
@@ -142,6 +153,19 @@ encode_hstore_string(Str) when is_float(Str) ->
|
|
encode_hstore_string(iolist_to_binary(io_lib:format("~w", [Str])));
|
|
encode_hstore_string(iolist_to_binary(io_lib:format("~w", [Str])));
|
|
encode_hstore_string(Str) when is_binary(Str) -> <<(byte_size(Str)):?int32, Str/binary>>.
|
|
encode_hstore_string(Str) when is_binary(Str) -> <<(byte_size(Str)):?int32, Str/binary>>.
|
|
|
|
|
|
|
|
+encode_net({{_, _, _, _} = IP, Mask}) ->
|
|
|
|
+ Bin = list_to_binary(tuple_to_list(IP)),
|
|
|
|
+ <<?INET, Mask, 1, ?IP_SIZE, Bin/binary>>;
|
|
|
|
+encode_net({{_, _, _, _, _, _, _, _} = IP, Mask}) ->
|
|
|
|
+ Bin = << <<X:16>> || X <- tuple_to_list(IP) >>,
|
|
|
|
+ <<?INET6, Mask, 1, ?IP6_SIZE, Bin/binary>>;
|
|
|
|
+encode_net({_, _, _, _} = IP) ->
|
|
|
|
+ Bin = list_to_binary(tuple_to_list(IP)),
|
|
|
|
+ <<?INET, ?MAX_IP_MASK, 0, ?IP_SIZE, Bin/binary>>;
|
|
|
|
+encode_net({_, _, _, _, _, _, _, _} = IP) ->
|
|
|
|
+ Bin = << <<X:16>> || X <- tuple_to_list(IP) >>,
|
|
|
|
+ <<?INET6, ?MAX_IP6_MASK, 0, ?IP6_SIZE, Bin/binary>>.
|
|
|
|
+
|
|
decode_array(<<NDims:?int32, _HasNull:?int32, Oid:?int32, Rest/binary>>, Codec) ->
|
|
decode_array(<<NDims:?int32, _HasNull:?int32, Oid:?int32, Rest/binary>>, Codec) ->
|
|
{Dims, Data} = erlang:split_binary(Rest, NDims * 2 * 4),
|
|
{Dims, Data} = erlang:split_binary(Rest, NDims * 2 * 4),
|
|
Lengths = [Len || <<Len:?int32, _LBound:?int32>> <= Dims],
|
|
Lengths = [Len || <<Len:?int32, _LBound:?int32>> <= Dims],
|
|
@@ -197,8 +221,15 @@ encode_geometry(Data) ->
|
|
Size = byte_size(Bin),
|
|
Size = byte_size(Bin),
|
|
<<Size:?int32, Bin/binary>>.
|
|
<<Size:?int32, Bin/binary>>.
|
|
|
|
|
|
-supports(geometry) -> true;
|
|
|
|
-supports(point) -> true;
|
|
|
|
|
|
+decode_net(<<?INET, Mask, 1, ?IP_SIZE, Bin/binary>>) ->
|
|
|
|
+ {list_to_tuple(binary_to_list(Bin)), Mask};
|
|
|
|
+decode_net(<<?INET6, Mask, 1, ?IP6_SIZE, Bin/binary>>) ->
|
|
|
|
+ {list_to_tuple([X || <<X:16>> <= Bin]), Mask};
|
|
|
|
+decode_net(<<?INET, ?MAX_IP_MASK, 0, ?IP_SIZE, Bin/binary>>) ->
|
|
|
|
+ list_to_tuple(binary_to_list(Bin));
|
|
|
|
+decode_net(<<?INET6, ?MAX_IP6_MASK, 0, ?IP6_SIZE, Bin/binary>>) ->
|
|
|
|
+ list_to_tuple([X || <<X:16>> <= Bin]).
|
|
|
|
+
|
|
supports(bool) -> true;
|
|
supports(bool) -> true;
|
|
supports(bpchar) -> true;
|
|
supports(bpchar) -> true;
|
|
supports(int2) -> true;
|
|
supports(int2) -> true;
|
|
@@ -218,6 +249,10 @@ supports(timestamptz) -> true;
|
|
supports(interval) -> true;
|
|
supports(interval) -> true;
|
|
supports(uuid) -> true;
|
|
supports(uuid) -> true;
|
|
supports(hstore) -> true;
|
|
supports(hstore) -> true;
|
|
|
|
+supports(cidr) -> true;
|
|
|
|
+supports(inet) -> true;
|
|
|
|
+supports(geometry) -> true;
|
|
|
|
+supports(point) -> true;
|
|
supports({array, bool}) -> true;
|
|
supports({array, bool}) -> true;
|
|
supports({array, int2}) -> true;
|
|
supports({array, int2}) -> true;
|
|
supports({array, int4}) -> true;
|
|
supports({array, int4}) -> true;
|
|
@@ -235,4 +270,6 @@ supports({array, interval}) -> true;
|
|
supports({array, hstore}) -> true;
|
|
supports({array, hstore}) -> true;
|
|
supports({array, varchar}) -> true;
|
|
supports({array, varchar}) -> true;
|
|
supports({array, uuid}) -> true;
|
|
supports({array, uuid}) -> true;
|
|
|
|
+supports({array, cidr}) -> true;
|
|
|
|
+supports({array, inet}) -> true;
|
|
supports(_Type) -> false.
|
|
supports(_Type) -> false.
|