ruby-oci8 2.1.7 → 2.1.8
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 +136 -0
- data/NEWS +61 -0
- data/README.md +2 -2
- data/VERSION +1 -1
- data/dist-files +5 -0
- data/docs/install-instant-client.md +2 -0
- data/ext/oci8/attr.c +0 -9
- data/ext/oci8/bind.c +86 -28
- data/ext/oci8/connection_pool.c +32 -17
- data/ext/oci8/extconf.rb +21 -0
- data/ext/oci8/hook_funcs.c +215 -0
- data/ext/oci8/lob.c +363 -168
- data/ext/oci8/metadata.c +43 -26
- data/ext/oci8/object.c +115 -36
- data/ext/oci8/oci8.c +392 -269
- data/ext/oci8/oci8.h +88 -33
- data/ext/oci8/oci8lib.c +59 -28
- data/ext/oci8/ocidatetime.c +100 -36
- data/ext/oci8/ocihandle.c +288 -286
- data/ext/oci8/ocinumber.c +172 -112
- data/ext/oci8/oradate.c +129 -87
- data/ext/oci8/plthook.h +56 -0
- data/ext/oci8/plthook_elf.c +537 -0
- data/ext/oci8/plthook_osx.c +474 -0
- data/ext/oci8/plthook_win32.c +376 -0
- data/ext/oci8/stmt.c +112 -75
- data/lib/oci8/cursor.rb +1 -1
- data/lib/oci8/oci8.rb +71 -0
- data/lib/oci8/properties.rb +18 -3
- metadata +10 -16
data/ext/oci8/connection_pool.c
CHANGED
@@ -2,13 +2,15 @@
|
|
2
2
|
/*
|
3
3
|
* connection_pool.c - part of ruby-oci8
|
4
4
|
*
|
5
|
-
* Copyright (C) 2010
|
5
|
+
* Copyright (C) 2010-2014 Kubo Takehiro <kubo@jiubao.org>
|
6
6
|
*
|
7
7
|
*/
|
8
8
|
#include "oci8.h"
|
9
9
|
|
10
10
|
static VALUE cOCIConnectionPool;
|
11
11
|
|
12
|
+
#define TO_CPOOL(obj) ((oci8_cpool_t *)oci8_check_typeddata((obj), &oci8_cpool_data_type, 1))
|
13
|
+
|
12
14
|
typedef struct {
|
13
15
|
oci8_base_t base;
|
14
16
|
VALUE pool_name;
|
@@ -32,23 +34,36 @@ static void oci8_cpool_free(oci8_base_t *base)
|
|
32
34
|
{
|
33
35
|
oci8_run_native_thread(cpool_free_thread, base->hp.poolhp);
|
34
36
|
base->type = 0;
|
37
|
+
base->closed = 1;
|
35
38
|
base->hp.ptr = NULL;
|
36
39
|
}
|
37
40
|
|
38
|
-
static
|
41
|
+
static const oci8_handle_data_type_t oci8_cpool_data_type = {
|
42
|
+
{
|
43
|
+
"OCI8::ConnectionPool",
|
44
|
+
{
|
45
|
+
(RUBY_DATA_FUNC)oci8_cpool_mark,
|
46
|
+
oci8_handle_cleanup,
|
47
|
+
oci8_handle_size,
|
48
|
+
},
|
49
|
+
&oci8_handle_data_type.rb_data_type, NULL,
|
50
|
+
#ifdef RUBY_TYPED_WB_PROTECTED
|
51
|
+
RUBY_TYPED_WB_PROTECTED,
|
52
|
+
#endif
|
53
|
+
},
|
54
|
+
oci8_cpool_free,
|
55
|
+
sizeof(oci8_cpool_t),
|
56
|
+
};
|
57
|
+
|
58
|
+
static VALUE oci8_cpool_alloc(VALUE klass)
|
39
59
|
{
|
40
|
-
|
60
|
+
VALUE self = oci8_allocate_typeddata(klass, &oci8_cpool_data_type);
|
61
|
+
oci8_cpool_t *cpool = (oci8_cpool_t *)RTYPEDDATA_DATA(self);
|
41
62
|
|
42
63
|
cpool->pool_name = Qnil;
|
64
|
+
return self;
|
43
65
|
}
|
44
66
|
|
45
|
-
static oci8_base_vtable_t oci8_cpool_vtable = {
|
46
|
-
oci8_cpool_mark,
|
47
|
-
oci8_cpool_free,
|
48
|
-
sizeof(oci8_cpool_t),
|
49
|
-
oci8_cpool_init,
|
50
|
-
};
|
51
|
-
|
52
67
|
/*
|
53
68
|
* call-seq:
|
54
69
|
* OCI8::ConnectionPool.new(conn_min, conn_max, conn_incr, username = nil, password = nil, dbname = nil) -> connection pool
|
@@ -89,9 +104,9 @@ static VALUE oci8_cpool_initialize(int argc, VALUE *argv, VALUE self)
|
|
89
104
|
VALUE username;
|
90
105
|
VALUE password;
|
91
106
|
VALUE dbname;
|
92
|
-
oci8_cpool_t *cpool =
|
93
|
-
OraText *pool_name;
|
94
|
-
sb4 pool_name_len;
|
107
|
+
oci8_cpool_t *cpool = TO_CPOOL(self);
|
108
|
+
OraText *pool_name = NULL;
|
109
|
+
sb4 pool_name_len = 0;
|
95
110
|
sword rv;
|
96
111
|
|
97
112
|
/* check arguments */
|
@@ -138,7 +153,7 @@ static VALUE oci8_cpool_initialize(int argc, VALUE *argv, VALUE self)
|
|
138
153
|
NIL_P(password) ? 0 : RSTRING_LEN(password),
|
139
154
|
OCI_DEFAULT),
|
140
155
|
&cpool->base);
|
141
|
-
cpool->pool_name
|
156
|
+
RB_OBJ_WRITE(cpool->base.self, &cpool->pool_name, rb_str_new(TO_CHARPTR(pool_name), pool_name_len));
|
142
157
|
rb_str_freeze(cpool->pool_name);
|
143
158
|
return Qnil;
|
144
159
|
}
|
@@ -152,7 +167,7 @@ static VALUE oci8_cpool_initialize(int argc, VALUE *argv, VALUE self)
|
|
152
167
|
*/
|
153
168
|
static VALUE oci8_cpool_reinitialize(VALUE self, VALUE conn_min, VALUE conn_max, VALUE conn_incr)
|
154
169
|
{
|
155
|
-
oci8_cpool_t *cpool =
|
170
|
+
oci8_cpool_t *cpool = TO_CPOOL(self);
|
156
171
|
OraText *pool_name;
|
157
172
|
sb4 pool_name_len;
|
158
173
|
|
@@ -180,7 +195,7 @@ static VALUE oci8_cpool_reinitialize(VALUE self, VALUE conn_min, VALUE conn_max,
|
|
180
195
|
*/
|
181
196
|
static VALUE oci8_cpool_pool_name(VALUE self)
|
182
197
|
{
|
183
|
-
oci8_cpool_t *cpool =
|
198
|
+
oci8_cpool_t *cpool = TO_CPOOL(self);
|
184
199
|
|
185
200
|
return cpool->pool_name;
|
186
201
|
}
|
@@ -193,7 +208,7 @@ void Init_oci8_connection_pool(VALUE cOCI8)
|
|
193
208
|
cOCIConnectionPool = rb_define_class_under(cOCI8, "ConnectionPool", cOCIHandle);
|
194
209
|
#endif
|
195
210
|
|
196
|
-
cOCIConnectionPool = oci8_define_class_under(cOCI8, "ConnectionPool", &
|
211
|
+
cOCIConnectionPool = oci8_define_class_under(cOCI8, "ConnectionPool", &oci8_cpool_data_type, oci8_cpool_alloc);
|
197
212
|
|
198
213
|
rb_define_private_method(cOCIConnectionPool, "initialize", oci8_cpool_initialize, -1);
|
199
214
|
rb_define_method(cOCIConnectionPool, "reinitialize", oci8_cpool_reinitialize, 3);
|
data/ext/oci8/extconf.rb
CHANGED
@@ -118,10 +118,12 @@ have_header("ruby/thread.h")
|
|
118
118
|
have_var("ruby_errinfo", "ruby.h") # ruby 1.8
|
119
119
|
have_func("rb_errinfo", "ruby.h") # ruby 1.9
|
120
120
|
|
121
|
+
have_func("rb_str_set_len", "ruby.h")
|
121
122
|
have_func("rb_set_end_proc", "ruby.h")
|
122
123
|
have_func("rb_class_superclass", "ruby.h")
|
123
124
|
have_func("rb_thread_blocking_region", "ruby.h")
|
124
125
|
have_func("rb_thread_call_without_gvl", "ruby/thread.h")
|
126
|
+
have_func("rb_sym2str", "ruby.h")
|
125
127
|
if (defined? RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
|
126
128
|
have_func("rb_str_buf_cat_ascii", "ruby.h")
|
127
129
|
have_func("rb_enc_str_buf_cat", "ruby.h")
|
@@ -181,6 +183,25 @@ else
|
|
181
183
|
raise 'unsupported ruby engine: ' + RUBY_ENGINE
|
182
184
|
end
|
183
185
|
|
186
|
+
print "checking for plthook... "
|
187
|
+
STDOUT.flush
|
188
|
+
case RUBY_PLATFORM
|
189
|
+
when /mswin32|cygwin|mingw32|bccwin32/
|
190
|
+
plthook_src = "plthook_win32.c"
|
191
|
+
when /darwin/
|
192
|
+
plthook_src = "plthook_osx.c"
|
193
|
+
else
|
194
|
+
plthook_src = "plthook_elf.c"
|
195
|
+
end
|
196
|
+
if xsystem(cc_command("").gsub(CONFTEST_C, File.dirname(__FILE__) + "/" + plthook_src))
|
197
|
+
puts plthook_src
|
198
|
+
$objs << plthook_src.gsub(/\.c$/, '.o')
|
199
|
+
$objs << "hook_funcs.o"
|
200
|
+
$defs << "-DHAVE_PLTHOOK"
|
201
|
+
else
|
202
|
+
puts "no"
|
203
|
+
end
|
204
|
+
|
184
205
|
$defs << "-DInit_oci8lib=Init_#{so_basename}"
|
185
206
|
$defs << "-Doci8lib=#{so_basename}"
|
186
207
|
$defs << "-DOCI8LIB_VERSION=\\\"#{RUBY_OCI8_VERSION}\\\""
|
@@ -0,0 +1,215 @@
|
|
1
|
+
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
|
2
|
+
/*
|
3
|
+
* hook.c
|
4
|
+
*
|
5
|
+
* Copyright (C) 2015 Kubo Takehiro <kubo@jiubao.org>
|
6
|
+
*/
|
7
|
+
#include "oci8.h"
|
8
|
+
#include "plthook.h"
|
9
|
+
#ifndef WIN32
|
10
|
+
#include <unistd.h>
|
11
|
+
#include <sys/socket.h>
|
12
|
+
#endif
|
13
|
+
|
14
|
+
#define DEBUG_HOOK_FUNCS 1
|
15
|
+
|
16
|
+
#ifdef WIN32
|
17
|
+
static CRITICAL_SECTION lock;
|
18
|
+
#define LOCK(lock) EnterCriticalSection(lock)
|
19
|
+
#define UNLOCK(lock) LeaveCriticalSection(lock)
|
20
|
+
#else
|
21
|
+
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
22
|
+
#define LOCK(lock) pthread_mutex_lock(lock)
|
23
|
+
#define UNLOCK(lock) pthread_mutex_unlock(lock)
|
24
|
+
#define SOCKET int
|
25
|
+
#define INVALID_SOCKET (-1)
|
26
|
+
#endif
|
27
|
+
|
28
|
+
typedef struct {
|
29
|
+
const char *func_name;
|
30
|
+
void *func_addr;
|
31
|
+
void *old_func_addr;
|
32
|
+
} hook_func_entry_t;
|
33
|
+
|
34
|
+
typedef struct socket_entry {
|
35
|
+
struct socket_entry *next;
|
36
|
+
struct socket_entry *prev;
|
37
|
+
SOCKET sock;
|
38
|
+
} socket_entry_t;
|
39
|
+
|
40
|
+
static socket_entry_t sockets_in_use = {
|
41
|
+
&sockets_in_use, &sockets_in_use, INVALID_SOCKET,
|
42
|
+
};
|
43
|
+
|
44
|
+
static void socket_entry_set(socket_entry_t *entry, SOCKET sock)
|
45
|
+
{
|
46
|
+
LOCK(&lock);
|
47
|
+
entry->next = sockets_in_use.next;
|
48
|
+
entry->prev = &sockets_in_use;
|
49
|
+
sockets_in_use.next->prev = entry;
|
50
|
+
sockets_in_use.next = entry;
|
51
|
+
entry->sock = sock;
|
52
|
+
UNLOCK(&lock);
|
53
|
+
}
|
54
|
+
|
55
|
+
static void socket_entry_clear(socket_entry_t *entry)
|
56
|
+
{
|
57
|
+
LOCK(&lock);
|
58
|
+
entry->next->prev = entry->prev;
|
59
|
+
entry->prev->next = entry->next;
|
60
|
+
UNLOCK(&lock);
|
61
|
+
}
|
62
|
+
|
63
|
+
static int replace_functions(const char * const *files, hook_func_entry_t *functions)
|
64
|
+
{
|
65
|
+
int i;
|
66
|
+
|
67
|
+
for (i = 0; files[i] != NULL; i++) {
|
68
|
+
const char *file = files[i];
|
69
|
+
plthook_t *ph;
|
70
|
+
if (plthook_open(&ph, file) == 0) {
|
71
|
+
int j;
|
72
|
+
int rv = 0;
|
73
|
+
|
74
|
+
/* install hooks */
|
75
|
+
for (j = 0; functions[j].func_name != NULL ; j++) {
|
76
|
+
hook_func_entry_t *function = &functions[j];
|
77
|
+
rv = plthook_replace(ph, function->func_name, function->func_addr, &function->old_func_addr);
|
78
|
+
if (rv != 0) {
|
79
|
+
while (--j >= 0) {
|
80
|
+
/*restore hooked fuction address */
|
81
|
+
plthook_replace(ph, functions[j].func_name, functions[j].old_func_addr, NULL);
|
82
|
+
}
|
83
|
+
plthook_close(ph);
|
84
|
+
rb_raise(rb_eRuntimeError, "Could not replace function %s in %s", function->func_name, file);
|
85
|
+
}
|
86
|
+
}
|
87
|
+
plthook_close(ph);
|
88
|
+
return 0;
|
89
|
+
}
|
90
|
+
}
|
91
|
+
return -1;
|
92
|
+
}
|
93
|
+
|
94
|
+
#ifdef WIN32
|
95
|
+
|
96
|
+
static int locK_is_initialized;
|
97
|
+
|
98
|
+
static int WSAAPI hook_WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
|
99
|
+
|
100
|
+
static const char * const tcp_func_files[] = {
|
101
|
+
/* full client */
|
102
|
+
"orantcp12.dll",
|
103
|
+
"orantcp11.dll",
|
104
|
+
"orantcp10.dll",
|
105
|
+
"orantcp9.dll",
|
106
|
+
/* instant client basic */
|
107
|
+
"oraociei12.dll",
|
108
|
+
"oraociei11.dll",
|
109
|
+
"oraociei10.dll",
|
110
|
+
/* instant client basic lite */
|
111
|
+
"oraociicus12.dll",
|
112
|
+
"oraociicus11.dll",
|
113
|
+
"oraociicus10.dll",
|
114
|
+
NULL,
|
115
|
+
};
|
116
|
+
|
117
|
+
static hook_func_entry_t tcp_functions[] = {
|
118
|
+
{"WSARecv", (void*)hook_WSARecv, NULL},
|
119
|
+
{NULL, NULL, NULL},
|
120
|
+
};
|
121
|
+
|
122
|
+
/* WSARecv() is used for TCP connections */
|
123
|
+
static int WSAAPI hook_WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
|
124
|
+
{
|
125
|
+
socket_entry_t entry;
|
126
|
+
int rv;
|
127
|
+
|
128
|
+
socket_entry_set(&entry, s);
|
129
|
+
rv = WSARecv(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine);
|
130
|
+
socket_entry_clear(&entry);
|
131
|
+
return rv;
|
132
|
+
}
|
133
|
+
|
134
|
+
void oci8_install_hook_functions()
|
135
|
+
{
|
136
|
+
InitializeCriticalSectionAndSpinCount(&lock, 5000);
|
137
|
+
locK_is_initialized = 1;
|
138
|
+
|
139
|
+
if (replace_functions(tcp_func_files, tcp_functions) != 0) {
|
140
|
+
rb_raise(rb_eRuntimeError, "No DLL is found to hook.");
|
141
|
+
}
|
142
|
+
}
|
143
|
+
|
144
|
+
static void shutdown_socket(socket_entry_t *entry)
|
145
|
+
{
|
146
|
+
/* This is dangerous. But I don't know how to cancel WSARecv().
|
147
|
+
* This technique is usable only at the process termination.
|
148
|
+
* Otherwise, Oracle client library may close sockets used by
|
149
|
+
* others.
|
150
|
+
*/
|
151
|
+
closesocket(entry->sock);
|
152
|
+
}
|
153
|
+
|
154
|
+
#else
|
155
|
+
static ssize_t hook_read(int fd, void *buf, size_t count);
|
156
|
+
|
157
|
+
#ifdef __APPLE__
|
158
|
+
#define SO_EXT "dylib"
|
159
|
+
#else
|
160
|
+
#define SO_EXT "so"
|
161
|
+
#endif
|
162
|
+
|
163
|
+
static const char * const files[] = {
|
164
|
+
"libclntsh." SO_EXT ".12.1",
|
165
|
+
"libclntsh." SO_EXT ".11.1",
|
166
|
+
"libclntsh." SO_EXT ".10.1",
|
167
|
+
"libclntsh." SO_EXT ".9.0",
|
168
|
+
NULL,
|
169
|
+
};
|
170
|
+
|
171
|
+
static hook_func_entry_t functions[] = {
|
172
|
+
{"read", (void*)hook_read, NULL},
|
173
|
+
{NULL, NULL, NULL},
|
174
|
+
};
|
175
|
+
|
176
|
+
static ssize_t hook_read(int fd, void *buf, size_t count)
|
177
|
+
{
|
178
|
+
socket_entry_t entry;
|
179
|
+
ssize_t rv;
|
180
|
+
|
181
|
+
socket_entry_set(&entry, fd);
|
182
|
+
rv = read(fd, buf, count);
|
183
|
+
socket_entry_clear(&entry);
|
184
|
+
return rv;
|
185
|
+
}
|
186
|
+
|
187
|
+
void oci8_install_hook_functions(void)
|
188
|
+
{
|
189
|
+
if (replace_functions(files, functions) != 0) {
|
190
|
+
rb_raise(rb_eRuntimeError, "No shared library is found to hook.");
|
191
|
+
}
|
192
|
+
}
|
193
|
+
|
194
|
+
static void shutdown_socket(socket_entry_t *entry)
|
195
|
+
{
|
196
|
+
shutdown(entry->sock, SHUT_RDWR);
|
197
|
+
}
|
198
|
+
#endif
|
199
|
+
|
200
|
+
void oci8_shutdown_sockets(void)
|
201
|
+
{
|
202
|
+
socket_entry_t *entry;
|
203
|
+
|
204
|
+
#ifdef WIN32
|
205
|
+
if (!locK_is_initialized) {
|
206
|
+
return;
|
207
|
+
}
|
208
|
+
#endif
|
209
|
+
|
210
|
+
LOCK(&lock);
|
211
|
+
for (entry = sockets_in_use.next; entry != &sockets_in_use; entry = entry->next) {
|
212
|
+
shutdown_socket(entry);
|
213
|
+
}
|
214
|
+
UNLOCK(&lock);
|
215
|
+
}
|
data/ext/oci8/lob.c
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
/*
|
3
3
|
* lob.c - part of ruby-oci8
|
4
4
|
*
|
5
|
-
* Copyright (C) 2002-
|
5
|
+
* Copyright (C) 2002-2015 Kubo Takehiro <kubo@jiubao.org>
|
6
6
|
*/
|
7
7
|
#include "oci8.h"
|
8
8
|
|
@@ -18,6 +18,8 @@ static VALUE seek_set;
|
|
18
18
|
static VALUE seek_cur;
|
19
19
|
static VALUE seek_end;
|
20
20
|
|
21
|
+
#define TO_LOB(obj) ((oci8_lob_t *)oci8_check_typeddata((obj), &oci8_lob_data_type, 1))
|
22
|
+
|
21
23
|
enum state {
|
22
24
|
S_NO_OPEN_CLOSE,
|
23
25
|
S_OPEN,
|
@@ -46,6 +48,148 @@ static oci8_svcctx_t *check_svcctx(oci8_lob_t *lob)
|
|
46
48
|
|
47
49
|
static VALUE oci8_lob_write(VALUE self, VALUE data);
|
48
50
|
|
51
|
+
static void oci8_lob_mark(oci8_base_t *base)
|
52
|
+
{
|
53
|
+
oci8_lob_t *lob = (oci8_lob_t *)base;
|
54
|
+
if (lob->svcctx != NULL) {
|
55
|
+
rb_gc_mark(lob->svcctx->base.self);
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
static void oci8_lob_free(oci8_base_t *base)
|
60
|
+
{
|
61
|
+
oci8_lob_t *lob = (oci8_lob_t *)base;
|
62
|
+
boolean is_temporary;
|
63
|
+
oci8_svcctx_t *svcctx = lob->svcctx;
|
64
|
+
|
65
|
+
if (svcctx != NULL
|
66
|
+
&& OCILobIsTemporary(oci8_envhp, oci8_errhp, lob->base.hp.lob, &is_temporary) == OCI_SUCCESS
|
67
|
+
&& is_temporary) {
|
68
|
+
|
69
|
+
#ifdef NATIVE_THREAD_WITH_GVL
|
70
|
+
oci8_temp_lob_t *temp_lob = ALLOC(oci8_temp_lob_t);
|
71
|
+
|
72
|
+
temp_lob->next = svcctx->temp_lobs;
|
73
|
+
temp_lob->lob = lob->base.hp.lob;
|
74
|
+
svcctx->temp_lobs = temp_lob;
|
75
|
+
lob->base.type = 0;
|
76
|
+
lob->base.closed = 1;
|
77
|
+
lob->base.hp.ptr = NULL;
|
78
|
+
#else
|
79
|
+
/* FIXME: This may stall the GC. */
|
80
|
+
OCILobFreeTemporary(svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob);
|
81
|
+
#endif
|
82
|
+
}
|
83
|
+
lob->svcctx = NULL;
|
84
|
+
}
|
85
|
+
|
86
|
+
static const oci8_handle_data_type_t oci8_lob_data_type = {
|
87
|
+
{
|
88
|
+
"OCI8::LOB",
|
89
|
+
{
|
90
|
+
NULL,
|
91
|
+
NULL,
|
92
|
+
NULL,
|
93
|
+
},
|
94
|
+
&oci8_handle_data_type.rb_data_type, NULL,
|
95
|
+
},
|
96
|
+
NULL,
|
97
|
+
sizeof(oci8_lob_t),
|
98
|
+
};
|
99
|
+
|
100
|
+
static VALUE oci8_lob_alloc(VALUE klass)
|
101
|
+
{
|
102
|
+
rb_raise(rb_eNameError, "private method `new' called for %s:Class", rb_class2name(klass));
|
103
|
+
}
|
104
|
+
|
105
|
+
static const oci8_handle_data_type_t oci8_clob_data_type = {
|
106
|
+
{
|
107
|
+
"OCI8::CLOB",
|
108
|
+
{
|
109
|
+
(RUBY_DATA_FUNC)oci8_lob_mark,
|
110
|
+
oci8_handle_cleanup,
|
111
|
+
oci8_handle_size,
|
112
|
+
},
|
113
|
+
&oci8_lob_data_type.rb_data_type, NULL,
|
114
|
+
#ifdef RUBY_TYPED_WB_PROTECTED
|
115
|
+
RUBY_TYPED_WB_PROTECTED,
|
116
|
+
#endif
|
117
|
+
},
|
118
|
+
oci8_lob_free,
|
119
|
+
sizeof(oci8_lob_t),
|
120
|
+
};
|
121
|
+
|
122
|
+
static VALUE oci8_clob_alloc(VALUE klass)
|
123
|
+
{
|
124
|
+
return oci8_allocate_typeddata(klass, &oci8_clob_data_type);
|
125
|
+
}
|
126
|
+
|
127
|
+
static const oci8_handle_data_type_t oci8_nclob_data_type = {
|
128
|
+
{
|
129
|
+
"OCI8::NCLOB",
|
130
|
+
{
|
131
|
+
(RUBY_DATA_FUNC)oci8_lob_mark,
|
132
|
+
oci8_handle_cleanup,
|
133
|
+
oci8_handle_size,
|
134
|
+
},
|
135
|
+
&oci8_lob_data_type.rb_data_type, NULL,
|
136
|
+
#ifdef RUBY_TYPED_WB_PROTECTED
|
137
|
+
RUBY_TYPED_WB_PROTECTED,
|
138
|
+
#endif
|
139
|
+
},
|
140
|
+
oci8_lob_free,
|
141
|
+
sizeof(oci8_lob_t),
|
142
|
+
};
|
143
|
+
|
144
|
+
static VALUE oci8_nclob_alloc(VALUE klass)
|
145
|
+
{
|
146
|
+
return oci8_allocate_typeddata(klass, &oci8_nclob_data_type);
|
147
|
+
}
|
148
|
+
|
149
|
+
static const oci8_handle_data_type_t oci8_blob_data_type = {
|
150
|
+
{
|
151
|
+
"OCI8::BLOB",
|
152
|
+
{
|
153
|
+
(RUBY_DATA_FUNC)oci8_lob_mark,
|
154
|
+
oci8_handle_cleanup,
|
155
|
+
oci8_handle_size,
|
156
|
+
},
|
157
|
+
&oci8_lob_data_type.rb_data_type, NULL,
|
158
|
+
#ifdef RUBY_TYPED_WB_PROTECTED
|
159
|
+
RUBY_TYPED_WB_PROTECTED,
|
160
|
+
#endif
|
161
|
+
},
|
162
|
+
oci8_lob_free,
|
163
|
+
sizeof(oci8_lob_t),
|
164
|
+
};
|
165
|
+
|
166
|
+
static VALUE oci8_blob_alloc(VALUE klass)
|
167
|
+
{
|
168
|
+
return oci8_allocate_typeddata(klass, &oci8_blob_data_type);
|
169
|
+
}
|
170
|
+
|
171
|
+
static const oci8_handle_data_type_t oci8_bfile_data_type = {
|
172
|
+
{
|
173
|
+
"OCI8::BFILE",
|
174
|
+
{
|
175
|
+
(RUBY_DATA_FUNC)oci8_lob_mark,
|
176
|
+
oci8_handle_cleanup,
|
177
|
+
oci8_handle_size,
|
178
|
+
},
|
179
|
+
&oci8_lob_data_type.rb_data_type, NULL,
|
180
|
+
#ifdef RUBY_TYPED_WB_PROTECTED
|
181
|
+
RUBY_TYPED_WB_PROTECTED,
|
182
|
+
#endif
|
183
|
+
},
|
184
|
+
oci8_lob_free,
|
185
|
+
sizeof(oci8_lob_t),
|
186
|
+
};
|
187
|
+
|
188
|
+
static VALUE oci8_bfile_alloc(VALUE klass)
|
189
|
+
{
|
190
|
+
return oci8_allocate_typeddata(klass, &oci8_bfile_data_type);
|
191
|
+
}
|
192
|
+
|
49
193
|
static VALUE oci8_make_lob(VALUE klass, oci8_svcctx_t *svcctx, OCILobLocator *s)
|
50
194
|
{
|
51
195
|
oci8_lob_t *lob;
|
@@ -53,7 +197,7 @@ static VALUE oci8_make_lob(VALUE klass, oci8_svcctx_t *svcctx, OCILobLocator *s)
|
|
53
197
|
VALUE lob_obj;
|
54
198
|
|
55
199
|
lob_obj = rb_class_new_instance(1, &svcctx->base.self, klass);
|
56
|
-
lob =
|
200
|
+
lob = TO_LOB(lob_obj);
|
57
201
|
/* If 's' is a temporary lob, use OCILobLocatorAssign instead. */
|
58
202
|
chker2(OCILobIsTemporary(oci8_envhp, oci8_errhp, s, &is_temp), &svcctx->base);
|
59
203
|
if (is_temp)
|
@@ -87,7 +231,11 @@ VALUE oci8_make_bfile(oci8_svcctx_t *svcctx, OCILobLocator *s)
|
|
87
231
|
|
88
232
|
static void oci8_assign_lob(VALUE klass, oci8_svcctx_t *svcctx, VALUE lob, OCILobLocator **dest)
|
89
233
|
{
|
90
|
-
oci8_base_t *base =
|
234
|
+
oci8_base_t *base = oci8_check_typeddata(lob, &oci8_lob_data_type, 1);
|
235
|
+
if (!rb_obj_is_kind_of(lob, klass)) {
|
236
|
+
rb_raise(rb_eTypeError, "wrong argument %s (expect %s)",
|
237
|
+
rb_obj_classname(lob), rb_class2name(klass));
|
238
|
+
}
|
91
239
|
chker2(OCILobLocatorAssign_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, base->hp.lob, dest), base);
|
92
240
|
}
|
93
241
|
|
@@ -111,46 +259,6 @@ void oci8_assign_bfile(oci8_svcctx_t *svcctx, VALUE lob, OCILobLocator **dest)
|
|
111
259
|
oci8_assign_lob(cOCI8BFILE, svcctx, lob, dest);
|
112
260
|
}
|
113
261
|
|
114
|
-
static void oci8_lob_mark(oci8_base_t *base)
|
115
|
-
{
|
116
|
-
oci8_lob_t *lob = (oci8_lob_t *)base;
|
117
|
-
if (lob->svcctx != NULL) {
|
118
|
-
rb_gc_mark(lob->svcctx->base.self);
|
119
|
-
}
|
120
|
-
}
|
121
|
-
|
122
|
-
static void oci8_lob_free(oci8_base_t *base)
|
123
|
-
{
|
124
|
-
oci8_lob_t *lob = (oci8_lob_t *)base;
|
125
|
-
boolean is_temporary;
|
126
|
-
oci8_svcctx_t *svcctx = lob->svcctx;
|
127
|
-
|
128
|
-
if (svcctx != NULL
|
129
|
-
&& OCILobIsTemporary(oci8_envhp, oci8_errhp, lob->base.hp.lob, &is_temporary) == OCI_SUCCESS
|
130
|
-
&& is_temporary) {
|
131
|
-
|
132
|
-
#ifdef HAVE_RB_THREAD_BLOCKING_REGION
|
133
|
-
oci8_temp_lob_t *temp_lob = ALLOC(oci8_temp_lob_t);
|
134
|
-
|
135
|
-
temp_lob->next = svcctx->temp_lobs;
|
136
|
-
temp_lob->lob = lob->base.hp.lob;
|
137
|
-
svcctx->temp_lobs = temp_lob;
|
138
|
-
lob->base.type = 0;
|
139
|
-
lob->base.hp.ptr = NULL;
|
140
|
-
#else
|
141
|
-
/* FIXME: This may stall the GC. */
|
142
|
-
OCILobFreeTemporary(svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob);
|
143
|
-
#endif
|
144
|
-
}
|
145
|
-
lob->svcctx = NULL;
|
146
|
-
}
|
147
|
-
|
148
|
-
static oci8_base_vtable_t oci8_lob_vtable = {
|
149
|
-
oci8_lob_mark,
|
150
|
-
oci8_lob_free,
|
151
|
-
sizeof(oci8_lob_t),
|
152
|
-
};
|
153
|
-
|
154
262
|
static ub4 oci8_lob_get_length(oci8_lob_t *lob)
|
155
263
|
{
|
156
264
|
oci8_svcctx_t *svcctx = check_svcctx(lob);
|
@@ -197,31 +305,58 @@ static void bfile_close(oci8_lob_t *lob)
|
|
197
305
|
/*
|
198
306
|
* Document-class: OCI8::LOB
|
199
307
|
*
|
200
|
-
* This is the abstract base class of large-object data types; BFILE, BLOB, CLOB and NCLOB.
|
308
|
+
* This is the abstract base class of large-object data types; {BFILE}, {BLOB}, {CLOB} and {NCLOB}.
|
201
309
|
*
|
202
310
|
*/
|
203
311
|
|
204
312
|
/*
|
205
313
|
* Document-class: OCI8::CLOB
|
206
314
|
*
|
315
|
+
* This class is a ruby-side class of {Oracle NCLOB datatype}[http://docs.oracle.com/database/121/SQLRF/sql_elements001.htm#sthref175].
|
207
316
|
*/
|
208
317
|
|
209
318
|
/*
|
210
319
|
* Document-class: OCI8::NCLOB
|
211
320
|
*
|
321
|
+
* This class is a ruby-side class of {Oracle CLOB datatype}[http://docs.oracle.com/database/121/SQLRF/sql_elements001.htm#sthref172].
|
212
322
|
*/
|
213
323
|
|
214
324
|
/*
|
215
325
|
* Document-class: OCI8::BLOB
|
216
326
|
*
|
327
|
+
* This class is a ruby-side class of {Oracle BLOB datatype}[http://docs.oracle.com/database/121/SQLRF/sql_elements001.htm#sthref168].
|
328
|
+
*
|
217
329
|
*/
|
218
330
|
|
219
331
|
/*
|
220
332
|
* Document-class: OCI8::BFILE
|
221
333
|
*
|
222
|
-
*
|
223
|
-
*
|
224
|
-
*
|
334
|
+
* This class is a ruby-side class of {Oracle BFILE datatype}[http://docs.oracle.com/database/121/SQLRF/sql_elements001.htm#sthref164].
|
335
|
+
* It is a read-only {LOB}. You cannot change the contents.
|
336
|
+
*
|
337
|
+
* You can read files on the server-side as follows:
|
338
|
+
*
|
339
|
+
* 1. Connect to the Oracle server as a user who has CREATE DIRECTORY privilege.
|
340
|
+
*
|
341
|
+
* # create a directory object on the Oracle server.
|
342
|
+
* CREATE DIRECTORY file_storage_dir AS '/opt/file_storage';
|
343
|
+
* # grant a privilege to read files on file_storage_dir directory to a user.
|
344
|
+
* GRANT READ ON DIRECTORY file_storage_dir TO username;
|
345
|
+
*
|
346
|
+
* 2. Create a file 'hello_world.txt' in the directory '/opt/file_storage' on the server filesystem.
|
347
|
+
*
|
348
|
+
* echo 'Hello World!' > /opt/file_storage/hello_world.txt
|
349
|
+
*
|
350
|
+
* 3. Read the file by ruby-oci8.
|
351
|
+
*
|
352
|
+
* require 'oci8'
|
353
|
+
* # The user must have 'READ ON DIRECTORY file_storage_dir' privilege.
|
354
|
+
* conn = OCI8.new('username/password')
|
355
|
+
*
|
356
|
+
* # The second argument is usually an uppercase string unless the directory
|
357
|
+
* # object is explicitly created as *double-quoted* lowercase characters.
|
358
|
+
* bfile = OCI8::BFILE.new(conn, 'FILE_STORAGE_DIR', 'hello_world.txt')
|
359
|
+
* bfile.read # => "Hello World!\n"
|
225
360
|
*/
|
226
361
|
|
227
362
|
/*
|
@@ -231,15 +366,15 @@ static void bfile_close(oci8_lob_t *lob)
|
|
231
366
|
*/
|
232
367
|
static VALUE oci8_lob_close(VALUE self)
|
233
368
|
{
|
234
|
-
oci8_lob_t *lob =
|
369
|
+
oci8_lob_t *lob = TO_LOB(self);
|
235
370
|
lob_close(lob);
|
236
|
-
oci8_base_free(
|
371
|
+
oci8_base_free(&lob->base);
|
237
372
|
return self;
|
238
373
|
}
|
239
374
|
|
240
375
|
static VALUE oci8_lob_do_initialize(int argc, VALUE *argv, VALUE self, ub1 csfrm, ub1 lobtype)
|
241
376
|
{
|
242
|
-
oci8_lob_t *lob =
|
377
|
+
oci8_lob_t *lob = TO_LOB(self);
|
243
378
|
VALUE svc;
|
244
379
|
VALUE val;
|
245
380
|
oci8_svcctx_t *svcctx;
|
@@ -256,8 +391,9 @@ static VALUE oci8_lob_do_initialize(int argc, VALUE *argv, VALUE self, ub1 csfrm
|
|
256
391
|
lob->csfrm = csfrm;
|
257
392
|
lob->lobtype = lobtype;
|
258
393
|
lob->state = S_NO_OPEN_CLOSE;
|
259
|
-
oci8_link_to_parent(
|
394
|
+
oci8_link_to_parent(&lob->base, &svcctx->base);
|
260
395
|
lob->svcctx = svcctx;
|
396
|
+
RB_OBJ_WRITTEN(self, Qundef, svc);
|
261
397
|
if (!NIL_P(val)) {
|
262
398
|
OCI8StringValue(val);
|
263
399
|
chker2(OCILobCreateTemporary_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, 0, csfrm, lobtype, TRUE, OCI_DURATION_SESSION),
|
@@ -346,7 +482,7 @@ static VALUE oci8_blob_initialize(int argc, VALUE *argv, VALUE self)
|
|
346
482
|
*/
|
347
483
|
static VALUE oci8_lob_set_char_width(VALUE self, VALUE vsize)
|
348
484
|
{
|
349
|
-
oci8_lob_t *lob =
|
485
|
+
oci8_lob_t *lob = TO_LOB(self);
|
350
486
|
int size;
|
351
487
|
|
352
488
|
size = NUM2INT(vsize); /* 1 */
|
@@ -364,7 +500,7 @@ static VALUE oci8_lob_set_char_width(VALUE self, VALUE vsize)
|
|
364
500
|
*/
|
365
501
|
static VALUE oci8_lob_available_p(VALUE self)
|
366
502
|
{
|
367
|
-
oci8_lob_t *lob =
|
503
|
+
oci8_lob_t *lob = TO_LOB(self);
|
368
504
|
boolean is_initialized;
|
369
505
|
|
370
506
|
chker2(OCILobLocatorIsInit(oci8_envhp, oci8_errhp, lob->base.hp.lob, &is_initialized),
|
@@ -381,7 +517,7 @@ static VALUE oci8_lob_available_p(VALUE self)
|
|
381
517
|
*/
|
382
518
|
static VALUE oci8_lob_get_size(VALUE self)
|
383
519
|
{
|
384
|
-
return UB4_TO_NUM(oci8_lob_get_length(
|
520
|
+
return UB4_TO_NUM(oci8_lob_get_length(TO_LOB(self)));
|
385
521
|
}
|
386
522
|
|
387
523
|
/*
|
@@ -393,7 +529,7 @@ static VALUE oci8_lob_get_size(VALUE self)
|
|
393
529
|
*/
|
394
530
|
static VALUE oci8_lob_get_pos(VALUE self)
|
395
531
|
{
|
396
|
-
oci8_lob_t *lob =
|
532
|
+
oci8_lob_t *lob = TO_LOB(self);
|
397
533
|
return UB4_TO_NUM(lob->pos);
|
398
534
|
}
|
399
535
|
|
@@ -404,7 +540,7 @@ static VALUE oci8_lob_get_pos(VALUE self)
|
|
404
540
|
*/
|
405
541
|
static VALUE oci8_lob_eof_p(VALUE self)
|
406
542
|
{
|
407
|
-
oci8_lob_t *lob =
|
543
|
+
oci8_lob_t *lob = TO_LOB(self);
|
408
544
|
if (oci8_lob_get_length(lob) < lob->pos)
|
409
545
|
return Qfalse;
|
410
546
|
else
|
@@ -427,7 +563,7 @@ static VALUE oci8_lob_eof_p(VALUE self)
|
|
427
563
|
*/
|
428
564
|
static VALUE oci8_lob_seek(int argc, VALUE *argv, VALUE self)
|
429
565
|
{
|
430
|
-
oci8_lob_t *lob =
|
566
|
+
oci8_lob_t *lob = TO_LOB(self);
|
431
567
|
VALUE position, whence;
|
432
568
|
|
433
569
|
rb_scan_args(argc, argv, "11", &position, &whence);
|
@@ -456,7 +592,7 @@ static VALUE oci8_lob_seek(int argc, VALUE *argv, VALUE self)
|
|
456
592
|
*/
|
457
593
|
static VALUE oci8_lob_rewind(VALUE self)
|
458
594
|
{
|
459
|
-
oci8_lob_t *lob =
|
595
|
+
oci8_lob_t *lob = TO_LOB(self);
|
460
596
|
lob->pos = 0;
|
461
597
|
return self;
|
462
598
|
}
|
@@ -465,14 +601,14 @@ static VALUE oci8_lob_rewind(VALUE self)
|
|
465
601
|
* call-seq:
|
466
602
|
* truncate(length)
|
467
603
|
*
|
468
|
-
*
|
469
|
-
*
|
470
|
-
* @param [Integer] length
|
604
|
+
* @param [Integer] length length in characters if +self+ is a {CLOB} or a {NCLOB}.
|
605
|
+
* length in bytes if +self+ is a {BLOB} or a {BFILE}.
|
471
606
|
* @return [self]
|
607
|
+
* @see #size=
|
472
608
|
*/
|
473
609
|
static VALUE oci8_lob_truncate(VALUE self, VALUE len)
|
474
610
|
{
|
475
|
-
oci8_lob_t *lob =
|
611
|
+
oci8_lob_t *lob = TO_LOB(self);
|
476
612
|
oci8_svcctx_t *svcctx = check_svcctx(lob);
|
477
613
|
|
478
614
|
lob_open(lob);
|
@@ -482,13 +618,13 @@ static VALUE oci8_lob_truncate(VALUE self, VALUE len)
|
|
482
618
|
}
|
483
619
|
|
484
620
|
/*
|
485
|
-
*
|
486
|
-
* size = length
|
621
|
+
* @overload size=(length)
|
487
622
|
*
|
488
623
|
* Changes the lob size to the given <i>length</i>.
|
489
624
|
*
|
490
|
-
* @param [Integer] length
|
491
|
-
*
|
625
|
+
* @param [Integer] length length in characters if +self+ is a {CLOB} or a {NCLOB}.
|
626
|
+
* length in bytes if +self+ is a {BLOB} or a {BFILE}.
|
627
|
+
* @see #truncate
|
492
628
|
*/
|
493
629
|
static VALUE oci8_lob_set_size(VALUE self, VALUE len)
|
494
630
|
{
|
@@ -497,29 +633,37 @@ static VALUE oci8_lob_set_size(VALUE self, VALUE len)
|
|
497
633
|
}
|
498
634
|
|
499
635
|
/*
|
500
|
-
*
|
501
|
-
* read(length = nil)
|
636
|
+
* @overload read
|
502
637
|
*
|
503
|
-
*
|
504
|
-
*
|
505
|
-
*
|
638
|
+
*
|
639
|
+
*
|
640
|
+
* @param [Integer] length number of characters if +self+ is a {CLOB} or a {NCLOB}.
|
641
|
+
* number of bytes if +self+ is a {BLOB} or a {BFILE}.
|
642
|
+
* @return [String or nil] data read. <code>nil</code> means it
|
643
|
+
* met EOF at beginning. It returns an empty string '' as a special exception
|
644
|
+
* when <i>length</i> is <code>nil</code> and the lob is empty.
|
506
645
|
*
|
507
|
-
*
|
508
|
-
* met EOF at beginning. As a special exception, when <i>length</i> is
|
509
|
-
* <code>nil</code> and the lob length is zero, it returns an empty string ''.
|
646
|
+
* @overload read(length)
|
510
647
|
*
|
511
|
-
*
|
512
|
-
*
|
648
|
+
* Reads <i>length</i> characters for {CLOB} and {NCLOB} or <i>length</i>
|
649
|
+
* bytes for {BLOB} and {BFILE} from the current position.
|
650
|
+
* If <i>length</i> is <code>nil</code>, it reads data until EOF.
|
651
|
+
*
|
652
|
+
* @param [Integer] length number of characters if +self+ is a {CLOB} or a {NCLOB}.
|
653
|
+
* number of bytes if +self+ is a {BLOB} or a {BFILE}.
|
654
|
+
* @return [String or nil] data read. <code>nil</code> means it
|
655
|
+
* met EOF at beginning. It returns an empty string '' as a special exception
|
656
|
+
* when <i>length</i> is <code>nil</code> and the lob is empty.
|
513
657
|
*/
|
514
658
|
static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
|
515
659
|
{
|
516
|
-
oci8_lob_t *lob =
|
660
|
+
oci8_lob_t *lob = TO_LOB(self);
|
517
661
|
oci8_svcctx_t *svcctx = check_svcctx(lob);
|
518
662
|
ub4 length;
|
519
663
|
ub4 nchar;
|
664
|
+
long nbyte;
|
520
665
|
ub4 amt;
|
521
666
|
sword rv;
|
522
|
-
char buf[8192];
|
523
667
|
size_t buf_size_in_char;
|
524
668
|
VALUE size;
|
525
669
|
VALUE v = rb_ary_new();
|
@@ -539,9 +683,13 @@ static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
|
|
539
683
|
if (nchar > length)
|
540
684
|
nchar = length;
|
541
685
|
}
|
686
|
+
nbyte = oci8_nls_ratio * (long)nchar;
|
542
687
|
amt = nchar;
|
543
|
-
buf_size_in_char =
|
688
|
+
buf_size_in_char = nbyte / lob->char_width;
|
544
689
|
do {
|
690
|
+
VALUE strbuf = rb_str_buf_new(nbyte);
|
691
|
+
char *buf = RSTRING_PTR(strbuf);
|
692
|
+
|
545
693
|
if (lob->state == S_BFILE_CLOSE) {
|
546
694
|
rv = OCILobFileOpen_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, OCI_FILE_READONLY);
|
547
695
|
if (rv == OCI_ERROR && oci8_get_error_code(oci8_errhp) == 22290) {
|
@@ -564,8 +712,8 @@ static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
|
|
564
712
|
lob->state = S_BFILE_OPEN;
|
565
713
|
}
|
566
714
|
/* initialize buf in zeros everytime to check a nul characters. */
|
567
|
-
memset(buf, 0,
|
568
|
-
rv = OCILobRead_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &amt, lob->pos + 1, buf,
|
715
|
+
memset(buf, 0, nbyte);
|
716
|
+
rv = OCILobRead_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &amt, lob->pos + 1, buf, nbyte, NULL, NULL, 0, lob->csfrm);
|
569
717
|
svcctx->suppress_free_temp_lobs = 0;
|
570
718
|
switch (rv) {
|
571
719
|
case OCI_SUCCESS:
|
@@ -594,7 +742,7 @@ static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
|
|
594
742
|
* amt is increaded until a nul character to know the actually
|
595
743
|
* read size.
|
596
744
|
*/
|
597
|
-
while (amt <
|
745
|
+
while (amt < nbyte && buf[amt] != '\0') {
|
598
746
|
amt++;
|
599
747
|
}
|
600
748
|
|
@@ -604,17 +752,23 @@ static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
|
|
604
752
|
if (amt > buf_size_in_char)
|
605
753
|
rb_raise(eOCIException, "Too large buffer fetched or you set too large size of a character.");
|
606
754
|
amt *= lob->char_width;
|
607
|
-
|
755
|
+
rb_str_set_len(strbuf, amt);
|
756
|
+
rb_ary_push(v, strbuf);
|
608
757
|
} while (rv == OCI_NEED_DATA);
|
609
758
|
lob->pos += nchar;
|
610
759
|
if (nchar == length) {
|
611
760
|
lob_close(lob);
|
612
761
|
bfile_close(lob);
|
613
762
|
}
|
614
|
-
|
763
|
+
switch (RARRAY_LEN(v)) {
|
764
|
+
case 0:
|
615
765
|
return Qnil;
|
766
|
+
case 1:
|
767
|
+
v = RARRAY_PTR(v)[0];
|
768
|
+
break;
|
769
|
+
default:
|
770
|
+
v = rb_ary_join(v, Qnil);
|
616
771
|
}
|
617
|
-
v = rb_ary_join(v, Qnil);
|
618
772
|
OBJ_TAINT(v);
|
619
773
|
if (lob->lobtype == OCI_TEMP_CLOB) {
|
620
774
|
/* set encoding */
|
@@ -627,17 +781,17 @@ static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
|
|
627
781
|
}
|
628
782
|
|
629
783
|
/*
|
630
|
-
*
|
631
|
-
* write(data)
|
784
|
+
* @overload write(data)
|
632
785
|
*
|
633
|
-
* Writes
|
786
|
+
* Writes +data+ to LOB.
|
634
787
|
*
|
635
788
|
* @param [String] data
|
636
|
-
* @return [Integer]
|
789
|
+
* @return [Integer] number of characters written if +self+ is a {CLOB} or a {NCLOB}.
|
790
|
+
* number of bytes written if +self+ is a {BLOB} or a {BFILE}.
|
637
791
|
*/
|
638
792
|
static VALUE oci8_lob_write(VALUE self, VALUE data)
|
639
793
|
{
|
640
|
-
oci8_lob_t *lob =
|
794
|
+
oci8_lob_t *lob = TO_LOB(self);
|
641
795
|
oci8_svcctx_t *svcctx = check_svcctx(lob);
|
642
796
|
ub4 amt;
|
643
797
|
|
@@ -666,7 +820,7 @@ static VALUE oci8_lob_write(VALUE self, VALUE data)
|
|
666
820
|
*/
|
667
821
|
static VALUE oci8_lob_get_sync(VALUE self)
|
668
822
|
{
|
669
|
-
oci8_lob_t *lob =
|
823
|
+
oci8_lob_t *lob = TO_LOB(self);
|
670
824
|
return (lob->state == S_NO_OPEN_CLOSE) ? Qtrue : Qfalse;
|
671
825
|
}
|
672
826
|
|
@@ -676,7 +830,7 @@ static VALUE oci8_lob_get_sync(VALUE self)
|
|
676
830
|
*/
|
677
831
|
static VALUE oci8_lob_set_sync(VALUE self, VALUE b)
|
678
832
|
{
|
679
|
-
oci8_lob_t *lob =
|
833
|
+
oci8_lob_t *lob = TO_LOB(self);
|
680
834
|
if (RTEST(b)) {
|
681
835
|
lob_close(lob);
|
682
836
|
lob->state = S_NO_OPEN_CLOSE;
|
@@ -693,7 +847,7 @@ static VALUE oci8_lob_set_sync(VALUE self, VALUE b)
|
|
693
847
|
*/
|
694
848
|
static VALUE oci8_lob_flush(VALUE self)
|
695
849
|
{
|
696
|
-
oci8_lob_t *lob =
|
850
|
+
oci8_lob_t *lob = TO_LOB(self);
|
697
851
|
lob_close(lob);
|
698
852
|
return self;
|
699
853
|
}
|
@@ -701,12 +855,12 @@ static VALUE oci8_lob_flush(VALUE self)
|
|
701
855
|
/*
|
702
856
|
* Returns the chunk size of a LOB.
|
703
857
|
*
|
704
|
-
* @see http://docs.oracle.com/
|
858
|
+
* @see http://docs.oracle.com/database/121/ARPLS/d_lob.htm#ARPLS66706 DBMS_LOB.GETCHUNKSIZE
|
705
859
|
* @return [Integer]
|
706
860
|
*/
|
707
861
|
static VALUE oci8_lob_get_chunk_size(VALUE self)
|
708
862
|
{
|
709
|
-
oci8_lob_t *lob =
|
863
|
+
oci8_lob_t *lob = TO_LOB(self);
|
710
864
|
oci8_svcctx_t *svcctx = check_svcctx(lob);
|
711
865
|
ub4 len;
|
712
866
|
|
@@ -717,7 +871,7 @@ static VALUE oci8_lob_get_chunk_size(VALUE self)
|
|
717
871
|
|
718
872
|
static VALUE oci8_lob_clone(VALUE self)
|
719
873
|
{
|
720
|
-
oci8_lob_t *lob =
|
874
|
+
oci8_lob_t *lob = TO_LOB(self);
|
721
875
|
oci8_lob_t *newlob;
|
722
876
|
VALUE newobj = lob->svcctx ? lob->svcctx->base.self : Qnil;
|
723
877
|
boolean is_temporary;
|
@@ -749,7 +903,7 @@ static void oci8_bfile_get_name(VALUE self, VALUE *dir_alias_p, VALUE *filename_
|
|
749
903
|
need_get = 1;
|
750
904
|
}
|
751
905
|
if (need_get) {
|
752
|
-
oci8_lob_t *lob =
|
906
|
+
oci8_lob_t *lob = TO_LOB(self);
|
753
907
|
char d_buf[31];
|
754
908
|
ub2 d_length = sizeof(d_buf);
|
755
909
|
char f_buf[256];
|
@@ -774,7 +928,7 @@ static void oci8_bfile_get_name(VALUE self, VALUE *dir_alias_p, VALUE *filename_
|
|
774
928
|
|
775
929
|
static void oci8_bfile_set_name(VALUE self, VALUE dir_alias, VALUE filename)
|
776
930
|
{
|
777
|
-
oci8_lob_t *lob =
|
931
|
+
oci8_lob_t *lob = TO_LOB(self);
|
778
932
|
|
779
933
|
bfile_close(lob);
|
780
934
|
if (RSTRING_LEN(dir_alias) > UB2MAXVAL) {
|
@@ -790,21 +944,20 @@ static void oci8_bfile_set_name(VALUE self, VALUE dir_alias, VALUE filename)
|
|
790
944
|
}
|
791
945
|
|
792
946
|
/*
|
793
|
-
*
|
794
|
-
* initialize(conn, dir_alias = nil, filename = nil)
|
947
|
+
* @overload initialize(conn, directory = nil, filename = nil)
|
795
948
|
*
|
796
949
|
* Creates a BFILE object.
|
797
|
-
* This is correspond to {
|
950
|
+
* This is correspond to {BFILENAME}[https://docs.oracle.com/database/121/SQLRF/functions020.htm].
|
798
951
|
*
|
799
952
|
* @param [OCI8] conn
|
800
|
-
* @param [String]
|
801
|
-
* {http://docs.oracle.com/
|
953
|
+
* @param [String] directory a directory object created by
|
954
|
+
* {"CREATE DIRECTORY"}[http://docs.oracle.com/database/121/SQLRF/statements_5008.htm].
|
802
955
|
* @param [String] filename
|
803
956
|
* @return [OCI8::BFILE]
|
804
957
|
*/
|
805
958
|
static VALUE oci8_bfile_initialize(int argc, VALUE *argv, VALUE self)
|
806
959
|
{
|
807
|
-
oci8_lob_t *lob =
|
960
|
+
oci8_lob_t *lob = TO_LOB(self);
|
808
961
|
VALUE svc;
|
809
962
|
VALUE dir_alias;
|
810
963
|
VALUE filename;
|
@@ -828,12 +981,14 @@ static VALUE oci8_bfile_initialize(int argc, VALUE *argv, VALUE self)
|
|
828
981
|
OCI8SafeStringValue(filename);
|
829
982
|
oci8_bfile_set_name(self, dir_alias, filename);
|
830
983
|
}
|
831
|
-
oci8_link_to_parent(
|
984
|
+
oci8_link_to_parent(&lob->base, &svcctx->base);
|
832
985
|
lob->svcctx = svcctx;
|
833
986
|
return Qnil;
|
834
987
|
}
|
835
988
|
|
836
989
|
/*
|
990
|
+
* @overload dir_alias
|
991
|
+
*
|
837
992
|
* Returns the directory object name.
|
838
993
|
*
|
839
994
|
* @return [String]
|
@@ -847,6 +1002,8 @@ static VALUE oci8_bfile_get_dir_alias(VALUE self)
|
|
847
1002
|
}
|
848
1003
|
|
849
1004
|
/*
|
1005
|
+
* @overload filename
|
1006
|
+
*
|
850
1007
|
* Returns the file name.
|
851
1008
|
*
|
852
1009
|
* @return [String]
|
@@ -860,12 +1017,11 @@ static VALUE oci8_bfile_get_filename(VALUE self)
|
|
860
1017
|
}
|
861
1018
|
|
862
1019
|
/*
|
863
|
-
*
|
864
|
-
* dir_alias = name
|
1020
|
+
* @overload dir_alias=(dir_alias)
|
865
1021
|
*
|
866
1022
|
* Changes the directory object name.
|
867
1023
|
*
|
868
|
-
* @param [String]
|
1024
|
+
* @param [String] dir_alias
|
869
1025
|
*/
|
870
1026
|
static VALUE oci8_bfile_set_dir_alias(VALUE self, VALUE dir_alias)
|
871
1027
|
{
|
@@ -879,12 +1035,11 @@ static VALUE oci8_bfile_set_dir_alias(VALUE self, VALUE dir_alias)
|
|
879
1035
|
}
|
880
1036
|
|
881
1037
|
/*
|
882
|
-
*
|
883
|
-
* filename = name
|
1038
|
+
* @overload filename=(filename)
|
884
1039
|
*
|
885
1040
|
* Changes the file name.
|
886
1041
|
*
|
887
|
-
* @param [String]
|
1042
|
+
* @param [String] filename
|
888
1043
|
*/
|
889
1044
|
static VALUE oci8_bfile_set_filename(VALUE self, VALUE filename)
|
890
1045
|
{
|
@@ -898,13 +1053,13 @@ static VALUE oci8_bfile_set_filename(VALUE self, VALUE filename)
|
|
898
1053
|
}
|
899
1054
|
|
900
1055
|
/*
|
901
|
-
*
|
1056
|
+
* @overload exists?
|
902
1057
|
*
|
903
|
-
*
|
1058
|
+
* Returns <code>true</code> when the BFILE exists on the server's operating system.
|
904
1059
|
*/
|
905
1060
|
static VALUE oci8_bfile_exists_p(VALUE self)
|
906
1061
|
{
|
907
|
-
oci8_lob_t *lob =
|
1062
|
+
oci8_lob_t *lob = TO_LOB(self);
|
908
1063
|
oci8_svcctx_t *svcctx = check_svcctx(lob);
|
909
1064
|
boolean flag;
|
910
1065
|
|
@@ -914,38 +1069,10 @@ static VALUE oci8_bfile_exists_p(VALUE self)
|
|
914
1069
|
}
|
915
1070
|
|
916
1071
|
/*
|
917
|
-
*
|
918
|
-
*
|
919
|
-
* call-seq:
|
920
|
-
* truncate(length)
|
921
|
-
*
|
922
|
-
* Raises <code>RuntimeError</code>.
|
923
|
-
*
|
924
|
-
* @raise [RuntimeError] cannot modify a read-only BFILE object
|
925
|
-
*/
|
926
|
-
|
927
|
-
/*
|
928
|
-
* Document-method: OCI8::BFILE#size=
|
929
|
-
*
|
930
|
-
* call-seq:
|
931
|
-
* size = length
|
932
|
-
*
|
933
|
-
* Raises <code>RuntimeError</code>.
|
934
|
-
*
|
935
|
-
* @raise [RuntimeError] cannot modify a read-only BFILE object
|
936
|
-
*/
|
937
|
-
|
938
|
-
/*
|
939
|
-
* Document-method: OCI8::BFILE#write
|
940
|
-
*
|
941
|
-
* call-seq:
|
942
|
-
* write(data)
|
943
|
-
*
|
944
|
-
* Raises <code>RuntimeError</code>.
|
1072
|
+
* Raises <code>RuntimeError</code> always.
|
945
1073
|
*
|
946
1074
|
* @raise [RuntimeError] cannot modify a read-only BFILE object
|
947
1075
|
*/
|
948
|
-
|
949
1076
|
static VALUE oci8_bfile_error(VALUE self, VALUE dummy)
|
950
1077
|
{
|
951
1078
|
rb_raise(rb_eRuntimeError, "cannot modify a read-only BFILE object");
|
@@ -956,9 +1083,9 @@ static VALUE oci8_bfile_error(VALUE self, VALUE dummy)
|
|
956
1083
|
*/
|
957
1084
|
|
958
1085
|
typedef struct {
|
959
|
-
|
1086
|
+
oci8_bind_data_type_t bind;
|
960
1087
|
VALUE *klass;
|
961
|
-
}
|
1088
|
+
} oci8_bind_lob_data_type_t;
|
962
1089
|
|
963
1090
|
static VALUE bind_lob_get(oci8_bind_t *obind, void *data, void *null_struct)
|
964
1091
|
{
|
@@ -969,13 +1096,11 @@ static VALUE bind_lob_get(oci8_bind_t *obind, void *data, void *null_struct)
|
|
969
1096
|
static void bind_lob_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
|
970
1097
|
{
|
971
1098
|
oci8_hp_obj_t *oho = (oci8_hp_obj_t *)data;
|
972
|
-
const
|
973
|
-
|
974
|
-
|
975
|
-
rb_raise(rb_eArgError, "Invalid argument: %s (expect %s)", rb_class2name(CLASS_OF(val)), rb_class2name(*vptr->klass));
|
976
|
-
h = DATA_PTR(val);
|
1099
|
+
const oci8_handle_data_type_t *bind_data_type = obind->base.data_type;
|
1100
|
+
const oci8_handle_data_type_t *lob_data_type = bind_data_type->rb_data_type.data;
|
1101
|
+
oci8_base_t *h = oci8_check_typeddata(val, lob_data_type, 1);
|
977
1102
|
oho->hp = h->hp.ptr;
|
978
|
-
oho->obj
|
1103
|
+
RB_OBJ_WRITE(obind->base.self, &oho->obj, val);
|
979
1104
|
}
|
980
1105
|
|
981
1106
|
static void bind_lob_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
|
@@ -986,13 +1111,14 @@ static void bind_lob_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length
|
|
986
1111
|
|
987
1112
|
static void bind_lob_init_elem(oci8_bind_t *obind, VALUE svc)
|
988
1113
|
{
|
989
|
-
const
|
1114
|
+
const oci8_bind_lob_data_type_t *data_type = (const oci8_bind_lob_data_type_t *)obind->base.data_type;
|
990
1115
|
oci8_hp_obj_t *oho = (oci8_hp_obj_t *)obind->valuep;
|
991
1116
|
oci8_base_t *h;
|
992
1117
|
ub4 idx = 0;
|
993
1118
|
|
994
1119
|
do {
|
995
|
-
oho[idx].obj = rb_class_new_instance(1, &svc, *
|
1120
|
+
oho[idx].obj = rb_class_new_instance(1, &svc, *data_type->klass);
|
1121
|
+
RB_OBJ_WRITTEN(obind->base.self, Qundef, oho[idx].obj);
|
996
1122
|
h = DATA_PTR(oho[idx].obj);
|
997
1123
|
oho[idx].hp = h->hp.ptr;
|
998
1124
|
} while (++idx < obind->maxar_sz);
|
@@ -1006,10 +1132,21 @@ static void bind_lob_post_bind_hook_for_nclob(oci8_bind_t *obind)
|
|
1006
1132
|
&obind->base);
|
1007
1133
|
}
|
1008
1134
|
|
1009
|
-
static const
|
1135
|
+
static const oci8_bind_lob_data_type_t bind_clob_data_type = {
|
1010
1136
|
{
|
1011
1137
|
{
|
1012
|
-
|
1138
|
+
{
|
1139
|
+
"OCI8::BindType::CLOB",
|
1140
|
+
{
|
1141
|
+
(RUBY_DATA_FUNC)oci8_bind_hp_obj_mark,
|
1142
|
+
oci8_handle_cleanup,
|
1143
|
+
oci8_handle_size,
|
1144
|
+
},
|
1145
|
+
&oci8_bind_data_type.rb_data_type, (void*)&oci8_clob_data_type,
|
1146
|
+
#ifdef RUBY_TYPED_WB_PROTECTED
|
1147
|
+
RUBY_TYPED_WB_PROTECTED,
|
1148
|
+
#endif
|
1149
|
+
},
|
1013
1150
|
oci8_bind_free,
|
1014
1151
|
sizeof(oci8_bind_t)
|
1015
1152
|
},
|
@@ -1023,10 +1160,26 @@ static const oci8_bind_lob_vtable_t bind_clob_vtable = {
|
|
1023
1160
|
&cOCI8CLOB
|
1024
1161
|
};
|
1025
1162
|
|
1026
|
-
static
|
1163
|
+
static VALUE bind_clob_alloc(VALUE klass)
|
1164
|
+
{
|
1165
|
+
return oci8_allocate_typeddata(klass, &bind_clob_data_type.bind.base);
|
1166
|
+
}
|
1167
|
+
|
1168
|
+
static const oci8_bind_lob_data_type_t bind_nclob_data_type = {
|
1027
1169
|
{
|
1028
1170
|
{
|
1029
|
-
|
1171
|
+
{
|
1172
|
+
"OCI8::BindType::NCLOB",
|
1173
|
+
{
|
1174
|
+
(RUBY_DATA_FUNC)oci8_bind_hp_obj_mark,
|
1175
|
+
oci8_handle_cleanup,
|
1176
|
+
oci8_handle_size,
|
1177
|
+
},
|
1178
|
+
&oci8_bind_data_type.rb_data_type, (void*)&oci8_nclob_data_type,
|
1179
|
+
#ifdef RUBY_TYPED_WB_PROTECTED
|
1180
|
+
RUBY_TYPED_WB_PROTECTED,
|
1181
|
+
#endif
|
1182
|
+
},
|
1030
1183
|
oci8_bind_free,
|
1031
1184
|
sizeof(oci8_bind_t)
|
1032
1185
|
},
|
@@ -1041,10 +1194,26 @@ static const oci8_bind_lob_vtable_t bind_nclob_vtable = {
|
|
1041
1194
|
&cOCI8NCLOB
|
1042
1195
|
};
|
1043
1196
|
|
1044
|
-
static
|
1197
|
+
static VALUE bind_nclob_alloc(VALUE klass)
|
1198
|
+
{
|
1199
|
+
return oci8_allocate_typeddata(klass, &bind_nclob_data_type.bind.base);
|
1200
|
+
}
|
1201
|
+
|
1202
|
+
static const oci8_bind_lob_data_type_t bind_blob_data_type = {
|
1045
1203
|
{
|
1046
1204
|
{
|
1047
|
-
|
1205
|
+
{
|
1206
|
+
"OCI8::BindType::BLOB",
|
1207
|
+
{
|
1208
|
+
(RUBY_DATA_FUNC)oci8_bind_hp_obj_mark,
|
1209
|
+
oci8_handle_cleanup,
|
1210
|
+
oci8_handle_size,
|
1211
|
+
},
|
1212
|
+
&oci8_bind_data_type.rb_data_type, (void*)&oci8_blob_data_type,
|
1213
|
+
#ifdef RUBY_TYPED_WB_PROTECTED
|
1214
|
+
RUBY_TYPED_WB_PROTECTED,
|
1215
|
+
#endif
|
1216
|
+
},
|
1048
1217
|
oci8_bind_free,
|
1049
1218
|
sizeof(oci8_bind_t)
|
1050
1219
|
},
|
@@ -1058,10 +1227,26 @@ static const oci8_bind_lob_vtable_t bind_blob_vtable = {
|
|
1058
1227
|
&cOCI8BLOB
|
1059
1228
|
};
|
1060
1229
|
|
1061
|
-
static
|
1230
|
+
static VALUE bind_blob_alloc(VALUE klass)
|
1231
|
+
{
|
1232
|
+
return oci8_allocate_typeddata(klass, &bind_blob_data_type.bind.base);
|
1233
|
+
}
|
1234
|
+
|
1235
|
+
static const oci8_bind_lob_data_type_t bind_bfile_data_type = {
|
1062
1236
|
{
|
1063
1237
|
{
|
1064
|
-
|
1238
|
+
{
|
1239
|
+
"OCI8::BindType::BFILE",
|
1240
|
+
{
|
1241
|
+
(RUBY_DATA_FUNC)oci8_bind_hp_obj_mark,
|
1242
|
+
oci8_handle_cleanup,
|
1243
|
+
oci8_handle_size,
|
1244
|
+
},
|
1245
|
+
&oci8_bind_data_type.rb_data_type, (void*)&oci8_bfile_data_type,
|
1246
|
+
#ifdef RUBY_TYPED_WB_PROTECTED
|
1247
|
+
RUBY_TYPED_WB_PROTECTED,
|
1248
|
+
#endif
|
1249
|
+
},
|
1065
1250
|
oci8_bind_free,
|
1066
1251
|
sizeof(oci8_bind_t)
|
1067
1252
|
},
|
@@ -1075,6 +1260,11 @@ static const oci8_bind_lob_vtable_t bind_bfile_vtable = {
|
|
1075
1260
|
&cOCI8BFILE
|
1076
1261
|
};
|
1077
1262
|
|
1263
|
+
static VALUE bind_bfile_alloc(VALUE klass)
|
1264
|
+
{
|
1265
|
+
return oci8_allocate_typeddata(klass, &bind_bfile_data_type.bind.base);
|
1266
|
+
}
|
1267
|
+
|
1078
1268
|
void Init_oci8_lob(VALUE cOCI8)
|
1079
1269
|
{
|
1080
1270
|
id_plus = rb_intern("+");
|
@@ -1085,16 +1275,21 @@ void Init_oci8_lob(VALUE cOCI8)
|
|
1085
1275
|
seek_end = rb_eval_string("::IO::SEEK_END");
|
1086
1276
|
|
1087
1277
|
#if 0
|
1278
|
+
/* for yard */
|
1088
1279
|
cOCIHandle = rb_define_class("OCIHandle", rb_cObject);
|
1089
1280
|
cOCI8 = rb_define_class("OCI8", cOCIHandle);
|
1090
1281
|
cOCI8LOB = rb_define_class_under(cOCI8, "LOB", cOCIHandle);
|
1091
|
-
#endif
|
1092
|
-
|
1093
|
-
cOCI8LOB = oci8_define_class_under(cOCI8, "LOB", &oci8_lob_vtable);
|
1094
1282
|
cOCI8CLOB = rb_define_class_under(cOCI8, "CLOB", cOCI8LOB);
|
1095
1283
|
cOCI8NCLOB = rb_define_class_under(cOCI8, "NCLOB", cOCI8LOB);
|
1096
1284
|
cOCI8BLOB = rb_define_class_under(cOCI8, "BLOB", cOCI8LOB);
|
1097
1285
|
cOCI8BFILE = rb_define_class_under(cOCI8, "BFILE", cOCI8LOB);
|
1286
|
+
#endif
|
1287
|
+
|
1288
|
+
cOCI8LOB = oci8_define_class_under(cOCI8, "LOB", &oci8_lob_data_type, oci8_lob_alloc);
|
1289
|
+
cOCI8CLOB = oci8_define_class_under(cOCI8, "CLOB", &oci8_clob_data_type, oci8_clob_alloc);
|
1290
|
+
cOCI8NCLOB = oci8_define_class_under(cOCI8, "NCLOB", &oci8_nclob_data_type, oci8_nclob_alloc);
|
1291
|
+
cOCI8BLOB = oci8_define_class_under(cOCI8, "BLOB", &oci8_blob_data_type, oci8_blob_alloc);
|
1292
|
+
cOCI8BFILE = oci8_define_class_under(cOCI8, "BFILE", &oci8_bfile_data_type, oci8_bfile_alloc);
|
1098
1293
|
|
1099
1294
|
rb_define_method(cOCI8CLOB, "initialize", oci8_clob_initialize, -1);
|
1100
1295
|
rb_define_method(cOCI8NCLOB, "initialize", oci8_nclob_initialize, -1);
|
@@ -1127,8 +1322,8 @@ void Init_oci8_lob(VALUE cOCI8)
|
|
1127
1322
|
rb_define_method(cOCI8BFILE, "size=", oci8_bfile_error, 1);
|
1128
1323
|
rb_define_method(cOCI8BFILE, "write", oci8_bfile_error, 1);
|
1129
1324
|
|
1130
|
-
oci8_define_bind_class("CLOB", &
|
1131
|
-
oci8_define_bind_class("NCLOB", &
|
1132
|
-
oci8_define_bind_class("BLOB", &
|
1133
|
-
oci8_define_bind_class("BFILE", &
|
1325
|
+
oci8_define_bind_class("CLOB", &bind_clob_data_type.bind, bind_clob_alloc);
|
1326
|
+
oci8_define_bind_class("NCLOB", &bind_nclob_data_type.bind, bind_nclob_alloc);
|
1327
|
+
oci8_define_bind_class("BLOB", &bind_blob_data_type.bind, bind_blob_alloc);
|
1328
|
+
oci8_define_bind_class("BFILE", &bind_bfile_data_type.bind, bind_bfile_alloc);
|
1134
1329
|
}
|