PageRenderTime 71ms CodeModel.GetById 16ms app.highlight 51ms RepoModel.GetById 1ms app.codeStats 1ms

/src/dbdrivers/postgresql/epgsql/pgsql_binary.erl

http://github.com/zotonic/zotonic
Erlang | 88 lines | 77 code | 9 blank | 2 comment | 12 complexity | c097561fbe3bf5985c5b0304bfdfeaa9 MD5 | raw file
 1%%% Copyright (C) 2008 - Will Glozer.  All rights reserved.
 2%%% 20090311 Marc Worrell - Added support for encoding terms and lists of terms in bytea values
 3
 4-module(pgsql_binary).
 5
 6-export([encode/3, decode/3, supports/1]).
 7
 8-include_lib("zotonic.hrl").
 9
10-define(int32, 1/big-signed-unit:32).
11-define(TERM_MAGIC_NUMBER, 16#01326A3A:1/big-unsigned-unit:32).
12
13
14encode(_Any, null, _UseIntDT)  -> <<-1:?int32>>;
15encode(_Any, undefined, _UseIntDT)  -> <<-1:?int32>>;
16encode(bool, <<1>>, _UseIntDT) -> <<1:?int32, 1:1/big-signed-unit:8>>;
17encode(bool, <<>>, _UseIntDT)  -> <<1:?int32, 0:1/big-signed-unit:8>>;
18encode(bool, true, _UseIntDT)  -> <<1:?int32, 1:1/big-signed-unit:8>>;
19encode(bool, false, _UseIntDT) -> <<1:?int32, 0:1/big-signed-unit:8>>;
20encode(int2, N, UseIntDT) when is_binary(N); is_list(N) -> encode(int2, z_convert:to_integer(N), UseIntDT);
21encode(int4, N, UseIntDT) when is_binary(N); is_list(N) -> encode(int4, z_convert:to_integer(N), UseIntDT);
22encode(int8, N, UseIntDT) when is_binary(N); is_list(N) -> encode(int8, z_convert:to_integer(N), UseIntDT);
23encode(int2, N, _UseIntDT)     -> <<2:?int32, N:1/big-signed-unit:16>>;
24encode(int4, N, _UseIntDT)     -> <<4:?int32, N:1/big-signed-unit:32>>;
25encode(int8, N, _UseIntDT)     -> <<8:?int32, N:1/big-signed-unit:64>>;
26encode(float4, N, _UseIntDT)   -> <<4:?int32, N:1/big-float-unit:32>>;
27encode(float8, N, _UseIntDT)   -> <<8:?int32, N:1/big-float-unit:64>>;
28encode(bpchar, C, _UseIntDT) when is_integer(C) -> <<1:?int32, C:1/big-unsigned-unit:8>>;
29encode(bpchar, B, _UseIntDT) when is_binary(B)  -> <<(byte_size(B)):?int32, B/binary>>;
30encode(Type, B, UseIntDT) when Type == time; Type == timetz          -> pgsql_datetime:encode(Type, B, UseIntDT);
31encode(Type, B, UseIntDT) when Type == date; Type == timestamp       -> pgsql_datetime:encode(Type, B, UseIntDT);
32encode(Type, B, UseIntDT) when Type == timestamptz; Type == interval -> pgsql_datetime:encode(Type, B, UseIntDT);
33encode(bytea, B, _UseIntDT) when is_binary(B)   -> <<(byte_size(B)):?int32, B/binary>>;
34encode(text, B, _UseIntDT) when is_binary(B)    -> <<(byte_size(B)):?int32, B/binary>>;
35encode(varchar, B, _UseIntDT) when is_binary(B) -> <<(byte_size(B)):?int32, B/binary>>;
36encode(bytea, T, UseIntDT) when is_tuple(T)   -> 
37    B = term_to_binary(T),
38    encode(bytea, <<?TERM_MAGIC_NUMBER, B/binary>>, UseIntDT);
39encode(bytea, [T|_Rest]=L, UseIntDT) when is_tuple(T)   -> 
40    B = term_to_binary(L),
41    encode(bytea, <<?TERM_MAGIC_NUMBER, B/binary>>, UseIntDT);
42encode(Type, A, UseIntDT) when is_atom(A)      -> encode(Type, atom_to_list(A), UseIntDT);
43encode(Type, L, UseIntDT) when is_list(L)      -> encode(Type, iolist_to_binary(L), UseIntDT);
44encode(_Type, _Value, _UseIntDT)                -> {error, unsupported}.
45
46decode(bool, <<1:1/big-signed-unit:8>>, _UseIntDT)     -> true;
47decode(bool, <<0:1/big-signed-unit:8>>, _UseIntDT)     -> false;
48decode(bool, <<"t">>, _UseIntDT) -> true;
49decode(bool, <<"f">>, _UseIntDT) -> false;
50decode(bpchar, <<C:1/big-unsigned-unit:8>>, _UseIntDT) -> C;
51decode(int2, <<N:1/big-signed-unit:16>>, _UseIntDT)    -> N;
52decode(int4, <<N:1/big-signed-unit:32>>, _UseIntDT)    -> N;
53decode(int8, <<N:1/big-signed-unit:64>>, _UseIntDT)    -> N;
54decode(float4, <<N:1/big-float-unit:32>>, _UseIntDT)   -> N;
55decode(float8, <<N:1/big-float-unit:64>>, _UseIntDT)   -> N;
56decode(record, <<_:?int32, Rest/binary>>, UseIntDT)   -> list_to_tuple(decode_record(Rest, UseIntDT, []));
57decode(Type, B, UseIntDT) when Type == time; Type == timetz          -> pgsql_datetime:decode(Type, B, UseIntDT);
58decode(Type, B, UseIntDT) when Type == date; Type == timestamp       -> pgsql_datetime:decode(Type, B, UseIntDT);
59decode(Type, B, UseIntDT) when Type == timestamptz; Type == interval -> pgsql_datetime:decode(Type, B, UseIntDT);
60decode(bytea, <<?TERM_MAGIC_NUMBER, B/binary>>, _UseIntDT) -> binary_to_term(B);
61decode(_Other, Bin, _UseIntDT) -> Bin.
62
63decode_record(<<>>, _UseIntDT, Acc) ->
64    lists:reverse(Acc);
65decode_record(<<_Type:?int32, -1:?int32, Rest/binary>>, UseIntDT, Acc) ->
66    decode_record(Rest, UseIntDT, [undefined | Acc]);
67decode_record(<<Type:?int32, Len:?int32, Value:Len/binary, Rest/binary>>, UseIntDT, Acc) ->
68    Value2 = decode(pgsql_types:oid2type(Type), Value, UseIntDT),
69    decode_record(Rest, UseIntDT, [Value2 | Acc]).
70
71supports(bool)    -> true;
72supports(bpchar)  -> true;
73supports(int2)    -> true;
74supports(int4)    -> true;
75supports(int8)    -> true;
76supports(float4)  -> true;
77supports(float8)  -> true;
78supports(bytea)   -> true;
79supports(text)    -> true;
80supports(varchar) -> true;
81supports(record)  -> true;
82supports(date)    -> true;
83supports(time)    -> true;
84supports(timetz)  -> true;
85supports(timestamp)   -> true;
86supports(timestamptz) -> true;
87supports(interval)    -> true;
88supports(_Type)       -> false.