ruby-oci8 2.2.5.1 → 2.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog +68 -0
- data/NEWS +39 -0
- data/README.md +1 -1
- data/dist-files +1 -0
- data/docs/install-on-osx.md +1 -1
- data/ext/oci8/apiwrap.rb +6 -1
- data/ext/oci8/apiwrap.yml +14 -0
- data/ext/oci8/hook_funcs.c +87 -57
- data/ext/oci8/lob.c +7 -43
- data/ext/oci8/object.c +30 -0
- data/ext/oci8/oci8.c +13 -4
- data/ext/oci8/oci8.h +20 -3
- data/ext/oci8/oci8lib.c +2 -0
- data/ext/oci8/win32.c +0 -20
- data/lib/oci8.rb +2 -0
- data/lib/oci8/metadata.rb +9 -1
- data/lib/oci8/object.rb +10 -0
- data/lib/oci8/oci8.rb +6 -0
- data/lib/oci8/oracle_version.rb +11 -1
- data/lib/oci8/version.rb +1 -1
- data/lib/ruby-oci8.rb +0 -3
- data/test/setup_test_object.sql +21 -13
- data/test/test_all.rb +1 -0
- data/test/test_clob.rb +3 -16
- data/test/test_object.rb +33 -9
- data/test/test_oci8.rb +15 -1
- data/test/test_package_type.rb +15 -3
- data/test/test_properties.rb +17 -0
- metadata +27 -42
data/ChangeLog
CHANGED
@@ -1,3 +1,71 @@
|
|
1
|
+
2018-08-22 Kubo Takehiro <kubo@jiubao.org>
|
2
|
+
* NEWS: Add changes between 2.2.5.1 and 2.2.6
|
3
|
+
* lib/oci8/version.rb: Update to 2.2.6
|
4
|
+
* mkpkg-win32.rb: Don't test with self-build ruby 2.4.
|
5
|
+
|
6
|
+
2018-08-22 Kubo Takehiro <kubo@jiubao.org>
|
7
|
+
* ext/oci8/oci8lib.c: Load a Oracle client library which doesn't have
|
8
|
+
version number suffix also on Unix when runtime-check is enabled.
|
9
|
+
Oracle version numbers are incremented yearly sice Oracle 18c.
|
10
|
+
|
11
|
+
2018-08-22 Kubo Takehiro <kubo@jiubao.org>
|
12
|
+
* ext/oci8/hook_funcs.c, ext/oci8/win32.c: Suppress warnings:
|
13
|
+
"'raise_error' defined but not used" and "'strncpy' specified
|
14
|
+
bound 512 equals destination size".
|
15
|
+
|
16
|
+
2018-08-19 Kubo Takehiro <kubo@jiubao.org>
|
17
|
+
* ext/oci8/hook_funcs.c: Not depend on Oracle version number
|
18
|
+
of Oracle client file name suffix when hooking functions.
|
19
|
+
(rsim/oracle-enhanced#1754)
|
20
|
+
* test/test_all.rb, test/test_properties.rb, dist-files:
|
21
|
+
Add tests for hooking.
|
22
|
+
|
23
|
+
2018-08-18 Kubo Takehiro <kubo@jiubao.org>
|
24
|
+
* test/test_oci8.rb: Fix to pass a test when the client is 11g
|
25
|
+
and the server is 18c. client_driver in v$session_connect_info
|
26
|
+
has an extra space at the end.
|
27
|
+
|
28
|
+
2018-08-18 Kubo Takehiro <kubo@jiubao.org>
|
29
|
+
* ext/oci8/apiwrap.rb, ext/oci8/apiwrap.yml, ext/oci8/oci8.c,
|
30
|
+
ext/oci8/oci8.h, lib/oci8/oci8.rb, lib/oci8/oracle_version.rb,
|
31
|
+
test/test_oci8.rb: Fix OCI8#oracle_server_version to get
|
32
|
+
full version of Oracle 18c.
|
33
|
+
|
34
|
+
2018-08-18 Kubo Takehiro <kubo@jiubao.org>
|
35
|
+
* lib/oci8/metadata.rb: Update doc comments of OCI8::Metadata::ArgBase#level
|
36
|
+
and OCI8::Metadata::ArgBase#arguments.
|
37
|
+
* test/test_package_type.rb, lib/oci8.rb: Fix to pass tests on Oracle 18c.
|
38
|
+
Detailed user-defined type information used in arguments isn't available
|
39
|
+
on Oracle 18c.
|
40
|
+
|
41
|
+
2018-08-12 Kubo Takehiro <kubo@jiubao.org>
|
42
|
+
* test/test_clob.rb: Skip TestCLob#test_github_issue_20 because it
|
43
|
+
takes 4 minutes to test it in my Linux box.
|
44
|
+
|
45
|
+
2018-08-12 Kubo Takehiro <kubo@jiubao.org>
|
46
|
+
* ext/oci8/lob.c, test/test_clob.rb: LOB#sync, LOB#sync= and LOB#flush
|
47
|
+
do nothing now. They have not worked by mistake from the beginning
|
48
|
+
because incorrect arguments has been passed to OCILobOpen().
|
49
|
+
Moreover it crashed Oracle 18c server-side processes and caused
|
50
|
+
"ORA-03113: end-of-file on communication channel."
|
51
|
+
(github issue #198)
|
52
|
+
|
53
|
+
2018-01-28 Kubo Takehiro <kubo@jiubao.org>
|
54
|
+
* ext/oci8/object.c, lib/oci8/object.rb: Add timestamp with time zone
|
55
|
+
data type support in object type attributes.
|
56
|
+
(github issue #185)
|
57
|
+
* test/setup_test_object.sql, test/test_object.rb: Add tests for
|
58
|
+
timestamp and timestamp with time zone.
|
59
|
+
|
60
|
+
2018-01-23 Kubo Takehiro <kubo@jiubao.org>
|
61
|
+
* ext/oci8/object.c, ext/oci8/oci8.h, lib/oci8/object.rb:
|
62
|
+
Add timestamp data type support in object type attributes.
|
63
|
+
(github issue #185)
|
64
|
+
|
65
|
+
2017-12-27 Kubo Takehiro <kubo@jiubao.org>
|
66
|
+
* mkpkg-win32.rb: Remove '-rubygems' in the command line to run tests.
|
67
|
+
`ubygems.rb` was removed in ruby 2.5.
|
68
|
+
|
1
69
|
2017-12-27 Kubo Takehiro <kubo@jiubao.org>
|
2
70
|
* NEWS: Add changes between 2.2.5 and 2.2.5.1
|
3
71
|
* lib/oci8/version.rb: Update to 2.2.5.1
|
data/NEWS
CHANGED
@@ -1,5 +1,44 @@
|
|
1
1
|
# @markup markdown
|
2
2
|
|
3
|
+
2.2.6
|
4
|
+
=====
|
5
|
+
|
6
|
+
This release fixed issues about Oracle 18c except one.
|
7
|
+
|
8
|
+
Fixed issue
|
9
|
+
-----------
|
10
|
+
|
11
|
+
### Setting some properties failed with Oracle 18c client
|
12
|
+
|
13
|
+
Setting `OCI8::properties[:tcp_keepalive_time]` or `OCI8::properties[:cancel_read_at_exit]`
|
14
|
+
failed with the error message "No shared library is found to hook" when Oracle
|
15
|
+
client version is 18c.
|
16
|
+
(rsim/oracle-enhanced#1754)
|
17
|
+
|
18
|
+
### Fix `OCI8#oracle_server_version` to get full version of Oracle 18c
|
19
|
+
|
20
|
+
`OCI8#oracle_server_version` returned Oracle version number whose
|
21
|
+
number components after the first dot are zeros such as '18.0.0.0.0'
|
22
|
+
even when the server version is `18.3.0.0.0`. This issue was fixed by
|
23
|
+
using a new OCI function. However the function is available since
|
24
|
+
Oracle 18c client. So when the Oracle client version is 12c or earlier
|
25
|
+
and the Oracle server version is 18c or later, it cannot get the *full*
|
26
|
+
Oracle version number.
|
27
|
+
|
28
|
+
### Fix tests when the Oracle server version is 18c.
|
29
|
+
|
30
|
+
### LOB#sync, LOB#sync= and LOB#flush do nothing now.
|
31
|
+
|
32
|
+
They have not worked by mistake from the beginning because incorrect
|
33
|
+
arguments has been passed to OCILobOpen(). Moreover it crashed Oracle
|
34
|
+
18c server-side processes and caused "ORA-03113: end-of-file on
|
35
|
+
communication channel."
|
36
|
+
(github issue #198)
|
37
|
+
|
38
|
+
### `unsupported typecode timestamp` when timestamp with time zone is in object type attributes.
|
39
|
+
|
40
|
+
(github issue #185)
|
41
|
+
|
3
42
|
2.2.5.1
|
4
43
|
=======
|
5
44
|
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@ Ruby-oci8
|
|
2
2
|
=========
|
3
3
|
|
4
4
|
[](http://badge.fury.io/rb/ruby-oci8)
|
5
|
-
[](https://travis-ci.org/kubo/ruby-oci8)
|
6
6
|
|
7
7
|
What is ruby-oci8
|
8
8
|
-----------------
|
data/dist-files
CHANGED
data/docs/install-on-osx.md
CHANGED
@@ -39,7 +39,7 @@ Download the following packages from [Oracle Technology Network][]
|
|
39
39
|
|
40
40
|
* Instant Client Package - Basic (`instantclient-basic-macos.x64-12.1.0.2.0.zip`) or Basic Lite (`instantclient-basiclite-macos.x64-12.1.0.2.0.zip`)
|
41
41
|
* Instant Client Package - SDK (`instantclient-sdk-macos.x64-12.1.0.2.0.zip`)
|
42
|
-
* Instant Client Package - SQL*Plus (`instantclient-
|
42
|
+
* Instant Client Package - SQL*Plus (`instantclient-sqlplus-macos.x64-12.1.0.2.0.zip`) (optionally)
|
43
43
|
|
44
44
|
### Install Oracle Instant Client Packages via Homebrew
|
45
45
|
|
data/ext/oci8/apiwrap.rb
CHANGED
@@ -35,7 +35,11 @@ class FuncDef
|
|
35
35
|
ver_major = (ver / 100)
|
36
36
|
ver_minor = (ver / 10) % 10
|
37
37
|
ver_update = ver % 10
|
38
|
-
@version =
|
38
|
+
@version = if ver_major >= 18
|
39
|
+
((ver_major << 24) | (ver_minor << 16) | (ver_update << 12))
|
40
|
+
else
|
41
|
+
((ver_major << 24) | (ver_minor << 20) | (ver_update << 12))
|
42
|
+
end
|
39
43
|
case @version
|
40
44
|
when 0x08000000; @version_num = 'ORAVER_8_0'
|
41
45
|
when 0x08100000; @version_num = 'ORAVER_8_1'
|
@@ -44,6 +48,7 @@ class FuncDef
|
|
44
48
|
when 0x0a100000; @version_num = 'ORAVER_10_1'
|
45
49
|
when 0x0a200000; @version_num = 'ORAVER_10_2'
|
46
50
|
when 0x0b100000; @version_num = 'ORAVER_11_1'
|
51
|
+
when 0x12000000; @version_num = 'ORAVER_18'
|
47
52
|
end
|
48
53
|
@version_str = "#{ver_major}.#{ver_minor}.#{ver_update}"
|
49
54
|
@ret = val[:ret] || 'sword'
|
data/ext/oci8/apiwrap.yml
CHANGED
@@ -1286,3 +1286,17 @@ OCIPing_nb:
|
|
1286
1286
|
- OCISvcCtx *svchp
|
1287
1287
|
- OCIError *errhp
|
1288
1288
|
- ub4 mode
|
1289
|
+
|
1290
|
+
#
|
1291
|
+
# Oracle 18.1
|
1292
|
+
#
|
1293
|
+
OCIServerRelease2:
|
1294
|
+
:version: 1800
|
1295
|
+
:args:
|
1296
|
+
- dvoid *hndlp
|
1297
|
+
- OCIError *errhp
|
1298
|
+
- OraText *bufp
|
1299
|
+
- ub4 bufsz
|
1300
|
+
- ub1 hndltype
|
1301
|
+
- ub4 *version
|
1302
|
+
- ub4 mode
|
data/ext/oci8/hook_funcs.c
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
/*
|
3
3
|
* hook.c
|
4
4
|
*
|
5
|
-
* Copyright (C) 2015 Kubo Takehiro <kubo@jiubao.org>
|
5
|
+
* Copyright (C) 2015-2018 Kubo Takehiro <kubo@jiubao.org>
|
6
6
|
*/
|
7
7
|
#if defined(_WIN32) || defined(__CYGWIN__)
|
8
8
|
#define WINDOWS
|
@@ -12,15 +12,19 @@
|
|
12
12
|
#include "plthook.h"
|
13
13
|
#ifdef __CYGWIN__
|
14
14
|
#undef boolean /* boolean defined in oratypes.h coflicts with that in windows.h */
|
15
|
+
#define stricmp strcasecmp
|
16
|
+
#define strnicmp strncasecmp
|
15
17
|
#endif
|
16
18
|
#ifdef WINDOWS
|
17
19
|
#include <windows.h>
|
18
20
|
#include <mstcpip.h>
|
21
|
+
#include <tlhelp32.h>
|
19
22
|
#else
|
20
23
|
#include <unistd.h>
|
21
24
|
#include <sys/socket.h>
|
22
25
|
#include <netinet/in.h>
|
23
26
|
#include <netinet/tcp.h>
|
27
|
+
#include <dlfcn.h>
|
24
28
|
#endif
|
25
29
|
|
26
30
|
#ifdef WINDOWS
|
@@ -59,6 +63,7 @@ static int WSAAPI hook_setsockopt(SOCKET sockfd, int level, int optname, const v
|
|
59
63
|
int oci8_tcp_keepalive_time = -1;
|
60
64
|
#endif
|
61
65
|
|
66
|
+
static char hook_errmsg[512];
|
62
67
|
|
63
68
|
typedef struct {
|
64
69
|
const char *func_name;
|
@@ -95,35 +100,35 @@ static void socket_entry_clear(socket_entry_t *entry)
|
|
95
100
|
UNLOCK(&lock);
|
96
101
|
}
|
97
102
|
|
98
|
-
static int replace_functions(
|
103
|
+
static int replace_functions(void *addr, const char *file, hook_func_entry_t *functions)
|
99
104
|
{
|
105
|
+
plthook_t *ph;
|
100
106
|
int i;
|
107
|
+
int rv = 0;
|
101
108
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
plthook_close(ph);
|
119
|
-
rb_raise(rb_eRuntimeError, "Could not replace function %s in %s", function->func_name, file);
|
120
|
-
}
|
109
|
+
if (plthook_open_by_address(&ph, addr) != 0) {
|
110
|
+
strncpy(hook_errmsg, plthook_error(), sizeof(hook_errmsg) - 1);
|
111
|
+
hook_errmsg[sizeof(hook_errmsg) - 1] = '\0';
|
112
|
+
return -1;
|
113
|
+
}
|
114
|
+
|
115
|
+
/* install hooks */
|
116
|
+
for (i = 0; functions[i].func_name != NULL ; i++) {
|
117
|
+
hook_func_entry_t *function = &functions[i];
|
118
|
+
rv = plthook_replace(ph, function->func_name, function->func_addr, &function->old_func_addr);
|
119
|
+
if (rv != 0) {
|
120
|
+
strncpy(hook_errmsg, plthook_error(), sizeof(hook_errmsg) - 1);
|
121
|
+
hook_errmsg[sizeof(hook_errmsg) - 1] = '\0';
|
122
|
+
while (--i >= 0) {
|
123
|
+
/*restore hooked fuction address */
|
124
|
+
plthook_replace(ph, functions[i].func_name, functions[i].old_func_addr, NULL);
|
121
125
|
}
|
122
|
-
|
123
|
-
|
126
|
+
snprintf(hook_errmsg, sizeof(hook_errmsg), "Could not replace function %s in %s", function->func_name, file);
|
127
|
+
break;
|
124
128
|
}
|
125
129
|
}
|
126
|
-
|
130
|
+
plthook_close(ph);
|
131
|
+
return rv;
|
127
132
|
}
|
128
133
|
|
129
134
|
#ifdef WINDOWS
|
@@ -142,23 +147,6 @@ static int locK_is_initialized;
|
|
142
147
|
|
143
148
|
static int WSAAPI hook_WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
|
144
149
|
|
145
|
-
static const char * const tcp_func_files[] = {
|
146
|
-
/* full client */
|
147
|
-
"orantcp12.dll",
|
148
|
-
"orantcp11.dll",
|
149
|
-
"orantcp10.dll",
|
150
|
-
"orantcp9.dll",
|
151
|
-
/* instant client basic */
|
152
|
-
"oraociei12.dll",
|
153
|
-
"oraociei11.dll",
|
154
|
-
"oraociei10.dll",
|
155
|
-
/* instant client basic lite */
|
156
|
-
"oraociicus12.dll",
|
157
|
-
"oraociicus11.dll",
|
158
|
-
"oraociicus10.dll",
|
159
|
-
NULL,
|
160
|
-
};
|
161
|
-
|
162
150
|
static hook_func_entry_t tcp_functions[] = {
|
163
151
|
{"WSARecv", (void*)hook_WSARecv, NULL},
|
164
152
|
{"setsockopt", (void*)hook_setsockopt, NULL},
|
@@ -190,6 +178,9 @@ void oci8_install_hook_functions()
|
|
190
178
|
DWORD data;
|
191
179
|
DWORD cbData = sizeof(data);
|
192
180
|
const char *reg_key = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters";
|
181
|
+
HANDLE hSnapshot;
|
182
|
+
MODULEENTRY32 me;
|
183
|
+
BOOL module_found = FALSE;
|
193
184
|
|
194
185
|
if (hook_functions_installed) {
|
195
186
|
return;
|
@@ -222,7 +213,32 @@ void oci8_install_hook_functions()
|
|
222
213
|
}
|
223
214
|
RegCloseKey(hKey);
|
224
215
|
|
225
|
-
|
216
|
+
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
|
217
|
+
me.dwSize = sizeof(me);
|
218
|
+
if (Module32First(hSnapshot, &me)) {
|
219
|
+
do {
|
220
|
+
const char *p = NULL;
|
221
|
+
if (strnicmp(me.szModule, "orantcp", 7) == 0) { // ORACLE_HOME-based client
|
222
|
+
p = me.szModule + 7;
|
223
|
+
} else if (strnicmp(me.szModule, "oraociei", 8) == 0) { // instant client basic
|
224
|
+
p = me.szModule + 8;
|
225
|
+
} else if (strnicmp(me.szModule, "oraociicus", 10) == 0) { // instant client basic lite
|
226
|
+
p = me.szModule + 10;
|
227
|
+
}
|
228
|
+
if (p != NULL && ('1' <= *p && *p <= '9') && ('0' <= *(p + 1) && *(p + 1) <= '9')
|
229
|
+
&& stricmp(p + 2, ".dll") == 0) {
|
230
|
+
if (GetProcAddress((HMODULE)me.modBaseAddr, "nttini") != NULL) {
|
231
|
+
module_found = TRUE;
|
232
|
+
if (replace_functions(me.modBaseAddr, me.szExePath, tcp_functions) != 0) {
|
233
|
+
CloseHandle(hSnapshot);
|
234
|
+
rb_raise(rb_eRuntimeError, "Hook error: %s", hook_errmsg);
|
235
|
+
}
|
236
|
+
}
|
237
|
+
}
|
238
|
+
} while (Module32Next(hSnapshot, &me));
|
239
|
+
}
|
240
|
+
CloseHandle(hSnapshot);
|
241
|
+
if (!module_found) {
|
226
242
|
rb_raise(rb_eRuntimeError, "No DLL is found to hook.");
|
227
243
|
}
|
228
244
|
hook_functions_installed = 1;
|
@@ -241,20 +257,6 @@ static void shutdown_socket(socket_entry_t *entry)
|
|
241
257
|
#else
|
242
258
|
static ssize_t hook_read(int fd, void *buf, size_t count);
|
243
259
|
|
244
|
-
#ifdef __APPLE__
|
245
|
-
#define SO_EXT "dylib"
|
246
|
-
#else
|
247
|
-
#define SO_EXT "so"
|
248
|
-
#endif
|
249
|
-
|
250
|
-
static const char * const files[] = {
|
251
|
-
"libclntsh." SO_EXT ".12.1",
|
252
|
-
"libclntsh." SO_EXT ".11.1",
|
253
|
-
"libclntsh." SO_EXT ".10.1",
|
254
|
-
"libclntsh." SO_EXT ".9.0",
|
255
|
-
NULL,
|
256
|
-
};
|
257
|
-
|
258
260
|
static hook_func_entry_t functions[] = {
|
259
261
|
{"read", (void*)hook_read, NULL},
|
260
262
|
#ifdef SUPPORT_TCP_KEEPALIVE_TIME
|
@@ -279,16 +281,44 @@ static ssize_t hook_read(int fd, void *buf, size_t count)
|
|
279
281
|
return rv;
|
280
282
|
}
|
281
283
|
|
284
|
+
static void *ocifunc_addr(void *dlsym_handle, const char **file)
|
285
|
+
{
|
286
|
+
void *addr = dlsym(dlsym_handle, "OCIEnvCreate");
|
287
|
+
Dl_info dli;
|
288
|
+
|
289
|
+
if (addr == NULL) {
|
290
|
+
return NULL;
|
291
|
+
}
|
292
|
+
if (dladdr(addr, &dli) == 0) {
|
293
|
+
return NULL;
|
294
|
+
}
|
295
|
+
if (strstr(dli.dli_fname, "/libclntsh.so") == 0) {
|
296
|
+
return NULL;
|
297
|
+
}
|
298
|
+
*file = dli.dli_fname;
|
299
|
+
return addr;
|
300
|
+
}
|
301
|
+
|
282
302
|
void oci8_install_hook_functions(void)
|
283
303
|
{
|
284
304
|
static int hook_functions_installed = 0;
|
305
|
+
void *addr;
|
306
|
+
const char *file;
|
285
307
|
|
286
308
|
if (hook_functions_installed) {
|
287
309
|
return;
|
288
310
|
}
|
289
|
-
|
311
|
+
addr = ocifunc_addr(RTLD_DEFAULT, &file);
|
312
|
+
if (addr == NULL) {
|
313
|
+
/* OCI symbols may be hooked by LD_PRELOAD. */
|
314
|
+
addr = ocifunc_addr(RTLD_NEXT, &file);
|
315
|
+
}
|
316
|
+
if (addr == NULL) {
|
290
317
|
rb_raise(rb_eRuntimeError, "No shared library is found to hook.");
|
291
318
|
}
|
319
|
+
if (replace_functions(addr, file, functions) != 0) {
|
320
|
+
rb_raise(rb_eRuntimeError, "Hook error: %s", hook_errmsg);
|
321
|
+
}
|
292
322
|
hook_functions_installed = 1;
|
293
323
|
}
|
294
324
|
|
data/ext/oci8/lob.c
CHANGED
@@ -26,8 +26,6 @@ static VALUE seek_end;
|
|
26
26
|
|
27
27
|
enum state {
|
28
28
|
S_NO_OPEN_CLOSE,
|
29
|
-
S_OPEN,
|
30
|
-
S_CLOSE,
|
31
29
|
S_BFILE_CLOSE,
|
32
30
|
S_BFILE_OPEN,
|
33
31
|
};
|
@@ -266,28 +264,6 @@ static ub8 oci8_lob_get_length(oci8_lob_t *lob)
|
|
266
264
|
return len;
|
267
265
|
}
|
268
266
|
|
269
|
-
static void lob_open(oci8_lob_t *lob)
|
270
|
-
{
|
271
|
-
if (lob->state == S_CLOSE) {
|
272
|
-
oci8_svcctx_t *svcctx = check_svcctx(lob);
|
273
|
-
|
274
|
-
chker2(OCILobOpen_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, OCI_DEFAULT),
|
275
|
-
&svcctx->base);
|
276
|
-
lob->state = S_OPEN;
|
277
|
-
}
|
278
|
-
}
|
279
|
-
|
280
|
-
static void lob_close(oci8_lob_t *lob)
|
281
|
-
{
|
282
|
-
if (lob->state == S_OPEN) {
|
283
|
-
oci8_svcctx_t *svcctx = check_svcctx(lob);
|
284
|
-
|
285
|
-
chker2(OCILobClose_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob),
|
286
|
-
&svcctx->base);
|
287
|
-
lob->state = S_CLOSE;
|
288
|
-
}
|
289
|
-
}
|
290
|
-
|
291
267
|
static void bfile_close(oci8_lob_t *lob)
|
292
268
|
{
|
293
269
|
if (lob->state == S_BFILE_OPEN) {
|
@@ -368,7 +344,6 @@ static void bfile_close(oci8_lob_t *lob)
|
|
368
344
|
static VALUE oci8_lob_close(VALUE self)
|
369
345
|
{
|
370
346
|
oci8_lob_t *lob = TO_LOB(self);
|
371
|
-
lob_close(lob);
|
372
347
|
oci8_base_free(&lob->base);
|
373
348
|
return self;
|
374
349
|
}
|
@@ -591,7 +566,6 @@ static VALUE oci8_lob_truncate(VALUE self, VALUE len)
|
|
591
566
|
oci8_lob_t *lob = TO_LOB(self);
|
592
567
|
oci8_svcctx_t *svcctx = check_svcctx(lob);
|
593
568
|
|
594
|
-
lob_open(lob);
|
595
569
|
chker2(OCILobTrim2_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, NUM2ULL(len)),
|
596
570
|
&svcctx->base);
|
597
571
|
return self;
|
@@ -740,7 +714,6 @@ static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
|
|
740
714
|
} while (rv == OCI_NEED_DATA);
|
741
715
|
|
742
716
|
if (pos >= lob_length) {
|
743
|
-
lob_close(lob);
|
744
717
|
bfile_close(lob);
|
745
718
|
}
|
746
719
|
lob->pos = pos;
|
@@ -781,7 +754,6 @@ static VALUE oci8_lob_write(VALUE self, VALUE data)
|
|
781
754
|
ub8 byte_amt;
|
782
755
|
ub8 char_amt;
|
783
756
|
|
784
|
-
lob_open(lob);
|
785
757
|
if (TYPE(data) != T_STRING) {
|
786
758
|
str = rb_obj_as_string(data);
|
787
759
|
} else {
|
@@ -809,40 +781,32 @@ static VALUE oci8_lob_write(VALUE self, VALUE data)
|
|
809
781
|
}
|
810
782
|
|
811
783
|
/*
|
812
|
-
* @deprecated
|
784
|
+
* @deprecated LOB#sync had not worked by mistake. Do nothing now.
|
813
785
|
* @private
|
814
786
|
*/
|
815
787
|
static VALUE oci8_lob_get_sync(VALUE self)
|
816
788
|
{
|
817
|
-
|
818
|
-
return
|
789
|
+
rb_warning("LOB#sync had not worked by mistake. Do nothing now.");
|
790
|
+
return Qfalse;
|
819
791
|
}
|
820
792
|
|
821
793
|
/*
|
822
|
-
* @deprecated
|
794
|
+
* @deprecated LOB#sync had not worked by mistake. Do nothing now.
|
823
795
|
* @private
|
824
796
|
*/
|
825
797
|
static VALUE oci8_lob_set_sync(VALUE self, VALUE b)
|
826
798
|
{
|
827
|
-
|
828
|
-
if (RTEST(b)) {
|
829
|
-
lob_close(lob);
|
830
|
-
lob->state = S_NO_OPEN_CLOSE;
|
831
|
-
} else {
|
832
|
-
if (lob->state == S_NO_OPEN_CLOSE)
|
833
|
-
lob->state = S_CLOSE;
|
834
|
-
}
|
799
|
+
rb_warning("LOB#sync had not worked by mistake. Do nothing now.");
|
835
800
|
return b;
|
836
801
|
}
|
837
802
|
|
838
803
|
/*
|
839
|
-
* @deprecated
|
804
|
+
* @deprecated LOB#flush had not worked by mistake. Do nothing now.
|
840
805
|
* @private
|
841
806
|
*/
|
842
807
|
static VALUE oci8_lob_flush(VALUE self)
|
843
808
|
{
|
844
|
-
|
845
|
-
lob_close(lob);
|
809
|
+
rb_warning("LOB#flush had not worked by mistake. Do nothing now.");
|
846
810
|
return self;
|
847
811
|
}
|
848
812
|
|
data/ext/oci8/object.c
CHANGED
@@ -44,6 +44,8 @@ enum {
|
|
44
44
|
ATTR_FLOAT,
|
45
45
|
ATTR_INTEGER,
|
46
46
|
ATTR_OCIDATE,
|
47
|
+
ATTR_TIMESTAMP,
|
48
|
+
ATTR_TIMESTAMP_TZ,
|
47
49
|
ATTR_BINARY_DOUBLE,
|
48
50
|
ATTR_BINARY_FLOAT,
|
49
51
|
ATTR_NAMED_TYPE,
|
@@ -235,6 +237,10 @@ static VALUE get_attribute(VALUE self, VALUE datatype, VALUE typeinfo, void *dat
|
|
235
237
|
return oci8_make_integer((OCINumber *)data, oci8_errhp);
|
236
238
|
case ATTR_OCIDATE:
|
237
239
|
return oci8_make_ocidate((OCIDate *)data);
|
240
|
+
case ATTR_TIMESTAMP:
|
241
|
+
return oci8_make_ocitimestamp(*(OCIDateTime**)data, FALSE);
|
242
|
+
case ATTR_TIMESTAMP_TZ:
|
243
|
+
return oci8_make_ocitimestamp(*(OCIDateTime**)data, TRUE);
|
238
244
|
case ATTR_BINARY_DOUBLE:
|
239
245
|
return rb_float_new(*(double*)data);
|
240
246
|
case ATTR_BINARY_FLOAT:
|
@@ -413,6 +419,18 @@ static VALUE oci8_named_coll_set_coll_element(VALUE self, VALUE datatype, VALUE
|
|
413
419
|
case ATTR_OCIDATE:
|
414
420
|
cb_data.indp = &cb_data.ind;
|
415
421
|
break;
|
422
|
+
case ATTR_TIMESTAMP:
|
423
|
+
chker2(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->hp.svc, OCI_TYPECODE_TIMESTAMP, NULL, NULL, OCI_DURATION_SESSION, TRUE, &cb_data.data.ptr),
|
424
|
+
svcctx);
|
425
|
+
chker2(OCIObjectGetInd(oci8_envhp, oci8_errhp, cb_data.data.ptr, (dvoid**)&cb_data.indp),
|
426
|
+
svcctx);
|
427
|
+
break;
|
428
|
+
case ATTR_TIMESTAMP_TZ:
|
429
|
+
chker2(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->hp.svc, OCI_TYPECODE_TIMESTAMP_TZ, NULL, NULL, OCI_DURATION_SESSION, TRUE, &cb_data.data.ptr),
|
430
|
+
svcctx);
|
431
|
+
chker2(OCIObjectGetInd(oci8_envhp, oci8_errhp, cb_data.data.ptr, (dvoid**)&cb_data.indp),
|
432
|
+
svcctx);
|
433
|
+
break;
|
416
434
|
case ATTR_BINARY_DOUBLE:
|
417
435
|
cb_data.data.dbl = 0.0;
|
418
436
|
cb_data.indp = &cb_data.ind;
|
@@ -507,6 +525,8 @@ static VALUE set_coll_element_ensure(set_coll_element_cb_data_t *cb_data)
|
|
507
525
|
switch (FIX2INT(datatype)) {
|
508
526
|
case ATTR_STRING:
|
509
527
|
case ATTR_RAW:
|
528
|
+
case ATTR_TIMESTAMP:
|
529
|
+
case ATTR_TIMESTAMP_TZ:
|
510
530
|
case ATTR_NAMED_TYPE:
|
511
531
|
case ATTR_NAMED_COLLECTION:
|
512
532
|
if (cb_data->data.ptr != NULL) {
|
@@ -558,6 +578,12 @@ static void set_attribute(VALUE self, VALUE datatype, VALUE typeinfo, void *data
|
|
558
578
|
case ATTR_OCIDATE:
|
559
579
|
oci8_set_ocidate((OCIDate*)data, val);
|
560
580
|
break;
|
581
|
+
case ATTR_TIMESTAMP:
|
582
|
+
oci8_set_ocitimestamp_tz(*(OCIDateTime **)data, val, Qnil);
|
583
|
+
break;
|
584
|
+
case ATTR_TIMESTAMP_TZ:
|
585
|
+
oci8_set_ocitimestamp_tz(*(OCIDateTime **)data, val, Qnil);
|
586
|
+
break;
|
561
587
|
case ATTR_BINARY_DOUBLE:
|
562
588
|
*(double*)data = NUM2DBL(val);
|
563
589
|
break;
|
@@ -818,6 +844,10 @@ void Init_oci_object(VALUE cOCI8)
|
|
818
844
|
/* @private */
|
819
845
|
rb_define_const(cOCI8TDO, "ATTR_OCIDATE", INT2FIX(ATTR_OCIDATE));
|
820
846
|
/* @private */
|
847
|
+
rb_define_const(cOCI8TDO, "ATTR_TIMESTAMP", INT2FIX(ATTR_TIMESTAMP));
|
848
|
+
/* @private */
|
849
|
+
rb_define_const(cOCI8TDO, "ATTR_TIMESTAMP_TZ", INT2FIX(ATTR_TIMESTAMP_TZ));
|
850
|
+
/* @private */
|
821
851
|
rb_define_const(cOCI8TDO, "ATTR_BINARY_DOUBLE", INT2FIX(ATTR_BINARY_DOUBLE));
|
822
852
|
/* @private */
|
823
853
|
rb_define_const(cOCI8TDO, "ATTR_BINARY_FLOAT", INT2FIX(ATTR_BINARY_FLOAT));
|
data/ext/oci8/oci8.c
CHANGED
@@ -582,6 +582,8 @@ static VALUE oci8_server_attach(VALUE self, VALUE dbname, VALUE attach_mode)
|
|
582
582
|
static VALUE oci8_session_begin(VALUE self, VALUE cred, VALUE mode)
|
583
583
|
{
|
584
584
|
oci8_svcctx_t *svcctx = oci8_get_svcctx(self);
|
585
|
+
char buf[100];
|
586
|
+
ub4 version;
|
585
587
|
|
586
588
|
if (svcctx->logoff_strategy != &complex_logoff) {
|
587
589
|
rb_raise(rb_eRuntimeError, "Use this method only for the service context handle created by OCI8#server_handle().");
|
@@ -604,6 +606,16 @@ static VALUE oci8_session_begin(VALUE self, VALUE cred, VALUE mode)
|
|
604
606
|
oci8_errhp),
|
605
607
|
&svcctx->base);
|
606
608
|
svcctx->state |= OCI8_STATE_SESSION_BEGIN_WAS_CALLED;
|
609
|
+
if (have_OCIServerRelease2) {
|
610
|
+
chker2(OCIServerRelease2(svcctx->base.hp.ptr, oci8_errhp, (text*)buf,
|
611
|
+
sizeof(buf), (ub1)svcctx->base.type, &version, OCI_DEFAULT),
|
612
|
+
&svcctx->base);
|
613
|
+
} else {
|
614
|
+
chker2(OCIServerRelease(svcctx->base.hp.ptr, oci8_errhp, (text*)buf,
|
615
|
+
sizeof(buf), (ub1)svcctx->base.type, &version),
|
616
|
+
&svcctx->base);
|
617
|
+
}
|
618
|
+
svcctx->server_version = version;
|
607
619
|
return Qnil;
|
608
620
|
}
|
609
621
|
|
@@ -796,11 +808,8 @@ static VALUE oci8_break(VALUE self)
|
|
796
808
|
static VALUE oci8_oracle_server_vernum(VALUE self)
|
797
809
|
{
|
798
810
|
oci8_svcctx_t *svcctx = oci8_get_svcctx(self);
|
799
|
-
char buf[100];
|
800
|
-
ub4 version;
|
801
811
|
|
802
|
-
|
803
|
-
return UINT2NUM(version);
|
812
|
+
return UINT2NUM(svcctx->server_version);
|
804
813
|
}
|
805
814
|
|
806
815
|
/*
|
data/ext/oci8/oci8.h
CHANGED
@@ -21,8 +21,23 @@ extern "C"
|
|
21
21
|
}
|
22
22
|
#endif
|
23
23
|
|
24
|
+
/*
|
25
|
+
* Oracle version number format in 32-bit integer.
|
26
|
+
*
|
27
|
+
* Oracle 12c or earier Oracle 18c or later
|
28
|
+
*
|
29
|
+
* hexadecimal -> dotted version number hexadecimal -> dotted version number
|
30
|
+
* 0c102304 -> 12.1.2.3.4 12012034 -> 18.1.2.3.4
|
31
|
+
* ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
|
32
|
+
* 0c ------------' | | | | 2 bytes 12 ------------' | | | | 2 bytes
|
33
|
+
* 1 --------------' | | | 1 byte 01 -------------' | | | 2 bytes
|
34
|
+
* 02 --------------' | | 2 bytes 2 --------------' | | 1 byte
|
35
|
+
* 3 ---------------' | 1 byte 03 --------------' | 2 bytes
|
36
|
+
* 04 ---------------' 2 bytes 4 ---------------' 1 byte
|
37
|
+
*/
|
24
38
|
#define ORAVERNUM(major, minor, update, patch, port_update) \
|
25
|
-
(((major) << 24) | ((minor) <<
|
39
|
+
(((major) >= 18) ? (((major) << 24) | ((minor) << 16) | ((update) << 12) | ((patch) << 4) | (port_update)) \
|
40
|
+
: (((major) << 24) | ((minor) << 20) | ((update) << 12) | ((patch) << 8) | (port_update)))
|
26
41
|
|
27
42
|
#define ORAVER_8_0 ORAVERNUM(8, 0, 0, 0, 0)
|
28
43
|
#define ORAVER_8_1 ORAVERNUM(8, 1, 0, 0, 0)
|
@@ -32,6 +47,7 @@ extern "C"
|
|
32
47
|
#define ORAVER_10_2 ORAVERNUM(10, 2, 0, 0, 0)
|
33
48
|
#define ORAVER_11_1 ORAVERNUM(11, 1, 0, 0, 0)
|
34
49
|
#define ORAVER_12_1 ORAVERNUM(12, 1, 0, 0, 0)
|
50
|
+
#define ORAVER_18 ORAVERNUM(18, 0, 0, 0, 0)
|
35
51
|
|
36
52
|
#include "extconf.h"
|
37
53
|
#include <ruby/encoding.h>
|
@@ -316,6 +332,7 @@ typedef struct oci8_svcctx {
|
|
316
332
|
const oci8_logoff_strategy_t *logoff_strategy;
|
317
333
|
OCISession *usrhp;
|
318
334
|
OCIServer *srvhp;
|
335
|
+
ub4 server_version;
|
319
336
|
rb_pid_t pid;
|
320
337
|
unsigned char state;
|
321
338
|
char is_autocommit;
|
@@ -489,8 +506,8 @@ OCINumber *oci8_dbl_to_onum(OCINumber *result, double dbl, OCIError *errhp);
|
|
489
506
|
void Init_oci_datetime(void);
|
490
507
|
VALUE oci8_make_ocidate(OCIDate *od);
|
491
508
|
OCIDate *oci8_set_ocidate(OCIDate *od, VALUE val);
|
492
|
-
VALUE
|
493
|
-
OCIDateTime *
|
509
|
+
VALUE oci8_make_ocitimestamp(OCIDateTime *dttm, boolean have_tz);
|
510
|
+
OCIDateTime *oci8_set_ocitimestamp_tz(OCIDateTime *dttm, VALUE val, VALUE svc);
|
494
511
|
VALUE oci8_make_interval_ym(OCIInterval *s);
|
495
512
|
VALUE oci8_make_interval_ds(OCIInterval *s);
|
496
513
|
|
data/ext/oci8/oci8lib.c
CHANGED
@@ -620,11 +620,13 @@ void *oci8_find_symbol(const char *symbol_name)
|
|
620
620
|
"libclntsh.sl.10.1",
|
621
621
|
#elif defined(__APPLE__)
|
622
622
|
/* Mac OS X */
|
623
|
+
"libclntsh.dylib",
|
623
624
|
"libclntsh.dylib.12.1",
|
624
625
|
"libclntsh.dylib.11.1",
|
625
626
|
"libclntsh.dylib.10.1",
|
626
627
|
#else
|
627
628
|
/* Linux, Solaris and HP-UX(IA64) */
|
629
|
+
"libclntsh.so",
|
628
630
|
"libclntsh.so.12.1",
|
629
631
|
"libclntsh.so.11.1",
|
630
632
|
"libclntsh.so.10.1",
|
data/ext/oci8/win32.c
CHANGED
@@ -21,26 +21,6 @@
|
|
21
21
|
* @private
|
22
22
|
*/
|
23
23
|
|
24
|
-
NORETURN(static void raise_error(void));
|
25
|
-
|
26
|
-
static void raise_error(void)
|
27
|
-
{
|
28
|
-
char msg[1024];
|
29
|
-
int err = GetLastError();
|
30
|
-
char *p;
|
31
|
-
|
32
|
-
sprintf(msg, "%d: ", err);
|
33
|
-
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
34
|
-
NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
35
|
-
msg + strlen(msg), sizeof(msg) - strlen(msg), NULL);
|
36
|
-
for (p = msg; *p != '\0'; p++) {
|
37
|
-
if (*p == '\n' || *p == '\r') {
|
38
|
-
*p = ' ';
|
39
|
-
}
|
40
|
-
}
|
41
|
-
rb_raise(rb_eRuntimeError, "%s", msg);
|
42
|
-
}
|
43
|
-
|
44
24
|
typedef struct {
|
45
25
|
HKEY hKey;
|
46
26
|
HKEY hSubKey;
|
data/lib/oci8.rb
CHANGED
@@ -140,6 +140,8 @@ class OCI8
|
|
140
140
|
ORAVER_11_1 = OCI8::OracleVersion.new(11, 1)
|
141
141
|
# @private
|
142
142
|
ORAVER_12_1 = OCI8::OracleVersion.new(12, 1)
|
143
|
+
# @private
|
144
|
+
ORAVER_18 = OCI8::OracleVersion.new(18)
|
143
145
|
|
144
146
|
# @private
|
145
147
|
@@oracle_client_version = OCI8::OracleVersion.new(self.oracle_client_vernum)
|
data/lib/oci8/metadata.rb
CHANGED
@@ -1503,7 +1503,11 @@ class OCI8
|
|
1503
1503
|
attr_get_sb1(OCI_ATTR_SCALE)
|
1504
1504
|
end
|
1505
1505
|
|
1506
|
-
# The
|
1506
|
+
# The nest level.
|
1507
|
+
#
|
1508
|
+
# Oracle manual says that it always returns zero. However it returns
|
1509
|
+
# the depth of {OCI8::ArgBase#arguments} calls when #arguments returns
|
1510
|
+
# a non-empty array.
|
1507
1511
|
def level
|
1508
1512
|
attr_get_ub2(OCI_ATTR_LEVEL)
|
1509
1513
|
end
|
@@ -1607,6 +1611,10 @@ class OCI8
|
|
1607
1611
|
|
1608
1612
|
# The list of arguments at the next level (when the argument is
|
1609
1613
|
# of a record or table type).
|
1614
|
+
#
|
1615
|
+
# This method returns an array containing type information when
|
1616
|
+
# the type is a user-defined type and the Oracle server version
|
1617
|
+
# is 12c or earlier. Otherwise, it returns an empty array.
|
1610
1618
|
def arguments
|
1611
1619
|
@arguments ||= list_arguments.to_a
|
1612
1620
|
end
|
data/lib/oci8/object.rb
CHANGED
@@ -493,6 +493,16 @@ EOS
|
|
493
493
|
Proc.new do |val| datetime_to_array(val, :date) end, # set_proc
|
494
494
|
Proc.new do |val| array_to_time(val, :local) end, # get_proc
|
495
495
|
]
|
496
|
+
when :timestamp
|
497
|
+
[ATTR_TIMESTAMP, con, SIZE_OF_POINTER, 2, ALIGNMENT_OF_POINTER,
|
498
|
+
Proc.new do |val| datetime_to_array(val, :timestamp) end, # set_proc
|
499
|
+
Proc.new do |val| array_to_time(val, :local) end, # get_proc
|
500
|
+
]
|
501
|
+
when :timestamp_tz
|
502
|
+
[ATTR_TIMESTAMP_TZ, con, SIZE_OF_POINTER, 2, ALIGNMENT_OF_POINTER,
|
503
|
+
Proc.new do |val| datetime_to_array(val, :timestamp_tz) end, # set_proc
|
504
|
+
Proc.new do |val| array_to_time(val, nil) end, # get_proc
|
505
|
+
]
|
496
506
|
when :binary_double
|
497
507
|
[ATTR_BINARY_DOUBLE, nil, SIZE_OF_DOUBLE, 2, ALIGNMENT_OF_DOUBLE]
|
498
508
|
when :binary_float
|
data/lib/oci8/oci8.rb
CHANGED
@@ -340,6 +340,12 @@ class OCI8
|
|
340
340
|
|
341
341
|
# Returns the Oracle server version.
|
342
342
|
#
|
343
|
+
# When the Oracle client version is 12c or earlier and
|
344
|
+
# the Oracle server version is 18c or later, this method
|
345
|
+
# doesn't return *full* version number such as '18.3.0.0.0'.
|
346
|
+
# It returns version number whose number components after
|
347
|
+
# the first dot are zeros such as '18.0.0.0.0'.
|
348
|
+
#
|
343
349
|
# @see OCI8.oracle_client_version
|
344
350
|
# @return [OCI8::OracleVersion]
|
345
351
|
def oracle_server_version
|
data/lib/oci8/oracle_version.rb
CHANGED
@@ -66,6 +66,12 @@ class OCI8
|
|
66
66
|
major, minor, update, patch, port_update = arg.split('.').collect do |v|
|
67
67
|
v.to_i
|
68
68
|
end
|
69
|
+
elsif arg >= 0x12000000
|
70
|
+
major = (arg & 0xFF000000) >> 24
|
71
|
+
minor = (arg & 0x00FF0000) >> 16
|
72
|
+
update = (arg & 0x0000F000) >> 12
|
73
|
+
patch = (arg & 0x00000FF0) >> 4
|
74
|
+
port_update = (arg & 0x0000000F)
|
69
75
|
elsif arg >= 0x08000000
|
70
76
|
major = (arg & 0xFF000000) >> 24
|
71
77
|
minor = (arg & 0x00F00000) >> 20
|
@@ -80,7 +86,11 @@ class OCI8
|
|
80
86
|
@update = update || 0
|
81
87
|
@patch = patch || 0
|
82
88
|
@port_update = port_update || 0
|
83
|
-
@vernum =
|
89
|
+
@vernum = if @major >= 18
|
90
|
+
(@major << 24) | (@minor << 16) | (@update << 12) | (@patch << 4) | @port_update
|
91
|
+
else
|
92
|
+
(@major << 24) | (@minor << 20) | (@update << 12) | (@patch << 8) | @port_update
|
93
|
+
end
|
84
94
|
end
|
85
95
|
|
86
96
|
# Compares +self+ and +other+.
|
data/lib/oci8/version.rb
CHANGED
data/lib/ruby-oci8.rb
CHANGED
data/test/setup_test_object.sql
CHANGED
@@ -61,6 +61,8 @@ create type rb_test_obj as object (
|
|
61
61
|
obj_array_val rb_test_obj_elem_array,
|
62
62
|
obj_ary_of_ary_val rb_test_obj_elem_ary_of_ary,
|
63
63
|
date_val date,
|
64
|
+
timestamp_val timestamp(9),
|
65
|
+
timestamp_tz_val timestamp(9) with time zone,
|
64
66
|
-- date_array_val rb_test_date_array,
|
65
67
|
|
66
68
|
constructor function rb_test_obj(n number) return self as result,
|
@@ -72,19 +74,23 @@ create type rb_test_obj as object (
|
|
72
74
|
member procedure member_proc(n in integer)
|
73
75
|
)
|
74
76
|
/
|
75
|
-
create
|
76
|
-
|
77
|
+
create type body rb_test_obj is
|
77
78
|
constructor function rb_test_obj(n number) return self as result is
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
to_char(mod(round(n) * 5, 12) + 1, 'FM00') ||
|
82
|
-
to_char(mod(round(n) * 7, 27) + 1, 'FM00') ||
|
83
|
-
to_char(mod(round(n) * 9, 24), 'FM00') ||
|
84
|
-
to_char(mod(round(n) * 11, 60), 'FM00') ||
|
85
|
-
to_char(mod(round(n) * 13, 60), 'FM00'), 'yyyymmddhh24miss');
|
86
|
-
end;
|
79
|
+
str varchar(28);
|
80
|
+
ts timestamp(9);
|
81
|
+
ts_tz timestamp(9) with time zone;
|
87
82
|
begin
|
83
|
+
str := to_char(1990 + n, 'FM0000') ||
|
84
|
+
to_char(mod(round(n) * 5, 12) + 1, 'FM00') ||
|
85
|
+
to_char(mod(round(n) * 7, 27) + 1, 'FM00') ||
|
86
|
+
to_char(mod(round(n) * 9, 24), 'FM00') ||
|
87
|
+
to_char(mod(round(n) * 11, 60), 'FM00') ||
|
88
|
+
to_char(mod(round(n) * 13, 60), 'FM00') ||
|
89
|
+
to_char(mod(round(n) * 333333333, 1000000000), 'FM000000000');
|
90
|
+
ts := to_timestamp(str, 'yyyymmddhh24missff9');
|
91
|
+
str := str || to_char(mod(round(n) * 15, 24) - 11, 'FMS00') ||
|
92
|
+
to_char(mod(round(n) * 17, 60), 'FM00');
|
93
|
+
ts_tz := to_timestamp_tz(str, 'yyyymmddhh24missff9tzhtzm');
|
88
94
|
self.int_val := n;
|
89
95
|
self.flt_val := n;
|
90
96
|
self.num_val := n;
|
@@ -96,7 +102,9 @@ create or replace type body rb_test_obj is
|
|
96
102
|
self.nclob_val := to_clob(n);
|
97
103
|
self.blob_val := to_blob(utl_raw.cast_to_raw(to_char(n)));
|
98
104
|
self.obj_val := rb_test_obj_elem(n, n + 1);
|
99
|
-
self.date_val :=
|
105
|
+
self.date_val := ts;
|
106
|
+
self.timestamp_val := ts;
|
107
|
+
self.timestamp_tz_val := ts_tz;
|
100
108
|
if self.int_val != 1 then
|
101
109
|
self.int_array_val := rb_test_int_array(n, n + 1, n + 2);
|
102
110
|
self.flt_array_val := rb_test_flt_array(n, n + 1, n + 2);
|
@@ -120,7 +128,7 @@ create or replace type body rb_test_obj is
|
|
120
128
|
|
121
129
|
static function test_object_version return integer is
|
122
130
|
begin
|
123
|
-
return
|
131
|
+
return 4;
|
124
132
|
end;
|
125
133
|
|
126
134
|
static function class_func(n number) return rb_test_obj is
|
data/test/test_all.rb
CHANGED
@@ -26,6 +26,7 @@ require "#{srcdir}/test_oracle_version"
|
|
26
26
|
require "#{srcdir}/test_error"
|
27
27
|
require "#{srcdir}/test_connection_pool"
|
28
28
|
require "#{srcdir}/test_object"
|
29
|
+
require "#{srcdir}/test_properties.rb"
|
29
30
|
|
30
31
|
if OCI8.respond_to? :encoding
|
31
32
|
require "#{srcdir}/test_encoding"
|
data/test/test_clob.rb
CHANGED
@@ -24,22 +24,6 @@ class TestCLob < Minitest::Test
|
|
24
24
|
lob.close
|
25
25
|
end
|
26
26
|
|
27
|
-
def test_insert_with_flush
|
28
|
-
filename = File.basename($lobfile)
|
29
|
-
@conn.exec("DELETE FROM test_table WHERE filename = :1", filename)
|
30
|
-
@conn.exec("INSERT INTO test_table(filename, content) VALUES (:1, EMPTY_CLOB())", filename)
|
31
|
-
cursor = @conn.exec("SELECT content FROM test_table WHERE filename = :1 FOR UPDATE", filename)
|
32
|
-
lob = cursor.fetch[0]
|
33
|
-
lob.sync = false
|
34
|
-
open($lobfile) do |f|
|
35
|
-
while s = f.read(1000)
|
36
|
-
lob.write(s)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
lob.flush
|
40
|
-
lob.close
|
41
|
-
end
|
42
|
-
|
43
27
|
def test_insert_symbol
|
44
28
|
filename = 'test_symbol'
|
45
29
|
value = :foo_bar
|
@@ -76,6 +60,9 @@ class TestCLob < Minitest::Test
|
|
76
60
|
|
77
61
|
# https://github.com/kubo/ruby-oci8/issues/20
|
78
62
|
def test_github_issue_20
|
63
|
+
# Skip this test if FULLTEST isn't set because it takes 4 minutes in my Linux box.
|
64
|
+
return if ENV['FULLTEST']
|
65
|
+
|
79
66
|
lob1 = OCI8::CLOB.new(@conn, ' ' * (1024 * 1024))
|
80
67
|
lob1.read(1) # to suppress `warning: assigned but unused variable - lob1`
|
81
68
|
begin
|
data/test/test_object.rb
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
require 'oci8'
|
2
2
|
require File.dirname(__FILE__) + '/config'
|
3
3
|
|
4
|
+
class Time
|
5
|
+
def inspect
|
6
|
+
self.strftime("%Y-%m-%d %H:%M:%S.%N %:z")
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
4
10
|
conn = OCI8.new($dbuser, $dbpass, $dbname)
|
5
11
|
error_message = nil
|
6
12
|
begin
|
@@ -22,7 +28,7 @@ begin
|
|
22
28
|
|
23
29
|
begin
|
24
30
|
version = RbTestObj.test_object_version(conn)
|
25
|
-
error_message = "Invalid test object version" if version !=
|
31
|
+
error_message = "Invalid test object version" if version != 4
|
26
32
|
rescue NoMethodError
|
27
33
|
raise unless $!.to_s.include?('test_object_version')
|
28
34
|
error_message = "rb_test_obj.test_object_version is not declared."
|
@@ -100,7 +106,8 @@ class TestObj1 < Minitest::Test
|
|
100
106
|
attr_reader :obj_array_val
|
101
107
|
attr_reader :obj_ary_of_ary_val
|
102
108
|
attr_reader :date_val
|
103
|
-
|
109
|
+
attr_reader :timestamp_val
|
110
|
+
attr_reader :timestamp_tz_val
|
104
111
|
|
105
112
|
attr_accessor :assertions
|
106
113
|
|
@@ -109,16 +116,28 @@ class TestObj1 < Minitest::Test
|
|
109
116
|
@assertions = 0
|
110
117
|
end
|
111
118
|
|
112
|
-
def
|
119
|
+
def to_test_datetime(n, type)
|
113
120
|
year = (1990 + n).round
|
114
121
|
month = (n.round * 5) % 12 + 1
|
115
122
|
mday = (n.round * 7) % 27 + 1
|
116
123
|
hour = (n.round * 9) % 24
|
117
124
|
minute = (n.round * 11) % 60
|
118
125
|
sec = (n.round * 13) % 60
|
119
|
-
|
126
|
+
nsec = if type == :date
|
127
|
+
0
|
128
|
+
else
|
129
|
+
((n.round * 333_333_333) % 1_000_000_000).to_r / 1_000_000_000
|
130
|
+
end
|
131
|
+
tz = if type == :timestamp_tz
|
132
|
+
tzh = (n.round * 15) % 24 - 11
|
133
|
+
tzm = (n.round * 17) % 60
|
134
|
+
format('%+03d:%02d', tzh, tzm)
|
135
|
+
else
|
136
|
+
nil
|
137
|
+
end
|
138
|
+
convert_to_time(year, month, mday, hour, minute, sec, nsec, tz)
|
120
139
|
end
|
121
|
-
private :
|
140
|
+
private :to_test_datetime
|
122
141
|
|
123
142
|
def next
|
124
143
|
@n += 1.2
|
@@ -135,7 +154,9 @@ class TestObj1 < Minitest::Test
|
|
135
154
|
@nclob_val = @str_val
|
136
155
|
@blob_val = @str_val
|
137
156
|
@obj_val = ExpectedValObjElem.new(@int_val, @int_val + 1)
|
138
|
-
@date_val =
|
157
|
+
@date_val = to_test_datetime(@n, :date)
|
158
|
+
@timestamp_val = to_test_datetime(@n, :timestamp)
|
159
|
+
@timestamp_tz_val = to_test_datetime(@n, :timestamp_tz)
|
139
160
|
if @int_val == 1
|
140
161
|
@int_array_val = nil
|
141
162
|
@flt_array_val = nil
|
@@ -199,7 +220,8 @@ class TestObj1 < Minitest::Test
|
|
199
220
|
obj_array_val = val[18]
|
200
221
|
obj_ary_of_ary_val = val[19]
|
201
222
|
date_val = val[20]
|
202
|
-
|
223
|
+
timestamp_val = val[21]
|
224
|
+
timestamp_tz_val = val[22]
|
203
225
|
else
|
204
226
|
assert_instance_of(RbTestObj, val)
|
205
227
|
int_val = val.int_val
|
@@ -223,7 +245,8 @@ class TestObj1 < Minitest::Test
|
|
223
245
|
obj_array_val = val.obj_array_val
|
224
246
|
obj_ary_of_ary_val = val.obj_ary_of_ary_val
|
225
247
|
date_val = val.date_val
|
226
|
-
|
248
|
+
timestamp_val = val.timestamp_val
|
249
|
+
timestamp_tz_val = val.timestamp_tz_val
|
227
250
|
end
|
228
251
|
|
229
252
|
assert_equal(@int_val, int_val)
|
@@ -267,7 +290,8 @@ class TestObj1 < Minitest::Test
|
|
267
290
|
assert_nil(obj_ary_of_ary_val)
|
268
291
|
end
|
269
292
|
assert_equal(@date_val, date_val)
|
270
|
-
|
293
|
+
assert_equal(@timestamp_val, timestamp_val)
|
294
|
+
assert_equal(@timestamp_tz_val, timestamp_tz_val)
|
271
295
|
end
|
272
296
|
|
273
297
|
def assert_array_in_delta(exp, val)
|
data/test/test_oci8.rb
CHANGED
@@ -491,9 +491,23 @@ EOS
|
|
491
491
|
else
|
492
492
|
raise "Unknown column size #{column_size}"
|
493
493
|
end
|
494
|
-
driver_name = cursor.fetch[0]
|
494
|
+
driver_name = cursor.fetch[0].strip
|
495
495
|
cursor.close
|
496
496
|
assert_equal(expected_value, driver_name)
|
497
497
|
end
|
498
498
|
end
|
499
|
+
|
500
|
+
def test_server_version
|
501
|
+
cursor = @conn.exec("select * from product_component_version where product like 'Oracle Database %'")
|
502
|
+
row = cursor.fetch_hash
|
503
|
+
cursor.close
|
504
|
+
ver = if OCI8::oracle_client_version >= OCI8::ORAVER_18
|
505
|
+
row['VERSION_FULL'] || row['VERSION']
|
506
|
+
else
|
507
|
+
# OCI8#oracle_server_version could not get infomation corresponding
|
508
|
+
# to VERSION_FULL when the Oracle client version is below 18.1.
|
509
|
+
row['VERSION']
|
510
|
+
end
|
511
|
+
assert_equal(ver, @conn.oracle_server_version.to_s)
|
512
|
+
end
|
499
513
|
end # TestOCI8
|
data/test/test_package_type.rb
CHANGED
@@ -639,7 +639,11 @@ class TestPackageType < Minitest::Test
|
|
639
639
|
:sub_name => "TABLE_OF_PLS_INTEGER",
|
640
640
|
:link => "",
|
641
641
|
#:type_metadata => nil,
|
642
|
-
:arguments =>
|
642
|
+
:arguments => ($oracle_server_version >= OCI8::ORAVER_18) ?
|
643
|
+
{
|
644
|
+
:class => Array,
|
645
|
+
:size => 0,
|
646
|
+
} : {
|
643
647
|
:class => Array,
|
644
648
|
:size => 1,
|
645
649
|
[0] => {
|
@@ -729,7 +733,11 @@ class TestPackageType < Minitest::Test
|
|
729
733
|
:sub_name => "TABLE_OF_REC1",
|
730
734
|
:link => "",
|
731
735
|
#:type_metadata => nil,
|
732
|
-
:arguments =>
|
736
|
+
:arguments => ($oracle_server_version >= OCI8::ORAVER_18) ?
|
737
|
+
{
|
738
|
+
:class => Array,
|
739
|
+
:size => 0,
|
740
|
+
} : {
|
733
741
|
:class => Array,
|
734
742
|
:size => 1,
|
735
743
|
[0] => {
|
@@ -846,7 +854,11 @@ class TestPackageType < Minitest::Test
|
|
846
854
|
:sub_name => "TABLE_OF_REC1",
|
847
855
|
:link => "",
|
848
856
|
#:type_metadata => nil,
|
849
|
-
:arguments =>
|
857
|
+
:arguments => ($oracle_server_version >= OCI8::ORAVER_18) ?
|
858
|
+
{
|
859
|
+
:class => Array,
|
860
|
+
:size => 0,
|
861
|
+
} : {
|
850
862
|
:class => Array,
|
851
863
|
:size => 1,
|
852
864
|
[0] => {
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'oci8'
|
2
|
+
require File.dirname(__FILE__) + '/config'
|
3
|
+
|
4
|
+
class TestProperties < Minitest::Test
|
5
|
+
def test_tcp_keepalive_time
|
6
|
+
begin
|
7
|
+
oldval = OCI8.properties[:tcp_keepalive_time]
|
8
|
+
begin
|
9
|
+
OCI8.properties[:tcp_keepalive_time] = 600
|
10
|
+
assert(true)
|
11
|
+
ensure
|
12
|
+
OCI8.properties[:tcp_keepalive_time] = oldval
|
13
|
+
end
|
14
|
+
rescue NotImplementedError
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
metadata
CHANGED
@@ -1,35 +1,27 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-oci8
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 2
|
7
|
-
- 2
|
8
|
-
- 5
|
9
|
-
- 1
|
10
|
-
version: 2.2.5.1
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.2.6
|
5
|
+
prerelease:
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Kubo Takehiro
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
date: 2017-12-27 00:00:00 +09:00
|
19
|
-
default_executable:
|
12
|
+
date: 2018-08-22 00:00:00.000000000 Z
|
20
13
|
dependencies: []
|
14
|
+
description: ! 'ruby-oci8 is a ruby interface for Oracle using OCI8 API. It is available
|
15
|
+
with Oracle 10g or later including Oracle Instant Client.
|
21
16
|
|
22
|
-
|
23
|
-
ruby-oci8 is a ruby interface for Oracle using OCI8 API. It is available with Oracle 10g or later including Oracle Instant Client.
|
24
|
-
|
17
|
+
'
|
25
18
|
email: kubo@jiubao.org
|
26
19
|
executables: []
|
27
|
-
|
28
|
-
extensions:
|
20
|
+
extensions:
|
29
21
|
- ext/oci8/extconf.rb
|
30
|
-
extra_rdoc_files:
|
22
|
+
extra_rdoc_files:
|
31
23
|
- README.md
|
32
|
-
files:
|
24
|
+
files:
|
33
25
|
- .yardopts
|
34
26
|
- COPYING
|
35
27
|
- COPYING_old
|
@@ -141,41 +133,34 @@ files:
|
|
141
133
|
- test/test_oradate.rb
|
142
134
|
- test/test_oranumber.rb
|
143
135
|
- test/test_package_type.rb
|
136
|
+
- test/test_properties.rb
|
144
137
|
- test/test_rowid.rb
|
145
|
-
has_rdoc: true
|
146
138
|
homepage: http://www.rubydoc.info/github/kubo/ruby-oci8
|
147
|
-
licenses:
|
139
|
+
licenses:
|
148
140
|
- BSD-2-Clause
|
149
141
|
post_install_message:
|
150
142
|
rdoc_options: []
|
151
|
-
|
152
|
-
require_paths:
|
143
|
+
require_paths:
|
153
144
|
- lib
|
154
145
|
- ext/oci8
|
155
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
146
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
156
147
|
none: false
|
157
|
-
requirements:
|
158
|
-
- -
|
159
|
-
- !ruby/object:Gem::Version
|
160
|
-
segments:
|
161
|
-
- 1
|
162
|
-
- 9
|
163
|
-
- 1
|
148
|
+
requirements:
|
149
|
+
- - ! '>='
|
150
|
+
- !ruby/object:Gem::Version
|
164
151
|
version: 1.9.1
|
165
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
152
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
166
153
|
none: false
|
167
|
-
requirements:
|
168
|
-
- -
|
169
|
-
- !ruby/object:Gem::Version
|
170
|
-
|
171
|
-
- 0
|
172
|
-
version: "0"
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
173
158
|
requirements: []
|
174
|
-
|
175
159
|
rubyforge_project:
|
176
|
-
rubygems_version: 1.
|
160
|
+
rubygems_version: 1.8.11
|
177
161
|
signing_key:
|
178
162
|
specification_version: 3
|
179
163
|
summary: Ruby interface for Oracle using OCI8 API
|
180
|
-
test_files:
|
164
|
+
test_files:
|
181
165
|
- test/test_all.rb
|
166
|
+
has_rdoc: yard
|