Skip to content

Commit

Permalink
Merge pull request #177 from erlangbureau/stage
Browse files Browse the repository at this point in the history
clean up decode
  • Loading branch information
vstavskyi authored Mar 3, 2024
2 parents 3cf0438 + ae3f982 commit 9632b94
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 95 deletions.
14 changes: 6 additions & 8 deletions src/jamdb_oracle_conn.erl
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ sql_query(#oraclient{conn_state=connected} = State, {fetch, Cursor, RowFormat, L
handle_resp({Cursor, RowFormat, [LastRow]}, State2);
sql_query(#oraclient{conn_state=connected} = State, {Query, Bind, Batch, Fetch}) ->
{ok, State2} = send_req(exec, State, {Query, Bind, Batch}),
#oraclient{server=Ver, defcols=DefCol, params=RowFormat, type=Type} = State2,
handle_resp(get_param(defcols, {DefCol, Ver, RowFormat, Type}),
#oraclient{defcols=DefCol, params=RowFormat, type=Type} = State2,
handle_resp(get_param(defcols, {DefCol, RowFormat, Type}),
State2#oraclient{type=get_param(type, {Type, Fetch})});
sql_query(#oraclient{conn_state=connected, timeouts={_Tout, ReadTout}} = State, {Query, Bind}) ->
case lists:nth(1, string:tokens(string:to_upper(Query)," \t;")) of
Expand Down Expand Up @@ -276,7 +276,7 @@ handle_resp(Acc, #oraclient{socket=Socket, sdu=Length, timeouts=Touts} = State)
end.

handle_resp(Data, Acc, #oraclient{type=Type, cursors=Cursors} = State) ->
case ?DECODER:decode_token(Data, Acc) of
case ?DECODER:decode_two_task(Data, Acc) of
{0, _RowNumber, Cursor, {LCursor, RowFormat}, []} when Type =/= change, RowFormat =/= [] ->
Type2 = if LCursor =:= Cursor -> Type; true -> cursor end,
{ok, State2} = send_req(fetch, State, {Cursor, RowFormat}),
Expand Down Expand Up @@ -366,11 +366,9 @@ get_param(defcols, {Sum, Cursors}) when is_pid(Cursors) ->
{Sum, proplists:get_value(Sum, Acc, {0,0,[]})};
get_param(defcols, {_Sum, {LCursor, Cursor, _RowFormat}}) when LCursor =:= Cursor -> {LCursor, 0};
get_param(defcols, {_Sum, {LCursor, Cursor, _RowFormat}}) -> {LCursor, Cursor};
get_param(defcols, {{_Sum, {LCursor, Cursor, _RowFormat}}, Ver, RowFormat, Type}) when LCursor =:= 0; LCursor =/= Cursor ->
{Ver, RowFormat, Type};
get_param(defcols, {{_Sum, {_LCursor, _Cursor, RowFormat}}, Ver, _RowFormat, Type}) when Type =/= select ->
{Ver, RowFormat, Type};
get_param(defcols, {{_Sum, {LCursor, _Cursor, RowFormat}}, _Ver, _RowFormat, Type}) ->
get_param(defcols, {{_Sum, {LCursor, Cursor, _RowFormat}}, RowFormat, Type}) when LCursor =:= 0; LCursor =/= Cursor ->
{0, RowFormat, Type};
get_param(defcols, {{_Sum, {LCursor, _Cursor, RowFormat}}, _RowFormat, Type}) ->
{LCursor, RowFormat, Type};
get_param(type, {true, false, [], Fetch}) -> {select, Fetch};
get_param(type, {false, true, [], _Fetch}) -> {change, 0};
Expand Down
154 changes: 74 additions & 80 deletions src/jamdb_oracle_tns_decoder.erl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

%% API
-export([decode_packet/2]).
-export([decode_two_task/2]).
-export([decode_token/2]).
-export([decode_helper/3]).

Expand Down Expand Up @@ -31,7 +32,7 @@ decode_packet(<<PacketSize:16, _PacketFlags:16, Type, _Flags:8, 0:16, Rest/bits>
decode_packet(_,_) ->
{error, more}.

decode_token(<<Token, Data/binary>>, Acc) ->
decode_two_task(<<Token, Data/binary>>, Acc) ->
case Token of
?TTI_DCB -> decode_token(dcb, Data, Acc);
?TTI_IOV -> decode_token(iov, Data, Acc);
Expand All @@ -45,30 +46,8 @@ decode_token(<<Token, Data/binary>>, Acc) ->
?TTI_FOB -> {error, fob}; %return
_ ->
{error, <<Token, (hd(binary:split(Data, <<0>>)))/binary>>}
end;
decode_token(net, {Data, EnvOpts}) ->
Values = lists:map(fun(L) -> list_to_tuple(string:tokens(L, "=")) end,
string:tokens(binary_to_list(hd(binary:split(Data, <<0>>))), "()")),
Host = proplists:get_value("HOST", Values),
Port = proplists:get_value("PORT", Values),
{ok, [{host, Host}, {port, list_to_integer(Port)}]++EnvOpts};
decode_token(rpa, Data) ->
Num = decode_ub4(Data),
Values = decode_keyval(decode_next(Data), Num, []),
SessKey = get_value("AUTH_SESSKEY", Values),
Salt = get_value("AUTH_VFR_DATA", Values),
Type = get_value("AUTH_VFR_DATA", Values, 3),
DerivedSalt = get_value("AUTH_PBKDF2_CSK_SALT", Values),
Logon = #logon{type=Type, auth=SessKey, salt=Salt, der_salt=DerivedSalt},
case get_value("AUTH_SVR_RESPONSE", Values) of
undefined ->
{?TTI_SESS, Logon};
Resp ->
Value = get_value("AUTH_VERSION_NO", Values),
SessId = get_value("AUTH_SESSION_ID", Values),
Ver = decode_version(Value),
{?TTI_AUTH, Resp, Ver, SessId}
end;
end.

decode_token(oac, Data) ->
DataType = decode_ub1(Data),
A = decode_next(ub1,Data), %data type
Expand All @@ -87,17 +66,7 @@ decode_token(oac, Data) ->
M = decode_next(ub1,L), %character set form
N = decode_next(ub4,M), %mxlc
{N, DataType, Length, Scale, Charset};
decode_token(wrn, Data) ->
A = decode_next(ub2,Data), %error number
Length = decode_ub2(A),
B = decode_next(ub2,A), %length of error message
C = decode_next(ub2,B), %flags
decode_next(ub1, C, Length).

decode_token(dcb, Data, {Ver, _RowFormat, Type}) when is_atom(Type) ->
{A, RowFormat} = decode_token(dcb, decode_next(Data), Ver),
decode_token(A, {0, RowFormat, []});
decode_token(dcb, Data, Ver) ->
decode_token(dcb, Data) ->
A = decode_next(ub4,Data),
Num = decode_ub4(A),
B = decode_next(ub4,A),
Expand All @@ -106,21 +75,50 @@ decode_token(dcb, Data, Ver) ->
0 -> B;
_ -> decode_next(ub1,B)
end,
{RowFormat, D} = decode_token(uds, C, {Ver, [], Num}),
{RowFormat, D} = decode_token(uds, C, {[], Num}),
E = decode_next(dalc,D), %flag
F = decode_next(ub4,E), %mdbz
G = decode_next(ub4,F), %mnpr
J = decode_next(ub4,G), %mxpr
K = decode_next(ub4,J),
L =
case Ver of
10 -> K;
_ -> decode_next(dalc,K)
end,
L = decode_next(dalc,K),
{L, RowFormat};
decode_token(uds, Data, {_Ver, RowFormat, 0}) ->
decode_token(net, {Data, EnvOpts}) ->
Values = lists:map(fun(L) -> list_to_tuple(string:tokens(L, "=")) end,
string:tokens(binary_to_list(hd(binary:split(Data, <<0>>))), "()")),
Host = proplists:get_value("HOST", Values),
Port = proplists:get_value("PORT", Values),
{ok, [{host, Host}, {port, list_to_integer(Port)}]++EnvOpts};
decode_token(rpa, Data) ->
Num = decode_ub4(Data),
Values = decode_keyval(decode_next(Data), Num, []),
SessKey = get_value("AUTH_SESSKEY", Values),
Salt = get_value("AUTH_VFR_DATA", Values),
Type = get_value("AUTH_VFR_DATA", Values, 3),
DerivedSalt = get_value("AUTH_PBKDF2_CSK_SALT", Values),
Logon = #logon{type=Type, auth=SessKey, salt=Salt, der_salt=DerivedSalt},
case get_value("AUTH_SVR_RESPONSE", Values) of
undefined ->
{?TTI_SESS, Logon};
Resp ->
Value = get_value("AUTH_VERSION_NO", Values),
SessId = get_value("AUTH_SESSION_ID", Values),
Ver = decode_version(Value),
{?TTI_AUTH, Resp, Ver, SessId}
end;
decode_token(wrn, Data) ->
A = decode_next(ub2,Data), %error number
Length = decode_ub2(A),
B = decode_next(ub2,A), %length of error message
C = decode_next(ub2,B), %flags
decode_next(ub1, C, Length).

decode_token(dcb, Data, {_Cursor, _RowFormat, Type}) when is_atom(Type) ->
{A, RowFormat} = decode_token(dcb, decode_next(Data)),
decode_two_task(A, {0, RowFormat, []});
decode_token(uds, Data, {RowFormat, 0}) ->
{lists:reverse(RowFormat), Data};
decode_token(uds, Data, {Ver, RowFormat, Num}) ->
decode_token(uds, Data, {RowFormat, Num}) ->
{A, DataType, Length, Scale, Charset} = decode_token(oac, Data),
B = decode_next(ub1,A), %nulls allowed
C = decode_next(ub1,B), %v7 length of name
Expand All @@ -129,16 +127,12 @@ decode_token(uds, Data, {Ver, RowFormat, Num}) ->
E = decode_next(dalc,D), %schema name
F = decode_next(dalc,E), %type name
G = decode_next(ub2,F), %column position
J =
case Ver of
10 -> G;
_ -> decode_next(ub4,G)
end,
decode_token(uds, J, {Ver, [#format{column_name=list_to_binary(Column),
J = decode_next(ub4,G),
decode_token(uds, J, {[#format{column_name=list_to_binary(Column),
data_type=DataType,data_length=Length,data_scale=Scale,charset=Charset}|RowFormat], Num-1});
decode_token(rxh, Data, {Cursor, RowFormat, Type}) when is_atom(Type) ->
A = decode_next(rxh,Data),
decode_token(A, {Cursor, RowFormat, [0], []});
decode_two_task(A, {Cursor, RowFormat, [0], []});
decode_token(rxh, Data, {Cursor, RowFormat, Rows}) ->
A = decode_next(ub1,Data), %flag
B = decode_next(ub2,A), %num requests
Expand All @@ -152,40 +146,40 @@ decode_token(rxh, Data, {Cursor, RowFormat, Rows}) ->
_ -> decode_bvc(list_to_binary(Bitvec), RowFormat, [])
end,
F = decode_next(rxh,Data),
decode_token(F, {Cursor, RowFormat, Bvc, Rows});
decode_token(iov, Data, {Ver, RowFormat, Type}) when is_atom(Type) ->
decode_two_task(F, {Cursor, RowFormat, Bvc, Rows});
decode_token(iov, Data, {Cursor, RowFormat, Type}) when is_atom(Type) ->
A = decode_next(ub1,Data),
Num = decode_ub2(A),
<<Mode:Num/binary, Rest/bits>> = decode_next(rxh,Data),
case binary:matches(Mode,[<<16>>,<<48>>]) of
[] -> decode_token(Rest, {0, [], []}); %proc_result
[] -> decode_two_task(Rest, {0, [], []}); %proc_result
_ ->
Bind = lists:zip(binary_to_list(Mode), RowFormat),
decode_token(Rest, {Ver, [decode_param(B) || B <- Bind], Type})
decode_two_task(Rest, {Cursor, [decode_param(B) || B <- Bind], Type})
end;
decode_token(rxd, Data, {Ver, _RowFormat, fetch}) ->
{A, CursorRowFormat} = decode_token(dcb, decode_next(ub1,Data), Ver),
decode_token(rxd, Data, {_Cursor, _RowFormat, fetch}) ->
{A, CursorRowFormat} = decode_token(dcb, decode_next(ub1,Data)),
Cursor = decode_ub4(A),
B = decode_next(ub4,A),
{{Cursor, CursorRowFormat}, decode_next(ub2,B)};
decode_token(rxd, Data, {Ver, _RowFormat, cursor}) ->
{A, _CursorRowFormat} = decode_token(dcb, decode_next(ub1,Data), Ver),
decode_token(rxd, Data, {_Cursor, _RowFormat, cursor}) ->
{A, _CursorRowFormat} = decode_token(dcb, decode_next(ub1,Data)),
{decode_ub4(A), decode_next(ub4,A)};
decode_token(rxd, Data, {Ver, RowFormat, Type}) when is_atom(Type) ->
case decode_data(Data, [], {[], RowFormat, Ver, Type}) of
decode_token(rxd, Data, {_Cursor, RowFormat, Type}) when is_atom(Type) ->
case decode_data(Data, [], {[], RowFormat, Type}) of
{{Cursor, CursorRowFormat}, A} ->
decode_token(A, {Cursor, CursorRowFormat, []}); %fetch cursor
{Rows, A} -> decode_token(A, {0, RowFormat, Rows}) %proc_result
decode_two_task(A, {Cursor, CursorRowFormat, []}); %fetch cursor
{Rows, A} -> decode_two_task(A, {0, RowFormat, Rows}) %proc_result
end;
decode_token(rxd, Data, {Cursor, RowFormat, Bvc, Rows}) ->
LastRow = last(Rows),
{A, Row} = decode_rxd(Data, RowFormat, 1, Bvc, LastRow, []),
decode_token(A, {Cursor, RowFormat, Bvc, Rows++[Row]});
decode_two_task(A, {Cursor, RowFormat, Bvc, Rows++[Row]});
decode_token(bvc, Data, {Cursor, RowFormat, _Bvc, Rows}) ->
A = decode_next(ub2,Data),
{Bvc, Num} = decode_bvc(A, RowFormat, []),
B = decode_next(ub1, A, Num),
decode_token(B, {Cursor, RowFormat, Bvc, Rows});
decode_two_task(B, {Cursor, RowFormat, Bvc, Rows});
decode_token(lob, Data, _Loc) ->
try decode_chr(Data) of
Value -> {ok, Value}
Expand All @@ -194,7 +188,7 @@ decode_token(lob, Data, _Loc) ->
end;
decode_token(rpa, Data, []) ->
{ok, [decode_ub4(Data)]};
decode_token(rpa, Data, {_Ver, RowFormat, Type}) when is_atom(Type) ->
decode_token(rpa, Data, {_Cursor, RowFormat, Type}) when is_atom(Type) ->
decode_token(rpa, Data, {0, RowFormat, []});
decode_token(rpa, Data, {0, RowFormat, Rows}) ->
Cursor =
Expand All @@ -207,15 +201,15 @@ decode_token(rpa, Data, {0, RowFormat, Rows}) ->
decode_ub4(C)
end,
D = decode_next(rpa,Data),
decode_token(D, {Cursor, RowFormat, Rows});
decode_two_task(D, {Cursor, RowFormat, Rows});
decode_token(rpa, Data, {Cursor, RowFormat, _Bvc, Rows}) ->
decode_token(rpa, Data, {Cursor, RowFormat, Rows});
decode_token(rpa, Data, {Cursor, RowFormat, Rows}) ->
A = decode_next(rpa,Data),
decode_token(A, {Cursor, RowFormat, Rows});
decode_two_task(A, {Cursor, RowFormat, Rows});
decode_token(oer, Data, []) ->
decode_token(oer, Data, {0, [], []});
decode_token(oer, Data, {_Ver, RowFormat, Type}) when is_atom(Type) ->
decode_token(oer, Data, {_Cursor, RowFormat, Type}) when is_atom(Type) ->
decode_token(oer, Data, {0, RowFormat, []});
decode_token(oer, Data, {Cursor, RowFormat, _Bvc, Rows}) ->
decode_token(oer, Data, {Cursor, RowFormat, Rows});
Expand Down Expand Up @@ -369,22 +363,22 @@ decode_bvc(Data, Acc, Num, I) when is_list(Acc) ->
Bvc = decode_bvc(decode_ub1(Data), {}, 0, I),
decode_bvc(decode_next(ub1,Data), Acc++tuple_to_list(Bvc), Num-1, I+1).

decode_data(Data, Values, {[], [], _Ver, _Type}) ->
decode_data(Data, Values, {[], [], _Type}) ->
{lists:reverse(Values), Data};
decode_data(Data, _Values, {DefCol, [], _Ver, _Type}) ->
decode_data(Data, _Values, {DefCol, [], _Type}) ->
{DefCol, Data};
decode_data(Data, Values, {DefCol, [#format{param=in}|RestRowFormat], Ver, Type}) ->
decode_data(Data, Values, {DefCol, RestRowFormat, Ver, Type});
decode_data(Data, Values, {_DefCol, [#format{data_type=?TNS_TYPE_REFCURSOR}|RestRowFormat], Ver, Type}) ->
{DefCol, Bin} = decode_token(rxd, Data, {Ver, [], fetch}),
decode_data(Bin, Values, {DefCol, RestRowFormat, Ver, Type});
decode_data(Data, Values, {DefCol, [ValueFormat|RestRowFormat], Ver, Type=return}) ->
decode_data(Data, Values, {DefCol, [#format{param=in}|RestRowFormat], Type}) ->
decode_data(Data, Values, {DefCol, RestRowFormat, Type});
decode_data(Data, Values, {_DefCol, [#format{data_type=?TNS_TYPE_REFCURSOR}|RestRowFormat], Type}) ->
{DefCol, Bin} = decode_token(rxd, Data, {0, [], fetch}),
decode_data(Bin, Values, {DefCol, RestRowFormat, Type});
decode_data(Data, Values, {DefCol, [ValueFormat|RestRowFormat], Type=return}) ->
Num = decode_ub4(Data),
{Value, RestData} = decode_data(decode_next(ub4,Data), ValueFormat, [], Num, Type),
decode_data(RestData, [Value|Values], {DefCol, RestRowFormat, Ver, Type});
decode_data(Data, Values, {DefCol, [ValueFormat|RestRowFormat], Ver, Type=block}) ->
decode_data(RestData, [Value|Values], {DefCol, RestRowFormat, Type});
decode_data(Data, Values, {DefCol, [ValueFormat|RestRowFormat], Type=block}) ->
{Value, RestData} = decode_data(Data, ValueFormat),
decode_data(decode_next(ub2,RestData), [Value|Values], {DefCol, RestRowFormat, Ver, Type}).
decode_data(decode_next(ub2,RestData), [Value|Values], {DefCol, RestRowFormat, Type}).

decode_data(Data, _ValueFormat, Values, 0, _Type) ->
{lists:reverse(Values), Data};
Expand Down
10 changes: 3 additions & 7 deletions src/jamdb_oracle_tns_encoder.erl
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,7 @@ encode_record(dty, #oraclient{charset=Charset}) ->
encode_record(pro, _EnvOpts) ->
<<
?TTI_PRO,
6,5,4,3,2,1,0,
98,101,97,109,0
6,0,98,101,97,109,0
>>;
encode_record(spfp, #oraclient{seq=Tseq}) ->
<<
Expand Down Expand Up @@ -202,7 +201,7 @@ encode_record(fetch, #oraclient{fetch=Fetch,req=Cursor,seq=Tseq}) ->
(encode_sb4(Cursor))/binary, %cursor
(encode_sb4(Fetch))/binary %rows to fetch
>>;
encode_record(exec, #oraclient{type=Type,auto=Auto,charset=Charset,fetch=Fetch,server=Ver,req={Cursor,Query,Bind,Batch,Def},seq=Tseq}) ->
encode_record(exec, #oraclient{type=Type,auto=Auto,charset=Charset,fetch=Fetch,req={Cursor,Query,Bind,Batch,Def},seq=Tseq}) ->
QueryData = encode_str(Query),
QueryLen = if Cursor =/= 0 -> 0; true -> byte_size(QueryData) end,
BindLen = length(Bind),
Expand Down Expand Up @@ -242,10 +241,7 @@ encode_record(exec, #oraclient{type=Type,auto=Auto,charset=Charset,fetch=Fetch,s
(encode_sb4(DefLen))/binary, %defcols count
0, %registration
0,1,
(case Ver of
10 -> <<>>;
_ -> <<0,0,0,0,0>>
end)/binary,
0,0,0,0,0,
(if QueryLen =/= 0 -> QueryData; true -> <<>> end)/binary,
(encode_array(All8))/binary,
(case {BindLen, DefLen, QueryLen} of
Expand Down

0 comments on commit 9632b94

Please sign in to comment.