%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% %CopyrightEnd%
%%
%%
-module(odbc_query_SUITE).
%% Note: This directive should only be used in test suites.
-compile(export_all).
-include_lib("common_test/include/ct.hrl").
-include("odbc_test.hrl").
%%--------------------------------------------------------------------
%% all(Arg) -> [Doc] | [Case] | {skip, Comment}
%% Arg - doc | suite
%% Doc - string()
%% Case - atom()
%% Name of a test case function.
%% Comment - string()
%% Description: Returns documentation/test cases in this test suite
%% or a skip tuple if the platform is not supported.
%%--------------------------------------------------------------------
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
case odbc_test_lib:odbc_check() of
ok ->
[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,
{group, multiple_result_sets},
{group, parameterized_queries}, {group, describe_table},
delete_nonexisting_row];
Other -> {skip, Other}
end.
groups() ->
[{multiple_result_sets, [], [multiple_select_result_sets,
multiple_mix_result_sets,
multiple_result_sets_error]},
{scrollable_cursors, [], [first, last, prev]},
{parameterized_queries, [],
[{group, param_integers}, param_insert_decimal,
param_insert_numeric, {group, param_insert_string},
param_insert_float, param_insert_real,
param_insert_double, param_insert_mix, param_update,
param_delete, param_select,
param_select_empty_params, param_delete_empty_params]},
{param_integers, [],
[param_insert_tiny_int, param_insert_small_int,
param_insert_int, param_insert_integer]},
{param_insert_string, [],
[param_insert_char, param_insert_character,
param_insert_char_varying,
param_insert_character_varying]},
{describe_table, [],
[describe_integer, describe_string, describe_floating,
describe_dec_num, describe_no_such_table]}].
init_per_group(multiple_result_sets, Config) ->
case is_supported_multiple_resultsets(?RDBMS) of
true ->
Config;
false ->
{skip, "Not supported by " ++ atom_to_list(?RDBMS) ++ "driver"}
end;
init_per_group(scrollable_cursors, Config) ->
case proplists:get_value(scrollable_cursors, odbc_test_lib:platform_options()) of
off ->
{skip, "Not supported by driver"};
_ ->
Config
end;
init_per_group(_,Config) ->
Config.
end_per_group(_GroupName, Config) ->
Config.
%%--------------------------------------------------------------------
%% Function: init_per_suite(Config) -> Config
%% Config - [tuple()]
%% A list of key/value pairs, holding the test case configuration.
%% Description: Initiation before the whole suite
%%
%% Note: This function is free to add any key/value pairs to the Config
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
init_per_suite(Config) when is_list(Config) ->
case odbc_test_lib:skip() of
true ->
{skip, "ODBC not supported"};
false ->
case (catch odbc:start()) of
ok ->
ct:timetrap(?default_timeout),
[{tableName, odbc_test_lib:unique_table_name()}| Config];
_ ->
{skip, "ODBC not startable"}
end
end.
%%--------------------------------------------------------------------
%% Function: end_per_suite(Config) -> _
%% Config - [tuple()]
%% A list of key/value pairs, holding the test case configuration.
%% Description: Cleanup after the whole suite
%%--------------------------------------------------------------------
end_per_suite(_Config) ->
application:stop(odbc),
ok.
%%--------------------------------------------------------------------
%% Function: init_per_testcase(Case, Config) -> Config
%% Case - atom()
%% Name of the test case that is about to be run.
%% Config - [tuple()]
%% A list of key/value pairs, holding the test case configuration.
%%
%% Description: Initiation before each test case
%%
%% Note: This function is free to add any key/value pairs to the Config
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
init_per_testcase(_Case, Config) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
odbc_test_lib:strict(Ref, ?RDBMS),
NewConfig = lists:keydelete(connection_ref, 1, Config),
[{connection_ref, Ref} | NewConfig].
%%--------------------------------------------------------------------
%% Function: end_per_testcase(Case, Config) -> _
%% Case - atom()
%% Name of the test case that is about to be run.
%% Config - [tuple()]
%% A list of key/value pairs, holding the test case configuration.
%% Description: Cleanup after each test case
%%--------------------------------------------------------------------
end_per_testcase(_Case, Config) ->
Ref = proplists:get_value(connection_ref, Config),
ok = odbc:disconnect(Ref),
%% Clean up if needed
Table = proplists:get_value(tableName, Config),
{ok, NewRef} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
odbc:sql_query(NewRef, "DROP TABLE " ++ Table),
odbc:disconnect(NewRef).
%%-------------------------------------------------------------------------
%% Test cases starts here.
%%-------------------------------------------------------------------------
stored_proc()->
[{doc, "Test stored proc with OUT param"}].
stored_proc(Config) when is_list(Config) ->
case ?RDBMS of
X when X == oracle; X == postgres->
Ref = proplists:get_value(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(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID integer, DATA varchar(10))"),
{updated, Count} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++ " VALUES(1,'bar')"),
true = odbc_test_lib:check_row_count(1, Count),
InsertResult = ?RDBMS:insert_result(),
InsertResult =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
{updated, NewCount} =
odbc:sql_query(Ref, "UPDATE " ++ Table ++
" SET DATA = 'foo' WHERE ID = 1"),
true = odbc_test_lib:check_row_count(1, NewCount),
UpdateResult = ?RDBMS:update_result(),
UpdateResult =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
{updated, NewCount1} = odbc:sql_query(Ref, "DELETE FROM " ++ Table ++
" WHERE ID = 1"),
true = odbc_test_lib:check_row_count(1, NewCount1),
{selected, Fields, []} =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
["ID","DATA"] = odbc_test_lib:to_upper(Fields),
ok.
%%-------------------------------------------------------------------------
select_count() ->
[{doc, "Tests select_count/[2,3]'s timeout, "
" select_count's functionality will be better tested by other tests "
" such as first."}].
select_count(sute) -> [];
select_count(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} = odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID integer)"),
{updated, Count} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(1)"),
true = odbc_test_lib:check_row_count(1, Count),
{ok, _} =
odbc:select_count(Ref, "SELECT * FROM " ++ Table, ?TIMEOUT),
{'EXIT', {function_clause, _}} =
(catch odbc:select_count(Ref, "SELECT * FROM ", -1)),
ok.
%%-------------------------------------------------------------------------
first() ->
[doc, {"Tests first/[1,2]"}].
first(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} = odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID integer)"),
{updated, Count} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(1)"),
true = odbc_test_lib:check_row_count(1, Count),
{updated, NewCount} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(2)"),
true = odbc_test_lib:check_row_count(1, NewCount),
{ok, _} = odbc:select_count(Ref, "SELECT * FROM " ++ Table),
FirstResult = ?RDBMS:selected_ID(1, first),
FirstResult = odbc:first(Ref),
FirstResult = odbc:first(Ref, ?TIMEOUT),
{'EXIT', {function_clause, _}} = (catch odbc:first(Ref, -1)),
ok.
%%-------------------------------------------------------------------------
last() ->
[{doc, "Tests last/[1,2]"}].
last(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} = odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID integer)"),
{updated, Count} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(1)"),
true = odbc_test_lib:check_row_count(1, Count),
{updated, NewCount} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(2)"),
true = odbc_test_lib:check_row_count(1, NewCount),
{ok, _} = odbc:select_count(Ref, "SELECT * FROM " ++ Table),
LastResult = ?RDBMS:selected_ID(2, last),
LastResult = odbc:last(Ref),
LastResult = odbc:last(Ref, ?TIMEOUT),
{'EXIT', {function_clause, _}} = (catch odbc:last(Ref, -1)),
ok.
%%-------------------------------------------------------------------------
next() ->
[{doc, "Tests next/[1,2]"}].
next(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} = odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID integer)"),
{updated, Count} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(1)"),
true = odbc_test_lib:check_row_count(1, Count),
{updated, NewCount} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(2)"),
true = odbc_test_lib:check_row_count(1, NewCount),
{ok, _} = odbc:select_count(Ref, "SELECT * FROM " ++ Table),
NextResult = ?RDBMS:selected_ID(1, next),
NextResult = odbc:next(Ref),
NextResult2 = ?RDBMS:selected_ID(2, next),
NextResult2 = odbc:next(Ref, ?TIMEOUT),
{'EXIT', {function_clause, _}} = (catch odbc:next(Ref, -1)),
ok.
%%-------------------------------------------------------------------------
prev() ->
[{doc, "Tests prev/[1,2]"}].
prev(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} = odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID integer)"),
{updated, Count} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(1)"),
true = odbc_test_lib:check_row_count(1, Count),
{updated, NewCount} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(2)"),
true = odbc_test_lib:check_row_count(1, NewCount),
{ok, _} = odbc:select_count(Ref, "SELECT * FROM " ++ Table),
odbc:last(Ref), % Position cursor last so there will be a prev
PrevResult = ?RDBMS:selected_ID(1, prev),
PrevResult = odbc:prev(Ref),
odbc:last(Ref), % Position cursor last so there will be a prev
PrevResult = odbc:prev(Ref, ?TIMEOUT),
{'EXIT', {function_clause, _}} = (catch odbc:prev(Ref, -1)),
ok.
%%-------------------------------------------------------------------------
select_next() ->
[{doc, "Tests select/[4,5] with CursorRelation = next "}].
select_next(suit) -> [];
select_next(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} = odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID integer)"),
{updated, 1} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(1)"),
{updated, 1} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(2)"),
{updated, 1} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(3)"),
{updated, 1} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(4)"),
{updated, 1} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(5)"),
{ok, _} = odbc:select_count(Ref, "SELECT * FROM " ++ Table),
SelectResult1 = ?RDBMS:selected_next_N(1),
SelectResult1 = odbc:select(Ref, next, 3),
%% Test that selecting stops at the end of the result set
SelectResult2 = ?RDBMS:selected_next_N(2),
SelectResult2 = odbc:select(Ref, next, 3, ?TIMEOUT),
{'EXIT',{function_clause, _}} =
(catch odbc:select(Ref, next, 2, -1)),
%% If you try fetching data beyond the the end of result set,
%% you get an empty list.
{selected, Fields, []} = odbc:select(Ref, next, 1),
["ID"] = odbc_test_lib:to_upper(Fields),
ok.
%%-------------------------------------------------------------------------
select_relative() ->
[{doc, "Tests select/[4,5] with CursorRelation = relative "}].
select_relative(suit) -> [];
select_relative(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} = odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID integer)"),
{updated, 1} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(1)"),
{updated, 1} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(2)"),
{updated, 1} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(3)"),
{updated, 1} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(4)"),
{updated, 1} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(5)"),
{updated, 1} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(6)"),
{updated, 1} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(7)"),
{updated, 1} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(8)"),
{ok, _} = odbc:select_count(Ref, "SELECT * FROM " ++ Table),
SelectResult1 = ?RDBMS:selected_relative_N(1),
SelectResult1 = odbc:select(Ref, {relative, 2}, 3),
%% Test that selecting stops at the end of the result set
SelectResult2 = ?RDBMS:selected_relative_N(2),
SelectResult2 = odbc:select(Ref, {relative, 3}, 3, ?TIMEOUT),
{'EXIT',{function_clause, _}} =
(catch odbc:select(Ref, {relative, 3} , 2, -1)),
ok.
%%-------------------------------------------------------------------------
select_absolute() ->
[{doc, "Tests select/[4,5] with CursorRelation = absolute "}].
select_absolute(suit) -> [];
select_absolute(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} = odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID integer)"),
{updated, 1} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(1)"),
{updated, 1} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(2)"),
{updated, 1} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(3)"),
{updated, 1} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(4)"),
{updated, 1} = odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(5)"),
{ok, _} = odbc:select_count(Ref, "SELECT * FROM " ++ Table),
SelectResult1 = ?RDBMS:selected_absolute_N(1),
SelectResult1 = odbc:select(Ref, {absolute, 1}, 3),
%% Test that selecting stops at the end of the result set
SelectResult2 = ?RDBMS:selected_absolute_N(2),
SelectResult2 = odbc:select(Ref, {absolute, 1}, 6, ?TIMEOUT),
{'EXIT',{function_clause, _}} =
(catch odbc:select(Ref, {absolute, 1}, 2, -1)),
ok.
%%-------------------------------------------------------------------------
create_table_twice() ->
[{doc, "Test what happens if you try to create the same table twice."}].
create_table_twice(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID integer, DATA varchar(10))"),
{error, Error} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID integer, DATA varchar(10))"),
is_driver_error(Error),
ok.
%%-------------------------------------------------------------------------
delete_table_twice() ->
[{doc, "Test what happens if you try to delete the same table twice."}].
delete_table_twice(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID integer, DATA varchar(10))"),
{updated, _} = odbc:sql_query(Ref, "DROP TABLE " ++ Table),
{error, Error} = odbc:sql_query(Ref, "DROP TABLE " ++ Table),
is_driver_error(Error),
ok.
%-------------------------------------------------------------------------
duplicate_key() ->
[{doc, "Test what happens if you try to use the same key twice"}].
duplicate_key(suit) -> [];
duplicate_key(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID integer, DATA char(10), PRIMARY KEY(ID))"),
{updated, 1} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++ " VALUES(1,'bar')"),
{error, Error} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++ " VALUES(1,'foo')"),
is_driver_error(Error),
ok.
%%-------------------------------------------------------------------------
not_connection_owner() ->
[{doc, "Test what happens if a process that did not start the connection"
" tries to acess it."}].
not_connection_owner(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
spawn_link(?MODULE, not_owner, [self(), Ref, Table]),
receive
continue ->
ok
end.
not_owner(Pid, Ref, Table) ->
{error, process_not_owner_of_odbc_connection} =
odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++ " (ID integer)"),
{error, process_not_owner_of_odbc_connection} =
odbc:disconnect(Ref),
Pid ! continue.
%%-------------------------------------------------------------------------
no_result_set() ->
[{doc, "Tests what happens if you try to use a function that needs an "
"associated result set when there is none."}].
no_result_set(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
{error, result_set_does_not_exist} = odbc:first(Ref),
{error, result_set_does_not_exist} = odbc:last(Ref),
{error, result_set_does_not_exist} = odbc:next(Ref),
{error, result_set_does_not_exist} = odbc:prev(Ref),
{error, result_set_does_not_exist} = odbc:select(Ref, next, 1),
{error, result_set_does_not_exist} =
odbc:select(Ref, {absolute, 2}, 1),
{error, result_set_does_not_exist} =
odbc:select(Ref, {relative, 2}, 1),
ok.
%%-------------------------------------------------------------------------
query_error() ->
[{doc, "Test what happens if there is an error in the query."}].
query_error(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID integer, DATA char(10), PRIMARY KEY(ID))"),
{updated, 1} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++ " VALUES(1,'bar')"),
{error, _} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++ " VALUES(1,'bar')"),
{error, _} =
odbc:sql_query(Ref, "INSERT ONTO " ++ Table ++ " VALUES(1,'bar')"),
ok.
%%-------------------------------------------------------------------------
multiple_select_result_sets() ->
[{doc, "Test what happens if you have a batch of select queries."}].
multiple_select_result_sets(Config) when is_list(Config) ->
case ?RDBMS of
sqlserver ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID integer, DATA varchar(10), "
"PRIMARY KEY(ID))"),
{updated, 1} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(1,'bar')"),
{updated, 1} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(2, 'foo')"),
MultipleResult = ?RDBMS:multiple_select(),
MultipleResult =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table ++
"; SELECT DATA FROM "++ Table ++
" WHERE ID=2"),
ok;
_ ->
{skip, "multiple result_set not supported"}
end.
%%-------------------------------------------------------------------------
multiple_mix_result_sets() ->
[{doc, "Test what happens if you have a batch of select and other type of"
" queries."}].
multiple_mix_result_sets(Config) when is_list(Config) ->
case ?RDBMS of
sqlserver ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID integer, DATA varchar(10), "
"PRIMARY KEY(ID))"),
{updated, 1} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(1,'bar')"),
MultipleResult = ?RDBMS:multiple_mix(),
MultipleResult =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(2,'foo'); UPDATE " ++ Table ++
" SET DATA = 'foobar' WHERE ID =1;SELECT "
"* FROM "
++ Table ++ ";DELETE FROM " ++ Table ++
" WHERE ID =1; SELECT DATA FROM " ++ Table),
ok;
_ ->
{skip, "multiple result_set not supported"}
end.
%%-------------------------------------------------------------------------
multiple_result_sets_error() ->
[{doc, "Test what happens if one of the batched queries fails."}].
multiple_result_sets_error(Config) when is_list(Config) ->
case ?RDBMS of
sqlserver ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID integer, DATA varchar(10), "
"PRIMARY KEY(ID))"),
{updated, 1} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(1,'bar')"),
{error, Error} =
odbc:sql_query(Ref, "INSERT INTO " ++ Table ++
" VALUES(1,'foo'); SELECT * FROM " ++ Table),
is_driver_error(Error),
{error, NewError} =
odbc:sql_query(Ref, "SELECT * FROM "
++ Table ++ ";INSERT INTO " ++ Table ++
" VALUES(1,'foo')"),
is_driver_error(NewError),
ok;
_ ->
{skip, "multiple result_set not supported"}
end.
%%-------------------------------------------------------------------------
param_insert_tiny_int()->
[{doc,"Test insertion of tiny ints by parameterized queries."}].
param_insert_tiny_int(Config) when is_list(Config) ->
case ?RDBMS of
sqlserver ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (FIELD TINYINT)"),
{updated, Count} =
odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{sql_tinyint, [1, 2]}],
?TIMEOUT),%Make sure to test timeout clause
true = odbc_test_lib:check_row_count(2, Count),
InsertResult = ?RDBMS:param_select_tiny_int(),
InsertResult =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
{'EXIT',{badarg,odbc,param_query,'Params'}} =
(catch odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{sql_tinyint, [1, "2"]}])),
ok;
_ ->
{skip, "Type tiniyint not supported"}
end.
%%-------------------------------------------------------------------------
param_insert_small_int()->
[{doc,"Test insertion of small ints by parameterized queries."}].
param_insert_small_int(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (FIELD SMALLINT)"),
{updated, Count} =
odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)", [{sql_smallint, [1, 2]}],
?TIMEOUT), %% Make sure to test timeout clause
true = odbc_test_lib:check_row_count(2, Count),
InsertResult = ?RDBMS:param_select_small_int(),
InsertResult =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
{'EXIT',{badarg,odbc,param_query,'Params'}} =
(catch odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{sql_smallint, [1, "2"]}])),
ok.
%%-------------------------------------------------------------------------
param_insert_int()->
[{doc,"Test insertion of ints by parameterized queries."}].
param_insert_int(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (FIELD INT)"),
Int = ?RDBMS:small_int_max() + 1,
{updated, Count} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{sql_integer, [1, Int]}]),
true = odbc_test_lib:check_row_count(2, Count),
InsertResult = ?RDBMS:param_select_int(),
InsertResult =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
{'EXIT',{badarg,odbc,param_query,'Params'}} =
(catch odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{sql_integer, [1, "2"]}])),
ok.
%%-------------------------------------------------------------------------
param_insert_integer()->
[{doc,"Test insertion of integers by parameterized queries."}].
param_insert_integer(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (FIELD INTEGER)"),
Int = ?RDBMS:small_int_max() + 1,
{updated, Count} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{sql_integer, [1, Int]}]),
true = odbc_test_lib:check_row_count(2, Count),
InsertResult = ?RDBMS:param_select_int(),
InsertResult =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
{'EXIT',{badarg,odbc,param_query,'Params'}} =
(catch odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{sql_integer, [1, 2.3]}])),
ok.
%%-------------------------------------------------------------------------
param_insert_decimal()->
[{doc,"Test insertion of decimal numbers by parameterized queries."}].
param_insert_decimal(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (FIELD DECIMAL (3,0))"),
{updated, Count} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{{sql_decimal, 3, 0}, [1, 2]}]),
true = odbc_test_lib:check_row_count(2, Count),
InsertResult = ?RDBMS:param_select_decimal(),
InsertResult =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
{'EXIT',{badarg,odbc,param_query,'Params'}} =
(catch odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{{sql_decimal, 3, 0}, [1, "2"]}])),
odbc:sql_query(Ref, "DROP TABLE " ++ Table),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (FIELD DECIMAL (3,1))"),
{updated, NewCount} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{{sql_decimal, 3, 1}, [0.25]}]),
true = odbc_test_lib:check_row_count(1, NewCount),
{selected, Fields, [{Value}]} =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
["FIELD"] = odbc_test_lib:to_upper(Fields),
odbc_test_lib:match_float(Value, 0.3, 0.01),
ok.
%%-------------------------------------------------------------------------
param_insert_numeric()->
[{doc,"Test insertion of numeric numbers by parameterized queries."}].
param_insert_numeric(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (FIELD NUMERIC (3,0))"),
{updated, Count} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{{sql_numeric,3,0}, [1, 2]}]),
true = odbc_test_lib:check_row_count(2, Count),
InsertResult = ?RDBMS:param_select_numeric(),
InsertResult =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
{'EXIT',{badarg,odbc,param_query,'Params'}} =
(catch odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{{sql_decimal, 3, 0}, [1, "2"]}])),
odbc:sql_query(Ref, "DROP TABLE " ++ Table),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (FIELD NUMERIC (3,1))"),
{updated, NewCount} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{{sql_numeric, 3, 1}, [0.25]}]),
true = odbc_test_lib:check_row_count(1, NewCount),
{selected, Fileds, [{Value}]} =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
["FIELD"] = odbc_test_lib:to_upper(Fileds),
odbc_test_lib:match_float(Value, 0.3, 0.01),
ok.
%%-------------------------------------------------------------------------
param_insert_char()->
[{doc,"Test insertion of fixed length string by parameterized queries."}].
param_insert_char(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (FIELD CHAR (10))"),
{updated, Count} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{{sql_char, 10},
["foofoofoof", "0123456789"]}]),
true = odbc_test_lib:check_row_count(2, Count),
{selected,Fileds,[{"foofoofoof"}, {"0123456789"}]} =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
["FIELD"] = odbc_test_lib:to_upper(Fileds),
{error, _} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{{sql_char, 10},
["foo", "01234567890"]}]),
{'EXIT',{badarg,odbc,param_query,'Params'}} =
(catch odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{{sql_char, 10}, ["1", 2.3]}])),
ok.
%%-------------------------------------------------------------------------
param_insert_character()->
[{doc,"Test insertion of fixed length string by parameterized queries."}].
param_insert_character(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (FIELD CHARACTER (10))"),
{updated, Count} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{{sql_char, 10},
["foofoofoof", "0123456789"]}]),
true = odbc_test_lib:check_row_count(2, Count),
{selected, Fileds, [{"foofoofoof"}, {"0123456789"}]} =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
["FIELD"] = odbc_test_lib:to_upper(Fileds),
{error, _} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{{sql_char, 10},
["foo", "01234567890"]}]),
{'EXIT',{badarg,odbc,param_query,'Params'}} =
(catch odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{{sql_char, 10}, ["1", 2]}])),
ok.
%%------------------------------------------------------------------------
param_insert_char_varying()->
[{doc,"Test insertion of variable length strings by parameterized queries."}].
param_insert_char_varying(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (FIELD CHAR VARYING(10))"),
{updated, Count} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{{sql_varchar, 10},
["foo", "0123456789"]}]),
true = odbc_test_lib:check_row_count(2, Count),
{selected, Fileds, [{"foo"}, {"0123456789"}]} =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
["FIELD"] = odbc_test_lib:to_upper(Fileds),
{error, _} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{{sql_varchar, 10},
["foo", "01234567890"]}]),
{'EXIT',{badarg,odbc,param_query,'Params'}} =
(catch odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{{sql_varchar, 10}, ["1", 2.3]}])),
ok.
%%-------------------------------------------------------------------------
param_insert_character_varying()->
[{doc,"Test insertion of variable length strings by parameterized queries."}].
param_insert_character_varying(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (FIELD CHARACTER VARYING(10))"),
{updated, Count} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{{sql_varchar, 10},
["foo", "0123456789"]}]),
true = odbc_test_lib:check_row_count(2, Count),
{selected, Fileds, [{"foo"}, {"0123456789"}]} =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
["FIELD"] = odbc_test_lib:to_upper(Fileds),
{error, _} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{{sql_varchar, 10},
["foo", "01234567890"]}]),
{'EXIT',{badarg,odbc,param_query,'Params'}} =
(catch odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{{sql_varchar, 10}, ["1", 2]}])),
ok.
%%-------------------------------------------------------------------------
param_insert_float()->
[{doc,"Test insertion of floats by parameterized queries."}].
param_insert_float(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (FIELD FLOAT(5))"),
{updated, Count} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{{sql_float,5}, [1.3, 1.2]}]),
true = odbc_test_lib:check_row_count(2, Count),
{selected, Fileds, [{Float1},{Float2}]} =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
["FIELD"] = odbc_test_lib:to_upper(Fileds),
case (odbc_test_lib:match_float(Float1, 1.3, 0.000001) and
odbc_test_lib:match_float(Float2, 1.2, 0.000001)) of
true ->
ok;
false ->
ct:fail(float_numbers_do_not_match)
end,
{'EXIT',{badarg,odbc,param_query,'Params'}} =
(catch odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{{sql_float, 5}, [1.0, "2"]}])),
ok.
%%-------------------------------------------------------------------------
param_insert_real()->
[{doc,"Test insertion of real numbers by parameterized queries."}].
param_insert_real(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (FIELD REAL)"),
{updated, Count} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{sql_real, [1.3, 1.2]}]),
true = odbc_test_lib:check_row_count(2, Count),
%_InsertResult = ?RDBMS:param_select_real(),
{selected, Fileds, [{Real1},{Real2}]} =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
["FIELD"] = odbc_test_lib:to_upper(Fileds),
case (odbc_test_lib:match_float(Real1, 1.3, 0.000001) and
odbc_test_lib:match_float(Real2, 1.2, 0.000001)) of
true ->
ok;
false ->
ct:fail(real_numbers_do_not_match)
end,
{'EXIT',{badarg,odbc,param_query,'Params'}} =
(catch odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{sql_real,[1.0, "2"]}])),
ok.
%%-------------------------------------------------------------------------
param_insert_double()->
[{doc,"Test insertion of doubles by parameterized queries."}].
param_insert_double(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (FIELD DOUBLE PRECISION)"),
{updated, Count} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{sql_double, [1.3, 1.2]}]),
true = odbc_test_lib:check_row_count(2, Count),
{selected, Fileds, [{Double1},{Double2}]} =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
["FIELD"] = odbc_test_lib:to_upper(Fileds),
case (odbc_test_lib:match_float(Double1, 1.3, 0.000001) and
odbc_test_lib:match_float(Double2, 1.2, 0.000001)) of
true ->
ok;
false ->
ct:fail(double_numbers_do_not_match)
end,
{'EXIT',{badarg,odbc,param_query,'Params'}} =
(catch odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(FIELD) VALUES(?)",
[{sql_double, [1.0, "2"]}])),
ok.
%%-------------------------------------------------------------------------
param_insert_mix()->
[{doc,"Test insertion of a mixture of datatypes by parameterized queries."}].
param_insert_mix(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID INTEGER, DATA CHARACTER VARYING(10),"
" PRIMARY KEY(ID))"),
{updated, Count} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(ID, DATA) VALUES(?, ?)",
[{sql_integer, [1, 2]},
{{sql_varchar, 10}, ["foo", "bar"]}]),
true = odbc_test_lib:check_row_count(2, Count),
InsertResult = ?RDBMS:param_select_mix(),
InsertResult =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
ok.
%%-------------------------------------------------------------------------
param_update()->
[{doc,"Test parameterized update query."}].
param_update(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID INTEGER, DATA CHARACTER VARYING(10),"
" PRIMARY KEY(ID))"),
{updated, Count} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(ID, DATA) VALUES(?, ?)",
[{sql_integer, [1, 2, 3]},
{{sql_varchar, 10},
["foo", "bar", "baz"]}]),
true = odbc_test_lib:check_row_count(3, Count),
{updated, NewCount} = odbc:param_query(Ref, "UPDATE " ++ Table ++
" SET DATA = 'foobar' WHERE ID = ?",
[{sql_integer, [1, 2]}]),
true = odbc_test_lib:check_row_count(2, NewCount),
UpdateResult = ?RDBMS:param_update(),
UpdateResult =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
ok.
%%-------------------------------------------------------------------------
delete_nonexisting_row() -> % OTP-5759
[{doc, "Make a delete...where with false conditions (0 rows deleted). ",
"This used to give an error message (see ticket OTP-5759)."}].
delete_nonexisting_row(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref, "CREATE TABLE " ++ Table
++ " (ID INTEGER, DATA CHARACTER VARYING(10))"),
{updated, Count} =
odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(ID, DATA) VALUES(?, ?)",
[{sql_integer, [1, 2, 3]},
{{sql_varchar, 10}, ["foo", "bar", "baz"]}]),
true = odbc_test_lib:check_row_count(3, Count),
{updated, NewCount} =
odbc:sql_query(Ref, "DELETE FROM " ++ Table ++ " WHERE ID = 8"),
true = odbc_test_lib:check_row_count(0, NewCount),
{updated, _} =
odbc:sql_query(Ref, "DROP TABLE "++ Table),
ok.
%%-------------------------------------------------------------------------
param_delete() ->
[{doc,"Test parameterized delete query."}].
param_delete(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID INTEGER, DATA CHARACTER VARYING(10),"
" PRIMARY KEY(ID))"),
{updated, Count} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(ID, DATA) VALUES(?, ?)",
[{sql_integer, [1, 2, 3]},
{{sql_varchar, 10},
["foo", "bar", "baz"]}]),
true = odbc_test_lib:check_row_count(3, Count),
{updated, NewCount} = odbc:param_query(Ref, "DELETE FROM " ++ Table ++
" WHERE ID = ?",
[{sql_integer, [1, 2]}]),
true = odbc_test_lib:check_row_count(2, NewCount),
UpdateResult = ?RDBMS:param_delete(),
UpdateResult =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
ok.
%%-------------------------------------------------------------------------
param_select() ->
[{doc,"Test parameterized select query."}].
param_select(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID INTEGER, DATA CHARACTER VARYING(10),"
" PRIMARY KEY(ID))"),
{updated, Count} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(ID, DATA) VALUES(?, ?)",
[{sql_integer, [1, 2, 3]},
{{sql_varchar, 10},
["foo", "bar", "foo"]}]),
true = odbc_test_lib:check_row_count(3, Count),
SelectResult = ?RDBMS:param_select(),
SelectResult = odbc:param_query(Ref, "SELECT * FROM " ++ Table ++
" WHERE DATA = ?",
[{{sql_varchar, 10}, ["foo"]}]),
ok.
%%-------------------------------------------------------------------------
param_select_empty_params() ->
[{doc,"Test parameterized select query with no parameters."}].
param_select_empty_params(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID INTEGER, DATA CHARACTER VARYING(10),"
" PRIMARY KEY(ID))"),
{updated, Count} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(ID, DATA) VALUES(?, ?)",
[{sql_integer, [1, 2, 3]},
{{sql_varchar, 10},
["foo", "bar", "foo"]}]),
true = odbc_test_lib:check_row_count(3, Count),
SelectResult = ?RDBMS:param_select(),
SelectResult = odbc:param_query(Ref, "SELECT * FROM " ++ Table ++
" WHERE DATA = \'foo\'",
[]),
ok.
%%-------------------------------------------------------------------------
param_delete_empty_params() ->
[{doc,"Test parameterized delete query with no parameters."}].
param_delete_empty_params(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (ID INTEGER, DATA CHARACTER VARYING(10),"
" PRIMARY KEY(ID))"),
{updated, Count} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
"(ID, DATA) VALUES(?, ?)",
[{sql_integer, [1, 2, 3]},
{{sql_varchar, 10},
["foo", "bar", "baz"]}]),
true = odbc_test_lib:check_row_count(3, Count),
{updated, NewCount} = odbc:param_query(Ref, "DELETE FROM " ++ Table ++
" WHERE ID = 1 OR ID = 2",
[]),
true = odbc_test_lib:check_row_count(2, NewCount),
UpdateResult = ?RDBMS:param_delete(),
UpdateResult =
odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
ok.
%%-------------------------------------------------------------------------
describe_integer() ->
[{doc,"Test describe_table/[2,3] for integer columns."}].
describe_integer(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (myint1 SMALLINT, myint2 INT, myint3 INTEGER)"),
Decs = ?RDBMS:describe_integer(),
%% Make sure to test timeout clause
Decs = odbc:describe_table(Ref, Table, ?TIMEOUT),
ok.
%%-------------------------------------------------------------------------
describe_string() ->
[{doc,"Test describe_table/[2,3] for string columns."}].
describe_string(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (str1 char(10), str2 character(10), "
"str3 CHAR VARYING(10), str4 "
"CHARACTER VARYING(10))"),
Decs = ?RDBMS:describe_string(),
Decs = odbc:describe_table(Ref, Table),
ok.
%%-------------------------------------------------------------------------
describe_floating() ->
[{doc,"Test describe_table/[2,3] for floting columns."}].
describe_floating(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (f FLOAT(5), r REAL, "
"d DOUBLE PRECISION)"),
Decs = ?RDBMS:describe_floating(),
Decs = odbc:describe_table(Ref, Table),
ok.
%%-------------------------------------------------------------------------
describe_dec_num() ->
[{doc,"Test describe_table/[2,3] for decimal and numerical columns"}].
describe_dec_num(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} =
odbc:sql_query(Ref,
"CREATE TABLE " ++ Table ++
" (mydec DECIMAL(9,3), mynum NUMERIC(9,2))"),
Decs = ?RDBMS:describe_dec_num(),
Decs = odbc:describe_table(Ref, Table),
ok.
%%-------------------------------------------------------------------------
describe_timestamp() ->
[{doc,"Test describe_table/[2,3] for tinmestap columns"}].
describe_timestamp(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{updated, _} = % Value == 0 || -1 driver dependent!
odbc:sql_query(Ref, "CREATE TABLE " ++ Table ++
?RDBMS:create_timestamp_table()),
Decs = ?RDBMS:describe_timestamp(),
Decs = odbc:describe_table(Ref, Table),
ok.
%%-------------------------------------------------------------------------
describe_no_such_table() ->
[{doc,"Test what happens if you try to describe a table that does not exist."}].
describe_no_such_table(Config) when is_list(Config) ->
Ref = proplists:get_value(connection_ref, Config),
Table = proplists:get_value(tableName, Config),
{error, _ } = odbc:describe_table(Ref, Table),
ok.
%%-------------------------------------------------------------------------
%% Internal functions
%%-------------------------------------------------------------------------
is_driver_error(Error) ->
case is_list(Error) of
true ->
ct:pal("Driver error ~p~n", [Error]),
ok;
false ->
ct:fail(Error)
end.
is_supported_multiple_resultsets(sqlserver) ->
true;
is_supported_multiple_resultsets(_) ->
false.