Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fetch LOB size from ddconfig, change oranif to a branch that includes… #18

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
{erlimem, {git, "https://github.com/konnexionsgmbh/erlimem", {tag, "3.1.0"}}},
{esaml, {git, "https://github.com/KonnexionsGmbH/esaml", {tag, "2.3.0"}}},
{imem, {git, "https://github.com/konnexionsgmbh/imem", {tag, "3.9.1"}}},
{oranif, {git, "https://github.com/konnexionsgmbh/oranif", {tag, "0.2.3"}}},
{oranif, {git, "https://github.com/konnexionsgmbh/oranif", {branch, "lob-res-fix"}}},
{prometheus, "4.5.0"}
]}.

Expand Down
27 changes: 14 additions & 13 deletions src/dderlodpi.erl
Original file line number Diff line number Diff line change
Expand Up @@ -939,13 +939,14 @@ get_column_info(Stmt, ColIdx, Limit) ->
[QueryInfo2 | get_column_info(Stmt, ColIdx + 1, Limit)].

dpi_fetch_rows( #odpi_conn{node = Node, connection = Conn}, Statement, BlockSize) ->
dpi:safe(Node, fun() -> get_rows_prepare(Conn, Statement, BlockSize, []) end).
LobSize = ?GET_CONFIG(odpiLobSize,[],4000,"Size of LOB objects in ODPI"),
dpi:safe(Node, fun() -> get_rows_prepare(Conn, Statement, BlockSize, [], LobSize) end).

%% initalizes things that need to be done before getting the rows
%% it finds out how many columns they are and what types all those columns are
%% then it makes and defines dpiVars for every column where it's necessary because stmt_getQueryValue() can't be used for those cols
%% and calls get_rows to fetch all the results of the query
get_rows_prepare(Conn, Stmt, NRows, Acc)->
get_rows_prepare(Conn, Stmt, NRows, Acc, LobSize)->
NumCols = dpi:stmt_getNumQueryColumns(Stmt), % get number of cols returned by the Stmt
Types = [
begin
Expand All @@ -967,14 +968,14 @@ get_rows_prepare(Conn, Stmt, NRows, Acc)->
ok = dpi:stmt_define(Stmt, Col, Var), %% results will be fetched to the vars and go into the data
{Var, Datas, OraType}; % put the variable and its data list into a tuple
'DPI_NATIVE_TYPE_LOB' ->
#{var := Var, data := Datas} = dpi:conn_newVar(Conn, OraType, 'DPI_NATIVE_TYPE_LOB', 100, 4000, false, false, null),
#{var := Var, data := Datas} = dpi:conn_newVar(Conn, OraType, 'DPI_NATIVE_TYPE_LOB', 100, LobSize, false, false, null),
ok = dpi:stmt_define(Stmt, Col, Var), %% results will be fetched to the vars and go into the data
{Var, Datas, OraType}; % put the variable and its data list into a tuple
_else -> {noVariable, OraType} % when no variable needs to be made for the type, just put an atom signlizing that no variable was made and stmt_getQueryValue() can be used to get the values
end
end
|| {OraType, NativeType, Col} <- Types], % make a list of {Var, Datas} tuples. Var is the dpiVar handle, Datas is the list of Data handles in that respective Var
R = get_rows(Conn, Stmt, NRows, Acc, VarsDatas), % gets all the results from the query
R = get_rows(Conn, Stmt, NRows, Acc, VarsDatas, LobSize), % gets all the results from the query
[begin
case VarDatas of {noVariable, _OraType} -> nop; % if no variable was made, then nothing needs to be done here
{Var, Datas, _OraType} -> % if there is a variable (which was made to fetch a double as a binary)
Expand All @@ -985,35 +986,35 @@ R = get_rows(Conn, Stmt, NRows, Acc, VarsDatas), % gets all the results from the
R. % return query results

%% this recursive function fetches all the rows. It does so by calling yet another recursive function that fetches all the fields in a row.
get_rows(_Conn, _, 0, Acc, _VarsDatas) -> {lists:reverse(Acc), false};
get_rows(Conn, Stmt, NRows, Acc, VarsDatas) ->
get_rows(_Conn, _, 0, Acc, _VarsDatas, _LobSize) -> {lists:reverse(Acc), false};
get_rows(Conn, Stmt, NRows, Acc, VarsDatas, LobSize) ->
case dpi:stmt_fetch(Stmt) of % try to fetch a row
#{found := true} -> % got a row: get the values in that row and then do the recursive call to try to get another row
get_rows(Conn, Stmt, NRows -1, [get_column_values(Conn, Stmt, 1, VarsDatas, length(Acc)+1) | Acc], VarsDatas); % recursive call
get_rows(Conn, Stmt, NRows -1, [get_column_values(Conn, Stmt, 1, VarsDatas, length(Acc)+1, LobSize) | Acc], VarsDatas, LobSize); % recursive call
#{found := false} -> % no more rows: that was all of them
{lists:reverse(Acc), true} % reverse the list so it's in the right order again after it was pieced together the other way around
end.

%% get all the fields in one row
get_column_values(_Conn, _Stmt, ColIdx, VarsDatas, _RowIndex) when ColIdx > length(VarsDatas) -> [];
get_column_values(Conn, Stmt, ColIdx, VarsDatas, RowIndex) ->
get_column_values(_Conn, _Stmt, ColIdx, VarsDatas, _RowIndex, _LobSize) when ColIdx > length(VarsDatas) -> [];
get_column_values(Conn, Stmt, ColIdx, VarsDatas, RowIndex, LobSize) ->
case lists:nth(ColIdx, VarsDatas) of % get the entry that is either a {Var, Datas} tuple or noVariable if no variable was made for this column
{_Var, Datas, OraType} -> % if a variable was made for this column: the value was fetched into the variable's data object, so get it from there
Value = dpi:data_get(lists:nth(RowIndex, Datas)), % get the value out of that data variable
ValueFixed = case OraType of % depending on the ora type, the value might have to be changed into a different format so it displays properly
'DPI_ORACLE_TYPE_BLOB' -> list_to_binary(lists:flatten([io_lib:format("~2.16.0B", [X]) || X <- binary_to_list(dpi:lob_readBytes(Value, 1, 4000))])); % turn binary to hex string
'DPI_ORACLE_TYPE_CLOB' -> dpi:lob_readBytes(Value, 1, 4000);
'DPI_ORACLE_TYPE_BLOB' -> list_to_binary(lists:flatten([io_lib:format("~2.16.0B", [X]) || X <- binary_to_list(dpi:lob_readBytes(Value, 1, LobSize))])); % turn binary to hex string
'DPI_ORACLE_TYPE_CLOB' -> dpi:lob_readBytes(Value, 1, LobSize);
_Else -> Value end, % the value is already in the correct format for most types, so do nothing

[ValueFixed | get_column_values(Conn, Stmt, ColIdx + 1, VarsDatas, RowIndex)]; % recursive call
[ValueFixed | get_column_values(Conn, Stmt, ColIdx + 1, VarsDatas, RowIndex, LobSize)]; % recursive call
{noVariable, OraType} -> % if no variable has been made then that means that the value can be fetched with stmt_getQueryValue()
#{data := Data} = dpi:stmt_getQueryValue(Stmt, ColIdx), % get the value
Value = dpi:data_get(Data), % take the value from this freshly made data
dpi:data_release(Data), % release this new data object
ValueFixed = case OraType of % some types may require additional casting/unmarshalling
'DPI_ORACLE_TYPE_LONG_VARCHAR' -> list_to_binary(lists:flatten([io_lib:format("~2.16.0B", [X]) || X <- binary_to_list(Value)])); % turn binary into hex representation of binary
_Else -> Value end, % value doesn't need any converting
[ValueFixed | get_column_values(Conn, Stmt, ColIdx + 1, VarsDatas, RowIndex)]; % recursive call
[ValueFixed | get_column_values(Conn, Stmt, ColIdx + 1, VarsDatas, RowIndex, LobSize)]; % recursive call
Else ->
?Error("Invalid variable term of ~p", [Else])
end.
Expand Down