aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/emulator/drivers/common/efile_drv.c159
-rw-r--r--erts/preloaded/ebin/prim_file.beambin31640 -> 32340 bytes
-rw-r--r--erts/preloaded/src/prim_file.erl21
-rw-r--r--erts/vsn.mk4
-rw-r--r--lib/kernel/vsn.mk2
-rw-r--r--lib/odbc/test/odbc_connect_SUITE.erl92
-rw-r--r--lib/odbc/test/odbc_data_type_SUITE.erl37
-rw-r--r--lib/odbc/test/odbc_query_SUITE.erl21
-rw-r--r--lib/odbc/test/odbc_start_SUITE.erl10
-rw-r--r--lib/odbc/test/odbc_test.hrl7
-rw-r--r--lib/odbc/test/odbc_test_lib.erl21
-rw-r--r--lib/stdlib/vsn.mk2
12 files changed, 219 insertions, 157 deletions
diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c
index f0ff3f54c5..68987b3493 100644
--- a/erts/emulator/drivers/common/efile_drv.c
+++ b/erts/emulator/drivers/common/efile_drv.c
@@ -69,6 +69,7 @@
#define FILE_RESP_EOF 8
#define FILE_RESP_FNAME 9
#define FILE_RESP_ALL_DATA 10
+#define FILE_RESP_LFNAME 11
/* Options */
@@ -184,6 +185,7 @@ static ErlDrvSysInfo sys_info;
# define RESBUFSIZE BUFSIZ
#endif
+#define READDIR_CHUNKS (5)
@@ -317,15 +319,16 @@ struct t_preadv {
Sint64 offsets[1];
};
-#define READDIR_BUFSIZE (8*1024)
-#if READDIR_BUFSIZE < (FILENAME_CHARSIZE*2*(MAXPATHLEN+1))
+#define READDIR_BUFSIZE (8*1024)*READDIR_CHUNKS
+#if READDIR_BUFSIZE < (1 + (2 + MAXPATHLEN)*FILENAME_CHARSIZE*READDIR_CHUNKS)
# undef READDIR_BUFSIZE
-# define READDIR_BUFSIZE (FILENAME_CHARSIZE*2*(MAXPATHLEN+1))
+# define READDIR_BUFSIZE (1 + (2 + MAXPATHLEN)*FILENAME_CHARSIZE*READDIR_CHUNKS)
#endif
struct t_readdir_buf {
- struct t_readdir_buf *next;
- char buf[READDIR_BUFSIZE];
+ struct t_readdir_buf *next;
+ size_t n;
+ char buf[READDIR_BUFSIZE];
};
struct t_data
@@ -1598,54 +1601,46 @@ static void invoke_lseek(void *data)
static void invoke_readdir(void *data)
{
struct t_data *d = (struct t_data *) data;
- int s;
char *p = NULL;
- int buf_sz = 0;
- size_t tmp_bs;
+ size_t file_bs;
+ size_t n = 0, total = 0;
+ struct t_readdir_buf *b = NULL;
+ int res = 0;
d->again = 0;
d->errInfo.posix_errno = 0;
- while (1) {
- char *str;
- if (buf_sz < (4 /* sz */ + 1 /* cmd */ +
- FILENAME_CHARSIZE*(MAXPATHLEN + 1))) {
- struct t_readdir_buf *b;
- if (p) {
- put_int32(0, p); /* EOB */
- }
- b = EF_SAFE_ALLOC(sizeof(struct t_readdir_buf));
- b->next = NULL;
- if (d->c.read_dir.last_buf)
- d->c.read_dir.last_buf->next = b;
- else
- d->c.read_dir.first_buf = b;
- d->c.read_dir.last_buf = b;
- p = &b->buf[0];
- buf_sz = READDIR_BUFSIZE - 4/* EOB */;
- }
-
- p[4] = FILE_RESP_FNAME;
- buf_sz -= 4 + 1;
- str = p + 4 + 1;
- ASSERT(buf_sz >= MAXPATHLEN + 1);
- tmp_bs = buf_sz;
- s = efile_readdir(&d->errInfo, d->b, &d->dir_handle, str, &tmp_bs);
-
- if (s) {
- put_int32(tmp_bs + 1 /* 1 byte for opcode */, p);
- p += 4 + tmp_bs + 1;
- ASSERT(p == (str + tmp_bs));
- buf_sz -= tmp_bs;
- }
- else {
- put_int32(1, p);
- p += 4 + 1;
- put_int32(0, p); /* EOB */
- d->result_ok = (d->errInfo.posix_errno == 0);
- break;
+ do {
+ total = READDIR_BUFSIZE;
+ n = 1;
+ b = EF_SAFE_ALLOC(sizeof(struct t_readdir_buf));
+ b->next = NULL;
+
+ if (d->c.read_dir.last_buf) {
+ d->c.read_dir.last_buf->next = b;
+ } else {
+ d->c.read_dir.first_buf = b;
}
- }
+ d->c.read_dir.last_buf = b;
+
+ p = &b->buf[0];
+ p[0] = FILE_RESP_LFNAME;
+ file_bs = READDIR_BUFSIZE - n;
+
+ do {
+ res = efile_readdir(&d->errInfo, d->b, &d->dir_handle, p + n + 2, &file_bs);
+
+ if (res) {
+ put_int16((Uint16)file_bs, p + n);
+ n += 2 + file_bs;
+ file_bs = READDIR_BUFSIZE - n;
+ }
+ } while( res && ((total - n - 2) >= MAXPATHLEN*FILENAME_CHARSIZE));
+
+ b->n = n;
+ } while(res);
+
+ d->result_ok = (d->errInfo.posix_errno == 0);
}
static void invoke_open(void *data)
@@ -2053,30 +2048,24 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data)
free_data(data);
break;
case FILE_READDIR:
- if (!d->result_ok)
+ if (!d->result_ok) {
reply_error(desc, &d->errInfo);
- else {
+ } else {
struct t_readdir_buf *b1 = d->c.read_dir.first_buf;
+ char op = FILE_RESP_LFNAME;
+
TRACE_C('R');
ASSERT(b1);
+
while (b1) {
struct t_readdir_buf *b2 = b1;
char *p = &b1->buf[0];
- int sz = get_int32(p);
- while (sz) { /* 0 == EOB */
- p += 4;
- if (sz - 1 > 0) {
- driver_output2(desc->port, p, 1, p+1, sz-1);
- } else {
- driver_output2(desc->port, p, 1, NULL, 0);
- }
- p += sz;
- sz = get_int32(p);
- }
+ driver_output2(desc->port, p, 1, p + 1, b1->n - 1);
b1 = b1->next;
EF_FREE(b2);
}
-
+ driver_output2(desc->port, &op, 1, NULL, 0);
+
d->c.read_dir.first_buf = NULL;
d->c.read_dir.last_buf = NULL;
}
@@ -2126,6 +2115,7 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data)
cq_execute(desc);
}
+
/*********************************************************************
* Driver entry point -> output
*/
@@ -2246,19 +2236,46 @@ file_output(ErlDrvData e, char* buf, int count)
#endif
{
size_t resbufsize;
- char resbuf[RESBUFSIZE+1];
+ size_t n = 0, total = 0;
+ int res = 0;
+ char resbuf[READDIR_BUFSIZE];
+
EFILE_DIR_HANDLE dir_handle; /* Handle to open directory. */
+ total = READDIR_BUFSIZE;
errInfo.posix_errno = 0;
- dir_handle = NULL;
- resbuf[0] = FILE_RESP_FNAME;
- resbufsize = RESBUFSIZE;
-
- while (efile_readdir(&errInfo, name, &dir_handle,
- resbuf+1, &resbufsize)) {
- driver_output2(desc->port, resbuf, 1, resbuf+1, resbufsize);
- resbufsize = RESBUFSIZE;
- }
+ dir_handle = NULL;
+ resbuf[0] = FILE_RESP_LFNAME;
+
+ /* Fill the buffer with multiple directory listings before sending it to the
+ * receiving process. READDIR_CHUNKS is minimum number of files sent to the
+ * receiver.
+ * Format for each driver_output2:
+ * ------------------------------------
+ * | Type | Len | Filename | ...
+ * | 1 byte | 2 bytes | Len bytes | ...
+ * ------------------------------------
+ */
+
+ do {
+ n = 1;
+ resbufsize = READDIR_BUFSIZE - n;
+
+ do {
+ res = efile_readdir(&errInfo, name, &dir_handle, resbuf + n + 2, &resbufsize);
+
+ if (res) {
+ put_int16((Uint16)resbufsize, resbuf + n);
+ n += 2 + resbufsize;
+ resbufsize = READDIR_BUFSIZE - n;
+ }
+ } while( res && ((total - n - 2) >= MAXPATHLEN*FILENAME_CHARSIZE));
+
+ if (n > 1) {
+ driver_output2(desc->port, resbuf, 1, resbuf + 1, n - 1);
+ }
+ } while(res);
+
if (errInfo.posix_errno != 0) {
reply_error(desc, &errInfo);
return;
diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam
index 00a1cf065a..03d0de9129 100644
--- a/erts/preloaded/ebin/prim_file.beam
+++ b/erts/preloaded/ebin/prim_file.beam
Binary files differ
diff --git a/erts/preloaded/src/prim_file.erl b/erts/preloaded/src/prim_file.erl
index ac7570582e..b18a57bfef 100644
--- a/erts/preloaded/src/prim_file.erl
+++ b/erts/preloaded/src/prim_file.erl
@@ -111,6 +111,7 @@
-define(FILE_RESP_EOF, 8).
-define(FILE_RESP_FNAME, 9).
-define(FILE_RESP_ALL_DATA, 10).
+-define(FILE_RESP_LFNAME, 11).
%% Open modes for the driver's open function.
-define(EFILE_MODE_READ, 1).
@@ -914,6 +915,8 @@ drv_get_response(Port, R) when is_list(R) ->
{ok, R};
{ok, Name} ->
drv_get_response(Port, [Name|R]);
+ {append, Names} ->
+ drv_get_response(Port, append(Names, R));
Error ->
Error
end;
@@ -938,6 +941,8 @@ drv_get_response(Port) ->
%%%-----------------------------------------------------------------
%%% Utility functions.
+append([I | Is], R) when is_list(R) -> append(Is, [I | R]);
+append([], R) -> R.
%% Converts a list of mode atoms into an mode word for the driver.
@@ -1067,7 +1072,7 @@ translate_response(?FILE_RESP_N2DATA,
{ok, {Size, Offset, D}};
translate_response(?FILE_RESP_N2DATA = X, L0) when is_list(L0) ->
{Offset, L1} = get_uint64(L0),
- {ReadSize, L2} = get_uint64(L1),
+ {ReadSize, L2} = get_uint64(L1),
{Size, L3} = get_uint64(L2),
case {ReadSize, L3} of
{0, []} ->
@@ -1087,6 +1092,12 @@ translate_response(?FILE_RESP_FNAME, Data) when is_binary(Data) ->
{ok, prim_file:internal_native2name(Data)};
translate_response(?FILE_RESP_FNAME, Data) ->
{ok, Data};
+translate_response(?FILE_RESP_LFNAME, []) ->
+ ok;
+translate_response(?FILE_RESP_LFNAME, Data) when is_binary(Data) ->
+ {append, transform_lfname(Data)};
+translate_response(?FILE_RESP_LFNAME, Data) ->
+ {append, transform_lfname(Data)};
translate_response(?FILE_RESP_ALL_DATA, Data) ->
{ok, Data};
translate_response(X, Data) ->
@@ -1199,6 +1210,14 @@ transform_ldata(0, List, [Size | Sizes], R) ->
{Front, Rear} = lists_split(List, Size),
transform_ldata(0, Rear, Sizes, [Front | R]).
+transform_lfname(<<>>) -> [];
+transform_lfname(<<L:16, Name:L/binary, Names/binary>>) ->
+ [ prim_file:internal_native2name(Name) | transform_lfname(Names)];
+transform_lfname([]) -> [];
+transform_lfname([L1,L2|Names]) ->
+ L = (L1 bsl 8) bor L2,
+ {Name, Rest} = lists_split(Names, L),
+ [Name | transform_lfname(Rest)].
lists_split(List, 0) when is_list(List) ->
diff --git a/erts/vsn.mk b/erts/vsn.mk
index 18799d2fba..d56d03146d 100644
--- a/erts/vsn.mk
+++ b/erts/vsn.mk
@@ -17,8 +17,8 @@
# %CopyrightEnd%
#
-VSN = 5.8.5
-SYSTEM_VSN = R14B04
+VSN = 5.9
+SYSTEM_VSN = R15A
# Port number 4365 in 4.2
# Port number 4366 in 4.3
diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk
index 8be265e79d..76c62ece67 100644
--- a/lib/kernel/vsn.mk
+++ b/lib/kernel/vsn.mk
@@ -1 +1 @@
-KERNEL_VSN = 2.14.5
+KERNEL_VSN = 2.15
diff --git a/lib/odbc/test/odbc_connect_SUITE.erl b/lib/odbc/test/odbc_connect_SUITE.erl
index 6eaf3a81c4..e59be772e3 100644
--- a/lib/odbc/test/odbc_connect_SUITE.erl
+++ b/lib/odbc/test/odbc_connect_SUITE.erl
@@ -80,7 +80,7 @@ init_per_suite(Config) ->
case (catch odbc:start()) of
ok ->
case catch odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]) of
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()) of
{ok, Ref} ->
odbc:disconnect(Ref),
[{tableName, odbc_test_lib:unique_table_name()} | Config];
@@ -116,12 +116,6 @@ init_per_testcase(_TestCase, Config) ->
Dog = test_server:timetrap(?default_timeout),
Temp = lists:keydelete(connection_ref, 1, Config),
NewConfig = lists:keydelete(watchdog, 1, Temp),
- %% Clean up if needed
- Table = ?config(tableName, Config),
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
- Result = odbc:sql_query(Ref, "DROP TABLE " ++ Table),
- io:format("Drop table: ~p ~p~n", [Table, Result]),
- odbc:disconnect(Ref),
[{watchdog, Dog} | NewConfig].
%%--------------------------------------------------------------------
@@ -133,6 +127,11 @@ init_per_testcase(_TestCase, Config) ->
%% Description: Cleanup after each test case
%%--------------------------------------------------------------------
end_per_testcase(_TestCase, Config) ->
+ Table = ?config(tableName, Config),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
+ Result = odbc:sql_query(Ref, "DROP TABLE " ++ Table),
+ io:format("Drop table: ~p ~p~n", [Table, Result]),
+ odbc:disconnect(Ref),
Dog = ?config(watchdog, Config),
test_server:timetrap_cancel(Dog).
@@ -144,7 +143,7 @@ commit(doc)->
commit(suite) -> [];
commit(Config) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
Table = ?config(tableName, Config),
TransStr = transaction_support_str(?RDBMS),
@@ -184,8 +183,11 @@ rollback(doc)->
["Test the use of explicit rollback"];
rollback(suite) -> [];
rollback(Config) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), [{auto_commit, off}]),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
+
Table = ?config(tableName, Config),
+
TransStr = transaction_support_str(?RDBMS),
{updated, _} =
@@ -222,7 +224,8 @@ not_explicit_commit(doc) ->
not_explicit_commit(suite) -> [];
not_explicit_commit(_Config) ->
{ok, Ref} =
- odbc:connect(?RDBMS:connection_string(), [{auto_commit, on}]),
+ odbc:connect(?RDBMS:connection_string(), [{auto_commit, on}] ++
+ odbc_test_lib:platform_options()),
{error, _} = odbc:commit(Ref, commit),
ok = odbc:disconnect(Ref).
@@ -231,7 +234,8 @@ not_exist_db(doc) ->
["Tests valid data format but invalid data in the connection parameters."];
not_exist_db(suite) -> [];
not_exist_db(_Config) ->
- {error, _} = odbc:connect("DSN=foo;UID=bar;PWD=foobar", []),
+ {error, _} = odbc:connect("DSN=foo;UID=bar;PWD=foobar",
+ odbc_test_lib:platform_options()),
%% So that the odbc control server can be stoped "in the correct way"
test_server:sleep(100).
@@ -248,7 +252,8 @@ no_c_node(_Config) ->
FileName2 = filename:nativename(filename:join(Dir, "odbcsrv")),
ok = file:rename(FileName1, FileName2),
Result =
- case catch odbc:connect(?RDBMS:connection_string(), []) of
+ case catch odbc:connect(?RDBMS:connection_string(),
+ odbc_test_lib:platform_options()) of
{error, port_program_executable_not_found} ->
ok;
Else ->
@@ -263,7 +268,7 @@ port_dies(doc) ->
"Tests what happens if the port program dies";
port_dies(suite) -> [];
port_dies(_Config) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
{status, _} = process_info(Ref, status),
process_flag(trap_exit, true),
Port = lists:last(erlang:ports()),
@@ -279,7 +284,7 @@ control_process_dies(doc) ->
"Tests what happens if the Erlang control process dies";
control_process_dies(suite) -> [];
control_process_dies(_Config) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
process_flag(trap_exit, true),
Port = lists:last(erlang:ports()),
{connected, Ref} = erlang:port_info(Port, connected),
@@ -312,7 +317,7 @@ client_dies_normal(Config) when is_list(Config) ->
end.
client_normal(Pid) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
Pid ! {dbRef, Ref},
receive
continue ->
@@ -344,7 +349,7 @@ client_dies_timeout(Config) when is_list(Config) ->
end.
client_timeout(Pid) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
Pid ! {dbRef, Ref},
receive
continue ->
@@ -376,7 +381,7 @@ client_dies_error(Config) when is_list(Config) ->
end.
client_error(Pid) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
Pid ! {dbRef, Ref},
receive
continue ->
@@ -391,7 +396,8 @@ connect_timeout(doc) ->
connect_timeout(suite) -> [];
connect_timeout(Config) when is_list(Config) ->
{'EXIT',timeout} = (catch odbc:connect(?RDBMS:connection_string(),
- [{timeout, 0}])),
+ [{timeout, 0}] ++
+ odbc_test_lib:platform_options())),
%% Need to return ok here "{'EXIT',timeout} return value" will
%% be interpreted as that the testcase has timed out.
ok.
@@ -448,7 +454,7 @@ timeout(Config) when is_list(Config) ->
update_table_timeout(Table, TimeOut, Pid) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
UpdateQuery = "UPDATE " ++ Table ++ " SET DATA = 'foobar' WHERE ID = 1",
case catch odbc:sql_query(Ref, UpdateQuery, TimeOut) of
@@ -486,7 +492,7 @@ many_timeouts(doc) ->
many_timeouts(suite) -> [];
many_timeouts(Config) when is_list(Config) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
Table = ?config(tableName, Config),
TransStr = transaction_support_str(?RDBMS),
@@ -520,7 +526,7 @@ many_timeouts(Config) when is_list(Config) ->
update_table_many_timeouts(Table, TimeOut, Pid) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
UpdateQuery = "UPDATE " ++ Table ++ " SET DATA = 'foobar' WHERE ID = 1",
ok = loop_many_timouts(Ref, UpdateQuery, TimeOut),
@@ -546,7 +552,7 @@ timeout_reset(doc) ->
timeout_reset(suite) -> [];
timeout_reset(Config) when is_list(Config) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
Table = ?config(tableName, Config),
TransStr = transaction_support_str(?RDBMS),
@@ -594,7 +600,7 @@ timeout_reset(Config) when is_list(Config) ->
update_table_timeout_reset(Table, TimeOut, Pid) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
UpdateQuery = "UPDATE " ++ Table ++ " SET DATA = 'foobar' WHERE ID = 1",
ok = loop_timout_reset(Ref, UpdateQuery, TimeOut,
@@ -644,7 +650,7 @@ disconnect_on_timeout(suite) -> [];
disconnect_on_timeout(Config) when is_list(Config) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
Table = ?config(tableName, Config),
TransStr = transaction_support_str(?RDBMS),
@@ -675,7 +681,7 @@ disconnect_on_timeout(Config) when is_list(Config) ->
update_table_disconnect_on_timeout(Table, TimeOut, Pid) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{auto_commit, off}]),
+ [{auto_commit, off}] ++ odbc_test_lib:platform_options()),
UpdateQuery = "UPDATE " ++ Table ++ " SET DATA = 'foobar' WHERE ID = 1",
case catch odbc:sql_query(Ref, UpdateQuery, TimeOut) of
@@ -692,7 +698,7 @@ connection_closed(doc) ->
" use a connection that has been closed"];
connection_closed(suite) -> [];
connection_closed(Config) when is_list(Config) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
Table = ?config(tableName, Config),
{updated, _} =
@@ -758,7 +764,7 @@ return_rows_as_lists(doc)->
return_rows_as_lists(suite) -> [];
return_rows_as_lists(Config) when is_list(Config) ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{tuple_row, off}]),
+ [{tuple_row, off}] ++ odbc_test_lib:platform_options()),
Table = ?config(tableName, Config),
@@ -779,15 +785,21 @@ return_rows_as_lists(Config) when is_list(Config) ->
{ok, _} = odbc:select_count(Ref, "SELECT * FROM " ++ Table),
- First = ?RDBMS:first_list_rows(),
- Last = ?RDBMS:last_list_rows(),
- Prev = ?RDBMS:prev_list_rows(),
- Next = ?RDBMS:next_list_rows(),
-
- Last = odbc:last(Ref),
- Prev = odbc:prev(Ref),
- First = odbc:first(Ref),
- Next = odbc:next(Ref).
+ case proplists:get_value(scrollable_cursors, odbc_test_lib:platform_options()) of
+ off ->
+ Next = ?RDBMS:next_list_rows(),
+ Next = odbc:next(Ref);
+ _ ->
+ First = ?RDBMS:first_list_rows(),
+ Last = ?RDBMS:last_list_rows(),
+ Prev = ?RDBMS:prev_list_rows(),
+ Next = ?RDBMS:next_list_rows(),
+
+ Last = odbc:last(Ref),
+ Prev = odbc:prev(Ref),
+ First = odbc:first(Ref),
+ Next = odbc:next(Ref)
+ end.
%%-------------------------------------------------------------------------
@@ -796,19 +808,21 @@ api_missuse(doc)->
api_missuse(suite) -> [];
api_missuse(Config) when is_list(Config)->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
%% Serious programming fault, connetion will be shut down
gen_server:call(Ref, {self(), foobar, 10}, infinity),
test_server:sleep(10),
undefined = process_info(Ref, status),
- {ok, Ref2} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref2} = odbc:connect(?RDBMS:connection_string(),
+ odbc_test_lib:platform_options()),
%% Serious programming fault, connetion will be shut down
gen_server:cast(Ref2, {self(), foobar, 10}),
test_server:sleep(10),
undefined = process_info(Ref2, status),
- {ok, Ref3} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref3} = odbc:connect(?RDBMS:connection_string(),
+ odbc_test_lib:platform_options()),
%% Could be an innocent misstake the connection lives.
Ref3 ! foobar,
test_server:sleep(10),
diff --git a/lib/odbc/test/odbc_data_type_SUITE.erl b/lib/odbc/test/odbc_data_type_SUITE.erl
index 3585446ec8..84c99e183b 100644
--- a/lib/odbc/test/odbc_data_type_SUITE.erl
+++ b/lib/odbc/test/odbc_data_type_SUITE.erl
@@ -167,31 +167,17 @@ init_per_testcase(param_insert_tiny_int = Case, Config) ->
init_per_testcase(Case, Config) ->
common_init_per_testcase(Case, Config).
-is_supported_tinyint(sqlserver) ->
- true;
-is_supported_tinyint(_) ->
- false.
-
-is_supported_bit(sqlserver) ->
- true;
-is_supported_bit(_) ->
- false.
-
-is_fixed_upper_limit(mysql) ->
- false;
-is_fixed_upper_limit(_) ->
- true.
-
common_init_per_testcase(Case, Config) ->
+ PlatformOptions = odbc_test_lib:platform_options(),
case atom_to_list(Case) of
"binary" ++ _ ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{binary_strings, on}]);
+ [{binary_strings, on}] ++ PlatformOptions);
"unicode" ->
{ok, Ref} = odbc:connect(?RDBMS:connection_string(),
- [{binary_strings, on}]);
+ [{binary_strings, on}] ++ PlatformOptions);
_ ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), [])
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), PlatformOptions)
end,
odbc_test_lib:strict(Ref, ?RDBMS),
Dog = test_server:timetrap(?default_timeout),
@@ -199,6 +185,19 @@ common_init_per_testcase(Case, Config) ->
NewConfig = lists:keydelete(watchdog, 1, Temp),
[{watchdog, Dog}, {connection_ref, Ref} | NewConfig].
+is_fixed_upper_limit(mysql) ->
+ false;
+is_fixed_upper_limit(_) ->
+ true.
+is_supported_tinyint(sqlserver) ->
+ true;
+is_supported_tinyint(_) ->
+ false.
+is_supported_bit(sqlserver) ->
+ true;
+is_supported_bit(_) ->
+ false.
+
%%--------------------------------------------------------------------
%% Function: end_per_testcase(Case, Config) -> _
%% Case - atom()
@@ -212,7 +211,7 @@ end_per_testcase(_TestCase, Config) ->
ok = odbc:disconnect(Ref),
%% Clean up if needed
Table = ?config(tableName, Config),
- {ok, NewRef} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, NewRef} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
odbc:sql_query(NewRef, "DROP TABLE " ++ Table),
odbc:disconnect(NewRef),
Dog = ?config(watchdog, Config),
diff --git a/lib/odbc/test/odbc_query_SUITE.erl b/lib/odbc/test/odbc_query_SUITE.erl
index 6dee588076..76a214d553 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, first, last, next, prev, select_count,
+ [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,
@@ -55,8 +55,9 @@ all() ->
groups() ->
[{multiple_result_sets, [], [multiple_select_result_sets,
- multiple_mix_result_sets,
- multiple_result_sets_error]},
+ 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},
@@ -81,8 +82,16 @@ init_per_group(multiple_result_sets, Config) ->
false ->
{skip, "Not supported by " ++ atom_to_list(?RDBMS) ++ "driver"}
end;
-init_per_group(_, Config) ->
+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.
@@ -126,7 +135,7 @@ end_per_suite(_Config) ->
%% variable, but should NOT alter/remove any existing entries.
%%--------------------------------------------------------------------
init_per_testcase(_Case, Config) ->
- {ok, Ref} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, Ref} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
odbc_test_lib:strict(Ref, ?RDBMS),
Dog = test_server:timetrap(?default_timeout),
Temp = lists:keydelete(connection_ref, 1, Config),
@@ -146,7 +155,7 @@ end_per_testcase(_Case, Config) ->
ok = odbc:disconnect(Ref),
%% Clean up if needed
Table = ?config(tableName, Config),
- {ok, NewRef} = odbc:connect(?RDBMS:connection_string(), []),
+ {ok, NewRef} = odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()),
odbc:sql_query(NewRef, "DROP TABLE " ++ Table),
odbc:disconnect(NewRef),
Dog = ?config(watchdog, Config),
diff --git a/lib/odbc/test/odbc_start_SUITE.erl b/lib/odbc/test/odbc_start_SUITE.erl
index 65b990133f..440c0ca921 100644
--- a/lib/odbc/test/odbc_start_SUITE.erl
+++ b/lib/odbc/test/odbc_start_SUITE.erl
@@ -125,14 +125,16 @@ start(doc) ->
start(suite) ->
[];
start(Config) when is_list(Config) ->
- {error,odbc_not_started} = odbc:connect(?RDBMS:connection_string(), []),
+ PlatformOptions = odbc_test_lib:platform_options(),
+ {error,odbc_not_started} = odbc:connect(?RDBMS:connection_string(),
+ PlatformOptions),
odbc:start(),
- case odbc:connect(?RDBMS:connection_string(), []) of
+ case odbc:connect(?RDBMS:connection_string(), PlatformOptions) of
{ok, Ref0} ->
ok = odbc:disconnect(Ref0),
odbc:stop(),
{error,odbc_not_started} =
- odbc:connect(?RDBMS:connection_string(), []),
+ odbc:connect(?RDBMS:connection_string(), PlatformOptions),
start_odbc(transient),
start_odbc(permanent);
{error, odbc_not_started} ->
@@ -144,7 +146,7 @@ start(Config) when is_list(Config) ->
start_odbc(Type) ->
ok = odbc:start(Type),
- case odbc:connect(?RDBMS:connection_string(), []) of
+ case odbc:connect(?RDBMS:connection_string(), odbc_test_lib:platform_options()) of
{ok, Ref} ->
ok = odbc:disconnect(Ref),
odbc:stop();
diff --git a/lib/odbc/test/odbc_test.hrl b/lib/odbc/test/odbc_test.hrl
index 7d2522d667..397d04756b 100644
--- a/lib/odbc/test/odbc_test.hrl
+++ b/lib/odbc/test/odbc_test.hrl
@@ -27,7 +27,12 @@
{unix, sunos} ->
postgres;
{unix,linux} ->
- mysql;
+ case erlang:system_info(wordsize) of
+ 4 ->
+ mysql;
+ _ ->
+ postgres
+ end;
{win32, _} ->
sqlserver
end).
diff --git a/lib/odbc/test/odbc_test_lib.erl b/lib/odbc/test/odbc_test_lib.erl
index 9956d74d24..3e78105cf3 100644
--- a/lib/odbc/test/odbc_test_lib.erl
+++ b/lib/odbc/test/odbc_test_lib.erl
@@ -38,18 +38,7 @@ match_float(Float, Match, Delta) ->
odbc_check() ->
case erlang:system_info(wordsize) of
4 ->
- case test_server:os_type() of
- {unix, sunos} ->
- ok;
- {unix, linux} ->
- ok;
- {win32, _} ->
- ok;
- Other ->
- lists:flatten(
- io_lib:format("Platform not supported: ~w",
- [Other]))
- end;
+ ok;
Other ->
case os:type() of
{unix, linux} ->
@@ -80,3 +69,11 @@ strict(Ref, mysql) ->
odbc:sql_query(Ref, "SET sql_mode='STRICT_ALL_TABLES,STRICT_TRANS_TABLES';");
strict(_,_) ->
ok.
+
+platform_options() ->
+ case os:type() of
+ {unix, sunos} ->
+ [{scrollable_cursors, off}];
+ _ ->
+ []
+ end.
diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk
index 9d4ed17774..2f0ecd3863 100644
--- a/lib/stdlib/vsn.mk
+++ b/lib/stdlib/vsn.mk
@@ -1 +1 @@
-STDLIB_VSN = 1.17.5
+STDLIB_VSN = 1.18