From 312dc963ea4dd197ac640b761534992f952cca07 Mon Sep 17 00:00:00 2001 From: Mykhailo Vstavskyi Date: Sun, 3 Mar 2024 10:40:29 +0200 Subject: [PATCH 1/3] Update jamdb_oracle_tns_encoder.erl --- src/jamdb_oracle_tns_encoder.erl | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/jamdb_oracle_tns_encoder.erl b/src/jamdb_oracle_tns_encoder.erl index 2e518e2..ef933c1 100644 --- a/src/jamdb_oracle_tns_encoder.erl +++ b/src/jamdb_oracle_tns_encoder.erl @@ -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}) -> << @@ -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), @@ -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 From de3a15976d2233b98d2b1773c65a76f6c045d808 Mon Sep 17 00:00:00 2001 From: Mykhailo Vstavskyi Date: Sun, 3 Mar 2024 10:42:13 +0200 Subject: [PATCH 2/3] Update jamdb_oracle_tns_decoder.erl --- src/jamdb_oracle_tns_decoder.erl | 154 +++++++++++++++---------------- 1 file changed, 74 insertions(+), 80 deletions(-) diff --git a/src/jamdb_oracle_tns_decoder.erl b/src/jamdb_oracle_tns_decoder.erl index 8412220..a9f9294 100644 --- a/src/jamdb_oracle_tns_decoder.erl +++ b/src/jamdb_oracle_tns_decoder.erl @@ -2,6 +2,7 @@ %% API -export([decode_packet/2]). +-export([decode_two_task/2]). -export([decode_token/2]). -export([decode_helper/3]). @@ -31,7 +32,7 @@ decode_packet(< decode_packet(_,_) -> {error, more}. -decode_token(<>, Acc) -> +decode_two_task(<>, Acc) -> case Token of ?TTI_DCB -> decode_token(dcb, Data, Acc); ?TTI_IOV -> decode_token(iov, Data, Acc); @@ -45,30 +46,8 @@ decode_token(<>, Acc) -> ?TTI_FOB -> {error, fob}; %return _ -> {error, <>)))/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 @@ -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), @@ -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 @@ -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 @@ -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), <> = 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} @@ -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 = @@ -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}); @@ -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}; From ae3f982d54e8b8dafac8ec81f3b2b680953efe73 Mon Sep 17 00:00:00 2001 From: Mykhailo Vstavskyi Date: Sun, 3 Mar 2024 10:43:41 +0200 Subject: [PATCH 3/3] Update jamdb_oracle_conn.erl --- src/jamdb_oracle_conn.erl | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/jamdb_oracle_conn.erl b/src/jamdb_oracle_conn.erl index 5402c57..e0a9b2d 100644 --- a/src/jamdb_oracle_conn.erl +++ b/src/jamdb_oracle_conn.erl @@ -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 @@ -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}), @@ -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};