diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/odbc/c_src/odbcserver.c | 2 | ||||
-rw-r--r-- | lib/odbc/test/odbc_query_SUITE.erl | 22 | ||||
-rw-r--r-- | lib/odbc/test/oracle.erl | 27 | ||||
-rw-r--r-- | lib/odbc/test/postgres.erl | 39 | ||||
-rw-r--r-- | lib/reltool/src/reltool_server.erl | 39 | ||||
-rw-r--r-- | lib/reltool/test/reltool_server_SUITE.erl | 53 |
6 files changed, 167 insertions, 15 deletions
diff --git a/lib/odbc/c_src/odbcserver.c b/lib/odbc/c_src/odbcserver.c index a6b3de6e48..5730e20774 100644 --- a/lib/odbc/c_src/odbcserver.c +++ b/lib/odbc/c_src/odbcserver.c @@ -1222,7 +1222,7 @@ static db_result_msg encode_out_params(db_state *state, (column.type.strlen_or_indptr_array[j])); break; case SQL_C_SLONG: - ei_x_encode_long(&dynamic_buffer(state), ((long*)values)[j]); + ei_x_encode_long(&dynamic_buffer(state), ((SQLINTEGER*)values)[j]); break; case SQL_C_DOUBLE: ei_x_encode_double(&dynamic_buffer(state), diff --git a/lib/odbc/test/odbc_query_SUITE.erl b/lib/odbc/test/odbc_query_SUITE.erl index 062373afa0..56550bfaa6 100644 --- a/lib/odbc/test/odbc_query_SUITE.erl +++ b/lib/odbc/test/odbc_query_SUITE.erl @@ -43,7 +43,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> case odbc_test_lib:odbc_check() of ok -> - [sql_query, next, {group, scrollable_cursors}, select_count, + [stored_proc, sql_query, next, {group, scrollable_cursors}, select_count, select_next, select_relative, select_absolute, create_table_twice, delete_table_twice, duplicate_key, not_connection_owner, no_result_set, query_error, @@ -172,6 +172,26 @@ end_per_testcase(_Case, Config) -> %%------------------------------------------------------------------------- %% Test cases starts here. %%------------------------------------------------------------------------- +stored_proc(doc)-> + ["Test stored proc with OUT param"]; +stored_proc(suite) -> []; +stored_proc(Config) when is_list(Config) -> + case ?RDBMS of + X when X == oracle; X == postgres-> + Ref = ?config(connection_ref, Config), + {updated, _} = + odbc:sql_query(Ref, + ?RDBMS:stored_proc_integer_out()), + Result = ?RDBMS:query_result(), + Result = + ?RDBMS:param_query(Ref), + {updated, _} = + odbc:sql_query(Ref, ?RDBMS:drop_proc()), + ok; + _ -> + {skip, "stored proc not yet supported"} + end. + sql_query(doc)-> ["Test the common cases"]; sql_query(suite) -> []; diff --git a/lib/odbc/test/oracle.erl b/lib/odbc/test/oracle.erl index d74863d8c1..95cf7155dc 100644 --- a/lib/odbc/test/oracle.erl +++ b/lib/odbc/test/oracle.erl @@ -240,3 +240,30 @@ describe_floating() -> {ok,[{"F",sql_double},{"R",sql_double},{"D",sql_double}]}. describe_dec_num() -> {ok,[{"MYDEC",{sql_decimal,9,3}},{"MYNUM",{sql_decimal,9,2}}]}. + +%------------------------------------------------------------------------- +drop_proc() -> + "drop procedure test_proc1;". + +stored_proc_integer_out() -> + "create or replace PROCEDURE test_proc1(" ++ + "int_a OUT NUMBER, " ++ + "int_b OUT NUMBER) " ++ + "is " ++ + "begin " ++ + " int_a := 123; " ++ + " int_b := 456; " ++ + "exception " ++ + "WHEN NO_DATA_FOUND THEN " ++ + " int_a := 0; " ++ + " int_b := 0; " ++ + "end;". + +param_query(Ref) -> + odbc:param_query(Ref, "call test_proc1(?,?)", + [{sql_integer, out, [0]}, + {sql_integer, out, [0]}]). + + +query_result() -> + {executed, 2, [{123, 456}]}. diff --git a/lib/odbc/test/postgres.erl b/lib/odbc/test/postgres.erl index d564dbd5ff..0c1761b835 100644 --- a/lib/odbc/test/postgres.erl +++ b/lib/odbc/test/postgres.erl @@ -293,3 +293,42 @@ describe_dec_num() -> describe_timestamp() -> {ok, [{"field", sql_timestamp}]}. + +%------------------------------------------------------------------------- +drop_proc() -> + "drop function test_proc1(OUT integer, OUT integer);". + +stored_proc_integer_out() -> + "create or replace FUNCTION test_proc1(" ++ + "OUT int_a INTEGER, " ++ + "OUT int_b INTEGER) " ++ + "AS $$ " ++ + "BEGIN " ++ + " int_a := 123; " ++ + " int_b := 456; " ++ + "END " ++ + "$$ LANGUAGE plpgsql ". + +%% This does not test what you might think it is supposed to test. +%% Since the stored procedure has got 2 out parameters and no +%% in parameters it is of arity 0 as called below. +%% +%% The port program odbcserver.c will marshal these out parameters +%% and hand them to ODBC. The ODBC driver for postgres will +%% apparently not give a hoot about these out parameters and instead +%% return the result in a regular result select set. The port program +%% will assume it has the result in the out parameters and marshal +%% these as they are i.e as it itself had packed them, so they +%% come back unchanged. +%% +%% The real function result goes into the void but the code in odbcserver.c +%% that marshals out parameters returned from ODBC will be run +%% so that is what this test tests... +%% +param_query(Ref) -> + odbc:param_query(Ref, "select * from test_proc1()", + [{sql_integer, out, [111]}, + {sql_integer, out, [444]}]). + +query_result() -> + {executed, 2, [{111, 444}]}. diff --git a/lib/reltool/src/reltool_server.erl b/lib/reltool/src/reltool_server.erl index 5e25f22a6f..97785ca7f8 100644 --- a/lib/reltool/src/reltool_server.erl +++ b/lib/reltool/src/reltool_server.erl @@ -973,7 +973,8 @@ refresh_app(#app{name = AppName, is_escript = IsEscript, active_dir = ActiveDir, label = OptLabel, - mods = Mods} = App, + mods = Mods, + status = AppStatus} = App, Force, Status) -> if @@ -993,6 +994,8 @@ refresh_app(#app{name = AppName, read_app_info(AppFile, AppFile, AppName, + ActiveDir, + AppStatus, DefaultVsn, Status), @@ -1064,9 +1067,11 @@ refresh_app(#app{name = AppName, missing_app_info(Vsn) -> #app_info{vsn = Vsn}. -read_app_info(_AppFileOrBin, _AppFile, erts, DefaultVsn, Status) -> +read_app_info(_AppFileOrBin, _AppFile, erts, _ActiveDir, _AppStatus, DefaultVsn, Status) -> {missing_app_info(DefaultVsn), Status}; -read_app_info(AppFileOrBin, AppFile, AppName, DefaultVsn, Status) -> +read_app_info(_AppFileOrBin, _AppFile, _AppName, undefined, missing, DefaultVsn, Status) -> + {missing_app_info(DefaultVsn), Status}; +read_app_info(AppFileOrBin, AppFile, AppName, _ActiveDir, _AppStatus, DefaultVsn, Status) -> EnoentText = file:format_error(enoent), case reltool_utils:prim_consult(AppFileOrBin) of {ok, [{application, AppName, Info}]} -> @@ -1080,9 +1085,9 @@ read_app_info(AppFileOrBin, AppFile, AppName, DefaultVsn, Status) -> Status)}; {error, Text} when Text =:= EnoentText -> {missing_app_info(DefaultVsn), - reltool_utils:add_warning("~w: Missing app file ~tp.", - [AppName,AppFile], - Status)}; + reltool_utils:add_warning("~w: Missing app file ~tp.", + [AppName,AppFile], + Status)}; {error, Text} -> {missing_app_info(DefaultVsn), reltool_utils:add_warning("~w: Cannot parse app file ~tp (~tp).", @@ -1773,13 +1778,15 @@ escripts_to_apps([Escript | Escripts], Apps, Status) -> get_vsn_from_dir(AppName,AppLabel), AppFileName = filename:join([Escript, FullName]), + Dir = filename:join([Escript, AppName]), {Info, StatusAcc2} = read_app_info(GetBin(), AppFileName, AppName, + Dir, + ok, DefaultVsn, Status), - Dir = filename:join([Escript, AppName]), {[{AppName, app, Dir, Info} | FileAcc], StatusAcc2}; E when E =:= Ext -> @@ -1979,20 +1986,27 @@ refresh_apps(ConfigApps, [New | NewApps], Acc, Force, Status) -> refresh_apps(_ConfigApps, [], Acc, _Force, Status) -> {lists:reverse(Acc), Status}. - ensure_app_info(#app{is_escript = IsEscript, active_dir = Dir, info = Info}, Status) when IsEscript=/=false -> %% Escript or application which is inlined in an escript {Info, Dir, Status}; -ensure_app_info(#app{name = Name, sorted_dirs = []}, _Status) -> - reltool_utils:throw_error("~w: : Missing application directory.",[Name]); +ensure_app_info(#app{name = Name, sorted_dirs = []} = App, Status) -> + Reason = "~w: Missing application directory.", + case App of + #app{incl_cond = exclude, status = missing, active_dir = Dir} -> + Status2 = reltool_utils:add_warning(Reason, [Name], Status), + {missing_app_info(""), Dir, Status2}; + _ -> + reltool_utils:throw_error(Reason, [Name]) + end; ensure_app_info(#app{name = Name, vsn = Vsn, use_selected_vsn = UseSelectedVsn, active_dir = ActiveDir, sorted_dirs = Dirs, - info = undefined}, + info = undefined, + status = AppStatus}, Status) -> ReadInfo = fun(Dir, StatusAcc) -> @@ -2000,7 +2014,8 @@ ensure_app_info(#app{name = Name, Ebin = filename:join([Dir, "ebin"]), DefaultVsn = get_vsn_from_dir(Name,Base), AppFile = filename:join([Ebin, atom_to_list(Name) ++ ".app"]), - read_app_info(AppFile, AppFile, Name, DefaultVsn, StatusAcc) + read_app_info(AppFile, AppFile, Name, ActiveDir, + AppStatus, DefaultVsn, StatusAcc) end, {AllInfo, Status2} = lists:mapfoldl(ReadInfo, Status, Dirs), AllVsns = [I#app_info.vsn || I <- AllInfo], diff --git a/lib/reltool/test/reltool_server_SUITE.erl b/lib/reltool/test/reltool_server_SUITE.erl index 23338d9ecd..adea716e99 100644 --- a/lib/reltool/test/reltool_server_SUITE.erl +++ b/lib/reltool/test/reltool_server_SUITE.erl @@ -80,6 +80,8 @@ all() -> otp_9229_dupl_mod_exclude_app, otp_9229_dupl_mod_exclude_mod, dupl_mod_in_app_file, + include_non_existing_app, + exclude_non_existing_app, get_apps, get_mod, get_sys, @@ -1313,7 +1315,6 @@ otp_9229_dupl_mod_exclude_mod(Config) -> ok. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Test that if a module is duplicated in a .app file, then a warning %% is produced, but target can still be created. @@ -1346,6 +1347,56 @@ dupl_mod_in_app_file(Config) -> ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Test that a reasonable error message is returned if an application +%% is missing +include_non_existing_app(_Config) -> + %% Configure the server + Sys = + {sys, + [ + {incl_cond,exclude}, + {app,foobar,[{incl_cond,include}]}, + {app,kernel,[{incl_cond,include}]}, + {app,stdlib,[{incl_cond,include}]}, + {app,sasl,[{incl_cond,include}]} + ]}, + + %% Generate target file + TargetDir = filename:join([?WORK_DIR, "target_include_non_existing_app"]), + ?m(ok, reltool_utils:recursive_delete(TargetDir)), + ?m(ok, file:make_dir(TargetDir)), + ?log("SPEC: ~p\n", [reltool:get_target_spec([{config, Sys}])]), + ?m({error,"foobar: Missing application directory."}, + reltool:get_status([{config, Sys}])), + + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Test that if a missing application is explicitly excluded a warning +%% should be issued. +exclude_non_existing_app(_Config) -> + %% Configure the server + Sys = + {sys, + [ + {incl_cond,exclude}, + {app,foobar,[{incl_cond,exclude}]}, + {app,kernel,[{incl_cond,include}]}, + {app,stdlib,[{incl_cond,include}]}, + {app,sasl,[{incl_cond,include}]} + ]}, + + %% Generate target file + TargetDir = filename:join([?WORK_DIR, "target_exclude_non_existing_app"]), + ?m(ok, reltool_utils:recursive_delete(TargetDir)), + ?m(ok, file:make_dir(TargetDir)), + ?log("SPEC: ~p\n", [reltool:get_target_spec([{config, Sys}])]), + ?m({ok,["foobar: Missing application directory."]}, + reltool:get_status([{config, Sys}])), + + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Test the interface used by the GUI: %% get_app %% get_apps |