ruby-oci8 2.2.5.1 → 2.2.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem Version](https://badge.fury.io/rb/ruby-oci8.svg)](http://badge.fury.io/rb/ruby-oci8)
|
5
|
-
[![
|
5
|
+
[![Build Status](https://travis-ci.org/kubo/ruby-oci8.svg?branch=master)](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
|