ruby-oci8 1.0.7-x86-mswin32-60 → 2.0.1-x86-mswin32-60
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 +1289 -383
- data/Makefile +48 -12
- data/NEWS +5 -419
- data/README +56 -385
- data/VERSION +1 -1
- data/dist-files +27 -27
- data/lib/.document +2 -0
- data/lib/dbd/OCI8.rb +2 -17
- data/lib/oci8.rb +48 -1622
- data/lib/oci8.rb.in +48 -1622
- data/lib/oci8/.document +5 -0
- data/lib/oci8/compat.rb +108 -0
- data/lib/oci8/datetime.rb +491 -0
- data/lib/oci8/encoding-init.rb +40 -0
- data/lib/oci8/encoding.yml +537 -0
- data/lib/oci8/metadata.rb +2077 -0
- data/lib/oci8/object.rb +548 -0
- data/lib/oci8/oci8.rb +798 -0
- data/lib/oci8/oracle_version.rb +144 -0
- data/lib/oci8lib_18.so +0 -0
- data/lib/oci8lib_191.so +0 -0
- data/metaconfig +3 -3
- data/ruby-oci8.gemspec +24 -15
- data/setup.rb +4 -4
- data/test/config.rb +64 -84
- data/test/test_all.rb +14 -21
- data/test/test_array_dml.rb +333 -0
- data/test/test_bind_raw.rb +18 -25
- data/test/test_bind_time.rb +78 -91
- data/test/test_break.rb +37 -35
- data/test/test_clob.rb +33 -89
- data/test/test_connstr.rb +5 -4
- data/test/test_datetime.rb +469 -0
- data/test/test_dbi.rb +99 -60
- data/test/test_dbi_clob.rb +3 -8
- data/test/test_metadata.rb +65 -51
- data/test/test_oci8.rb +151 -55
- data/test/test_oracle_version.rb +70 -0
- data/test/test_oradate.rb +76 -83
- data/test/test_oranumber.rb +405 -71
- data/test/test_rowid.rb +6 -11
- metadata +21 -25
- data/ext/oci8/oci8lib.so +0 -0
- data/ruby-oci8.spec +0 -62
- data/support/README +0 -4
- data/support/runit/assert.rb +0 -281
- data/support/runit/cui/testrunner.rb +0 -101
- data/support/runit/error.rb +0 -4
- data/support/runit/method_mappable.rb +0 -20
- data/support/runit/robserver.rb +0 -25
- data/support/runit/setuppable.rb +0 -15
- data/support/runit/teardownable.rb +0 -16
- data/support/runit/testcase.rb +0 -113
- data/support/runit/testfailure.rb +0 -25
- data/support/runit/testresult.rb +0 -121
- data/support/runit/testsuite.rb +0 -43
- data/support/runit/version.rb +0 -3
- data/test/test_describe.rb +0 -137
data/lib/oci8.rb.in
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
# --*- ruby -*--
|
2
3
|
# This is based on yoshidam's oracle.rb.
|
3
4
|
#
|
@@ -17,1639 +18,64 @@ if RUBY_PLATFORM =~ /cygwin/
|
|
17
18
|
end
|
18
19
|
end
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
require '
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
21
|
+
case RUBY_VERSION
|
22
|
+
when /^1\.9\.1/
|
23
|
+
require 'oci8lib_191'
|
24
|
+
when /^1\.8/
|
25
|
+
require 'oci8lib_18'
|
26
|
+
else
|
27
|
+
raise 'unsupported ruby version: ' + RUBY_VERSION
|
28
28
|
end
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
@ctx = ctx
|
30
|
+
if OCI8.respond_to? :encoding
|
31
|
+
if defined? DEFAULT_OCI8_ENCODING
|
32
|
+
OCI8.encoding = DEFAULT_OCI8_ENCODING
|
33
|
+
else
|
34
|
+
load 'oci8/encoding-init.rb'
|
36
35
|
end
|
37
36
|
end
|
38
37
|
|
39
|
-
|
40
|
-
# define handle of OCILobLocator needs @env and @svc.
|
41
|
-
def set_handle(env, svc, ctx)
|
42
|
-
@env = env
|
43
|
-
@svc = svc
|
44
|
-
@ctx = ctx
|
45
|
-
end
|
46
|
-
end
|
38
|
+
require 'oci8/oracle_version.rb'
|
47
39
|
|
48
40
|
class OCI8
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
#
|
61
|
-
RAW = OCI_TYPECODE_RAW
|
62
|
-
STMT_SELECT = OCI_STMT_SELECT
|
63
|
-
STMT_UPDATE = OCI_STMT_UPDATE
|
64
|
-
STMT_DELETE = OCI_STMT_DELETE
|
65
|
-
STMT_INSERT = OCI_STMT_INSERT
|
66
|
-
STMT_CREATE = OCI_STMT_CREATE
|
67
|
-
STMT_DROP = OCI_STMT_DROP
|
68
|
-
STMT_ALTER = OCI_STMT_ALTER
|
69
|
-
STMT_BEGIN = OCI_STMT_BEGIN
|
70
|
-
STMT_DECLARE = OCI_STMT_DECLARE
|
71
|
-
# :startdoc:
|
72
|
-
|
73
|
-
# sql type (varchar, varchar2)
|
74
|
-
SQLT_CHR = 1
|
75
|
-
# sql type (number, double precision, float, real, numeric, int, integer, smallint)
|
76
|
-
SQLT_NUM = 2
|
77
|
-
# sql type (long)
|
78
|
-
SQLT_LNG = 8
|
79
|
-
# sql type (date)
|
80
|
-
SQLT_DAT = 12
|
81
|
-
# sql type (raw)
|
82
|
-
SQLT_BIN = 23
|
83
|
-
# sql type (long raw)
|
84
|
-
SQLT_LBI = 24
|
85
|
-
# sql type (char)
|
86
|
-
SQLT_AFC = 96
|
87
|
-
# sql type (binary_float)
|
88
|
-
SQLT_IBFLOAT = 100
|
89
|
-
# sql type (binary_double)
|
90
|
-
SQLT_IBDOUBLE = 101
|
91
|
-
# sql type (rowid)
|
92
|
-
SQLT_RDD = 104
|
93
|
-
# sql type (clob)
|
94
|
-
SQLT_CLOB = 112
|
95
|
-
# sql type (blob)
|
96
|
-
SQLT_BLOB = 113
|
97
|
-
# sql type (bfile)
|
98
|
-
SQLT_BFILE = 114
|
99
|
-
# sql type (result set)
|
100
|
-
SQLT_RSET = 116
|
101
|
-
# sql type (timestamp), not supported yet.
|
41
|
+
ORAVER_8_0 = OCI8::OracleVersion.new(8, 0)
|
42
|
+
ORAVER_8_1 = OCI8::OracleVersion.new(8, 1)
|
43
|
+
ORAVER_9_0 = OCI8::OracleVersion.new(9, 0)
|
44
|
+
ORAVER_9_2 = OCI8::OracleVersion.new(9, 2)
|
45
|
+
ORAVER_10_1 = OCI8::OracleVersion.new(10, 1)
|
46
|
+
ORAVER_10_2 = OCI8::OracleVersion.new(10, 2)
|
47
|
+
ORAVER_11_1 = OCI8::OracleVersion.new(11, 1)
|
48
|
+
|
49
|
+
@@oracle_client_version = OCI8::OracleVersion.new(self.oracle_client_vernum)
|
50
|
+
|
51
|
+
# :call-seq:
|
52
|
+
# OCI8.oracle_client_version -> oraver
|
102
53
|
#
|
103
|
-
#
|
104
|
-
#
|
105
|
-
#
|
106
|
-
#
|
107
|
-
|
108
|
-
#
|
109
|
-
|
110
|
-
#
|
111
|
-
|
112
|
-
#
|
113
|
-
|
114
|
-
#
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
SQLCS_IMPLICIT = 1
|
119
|
-
SQLCS_NCHAR = 2
|
120
|
-
|
121
|
-
# mapping of sql type number to sql type name.
|
122
|
-
SQLT_NAMES = {}
|
123
|
-
constants.each do |name|
|
124
|
-
next if name.index("SQLT_") != 0
|
125
|
-
val = const_get name.intern
|
126
|
-
if val.is_a? Fixnum
|
127
|
-
SQLT_NAMES[val] = name
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
module Util # :nodoc:
|
132
|
-
CTX_EXECFLAG = 0
|
133
|
-
CTX_MUTEX = 1
|
134
|
-
CTX_THREAD = 2
|
135
|
-
CTX_LONG_READ_LEN = 3
|
136
|
-
|
137
|
-
def do_ocicall(ctx)
|
138
|
-
sleep_time = 0.01
|
139
|
-
ctx[CTX_MUTEX].lock
|
140
|
-
ctx[CTX_THREAD] = Thread.current
|
141
|
-
begin
|
142
|
-
yield
|
143
|
-
rescue OCIStillExecuting # non-blocking mode
|
144
|
-
ctx[CTX_MUTEX].unlock
|
145
|
-
sleep(sleep_time)
|
146
|
-
ctx[CTX_MUTEX].lock
|
147
|
-
if ctx[CTX_THREAD].nil?
|
148
|
-
raise OCIBreak
|
149
|
-
end
|
150
|
-
# expand sleep time to prevent busy loop.
|
151
|
-
sleep_time *= 2 if sleep_time < 0.5
|
152
|
-
retry
|
153
|
-
ensure
|
154
|
-
ctx[CTX_THREAD] = nil
|
155
|
-
ctx[CTX_MUTEX].unlock
|
156
|
-
end
|
157
|
-
end # do_ocicall
|
158
|
-
end
|
159
|
-
include Util
|
160
|
-
|
161
|
-
def parse_connect_string(connstr)
|
162
|
-
if connstr !~ /^([^(\s|\@)]*)\/([^(\s|\@)]*)(?:\@(\S+))?(?:\s+as\s+(\S*)\s*)?$/i
|
163
|
-
raise ArgumentError, %Q{invalid connect string "#{connstr}" (expect "username/password[@(tns_name|//host[:port]/service_name)][ as (sysdba|sysoper)]")}
|
164
|
-
end
|
165
|
-
uid, pswd, conn, privilege = $1, $2, $3, $4
|
166
|
-
case privilege.upcase
|
167
|
-
when 'SYSDBA'
|
168
|
-
privilege = :SYSDBA
|
169
|
-
when 'SYSOPER'
|
170
|
-
privilege = :SYSOPER
|
171
|
-
end if privilege
|
172
|
-
if uid.length == 0 && pswd.length == 0
|
173
|
-
# external credential
|
174
|
-
uid = nil
|
175
|
-
pswd = nil
|
176
|
-
end
|
177
|
-
return uid, pswd, conn, privilege
|
178
|
-
end
|
179
|
-
private :parse_connect_string
|
180
|
-
|
181
|
-
def initialize(*args)
|
182
|
-
raise @@error_in_initialization if @@error_in_initialization
|
183
|
-
case args.length
|
184
|
-
when 1
|
185
|
-
uid, pswd, conn, privilege = parse_connect_string(args[0])
|
186
|
-
when 2, 3, 4
|
187
|
-
uid, pswd, conn, privilege = *args
|
188
|
-
else
|
189
|
-
raise ArgumentError, "wrong number of arguments (#{args.length} for 1..4)"
|
190
|
-
end
|
191
|
-
case privilege
|
192
|
-
when nil
|
193
|
-
@privilege = nil
|
194
|
-
when :SYSDBA
|
195
|
-
@privilege = OCI_SYSDBA
|
196
|
-
when :SYSOPER
|
197
|
-
@privilege = OCI_SYSOPER
|
198
|
-
else
|
199
|
-
raise ArgumentError, "invalid privilege name #{privilege} (expect :SYSDBA, :SYSOPER or nil)"
|
200
|
-
end
|
201
|
-
|
202
|
-
@prefetch_rows = nil
|
203
|
-
@ctx = [0, Mutex.new, nil, 65535]
|
204
|
-
if @privilege or (uid.nil? and pswd.nil?)
|
205
|
-
@svc = @@env.alloc(OCISvcCtx)
|
206
|
-
@srv = @@env.alloc(OCIServer)
|
207
|
-
@auth = @@env.alloc(OCISession)
|
208
|
-
@privilege ||= OCI_DEFAULT
|
209
|
-
|
210
|
-
if uid.nil? and pswd.nil?
|
211
|
-
# external credential
|
212
|
-
cred = OCI_CRED_EXT
|
213
|
-
else
|
214
|
-
# RDBMS credential
|
215
|
-
cred = OCI_CRED_RDBMS
|
216
|
-
@auth.attrSet(OCI_ATTR_USERNAME, uid)
|
217
|
-
@auth.attrSet(OCI_ATTR_PASSWORD, pswd)
|
218
|
-
end
|
219
|
-
do_ocicall(@ctx) { @srv.attach(conn) }
|
220
|
-
begin
|
221
|
-
@svc.attrSet(OCI_ATTR_SERVER, @srv)
|
222
|
-
do_ocicall(@ctx) { @auth.begin(@svc, cred, @privilege) }
|
223
|
-
@svc.attrSet(OCI_ATTR_SESSION, @auth)
|
224
|
-
rescue
|
225
|
-
@srv.detach()
|
226
|
-
raise
|
227
|
-
end
|
228
|
-
else
|
229
|
-
@svc = @@env.logon(uid, pswd, conn)
|
230
|
-
end
|
231
|
-
@svc.instance_variable_set(:@env, @@env)
|
232
|
-
end # initialize
|
233
|
-
|
234
|
-
def logoff
|
235
|
-
rollback()
|
236
|
-
if @privilege
|
237
|
-
do_ocicall(@ctx) { @auth.end(@svc) }
|
238
|
-
do_ocicall(@ctx) { @srv.detach() }
|
239
|
-
else
|
240
|
-
@svc.logoff
|
241
|
-
end
|
242
|
-
@svc.free()
|
243
|
-
true
|
244
|
-
end # logoff
|
245
|
-
|
246
|
-
def exec(sql, *bindvars)
|
247
|
-
cursor = OCI8::Cursor.new(@@env, @svc, @ctx)
|
248
|
-
cursor.prefetch_rows = @prefetch_rows if @prefetch_rows
|
249
|
-
cursor.parse(sql)
|
250
|
-
if cursor.type == OCI_STMT_SELECT && ! block_given?
|
251
|
-
cursor.exec(*bindvars)
|
252
|
-
cursor
|
253
|
-
else
|
254
|
-
begin
|
255
|
-
ret = cursor.exec(*bindvars)
|
256
|
-
case cursor.type
|
257
|
-
when OCI_STMT_SELECT
|
258
|
-
cursor.fetch { |row| yield(row) } # for each row
|
259
|
-
cursor.row_count()
|
260
|
-
when OCI_STMT_BEGIN, OCI_STMT_DECLARE # PL/SQL block
|
261
|
-
ary = []
|
262
|
-
cursor.keys.sort.each do |key|
|
263
|
-
ary << cursor[key]
|
264
|
-
end
|
265
|
-
ary
|
266
|
-
else
|
267
|
-
ret
|
268
|
-
end
|
269
|
-
ensure
|
270
|
-
cursor.close
|
271
|
-
end
|
272
|
-
end
|
273
|
-
end # exec
|
274
|
-
|
275
|
-
def parse(sql)
|
276
|
-
cursor = OCI8::Cursor.new(@@env, @svc, @ctx)
|
277
|
-
cursor.prefetch_rows = @prefetch_rows if @prefetch_rows
|
278
|
-
cursor.parse(sql)
|
279
|
-
cursor
|
280
|
-
end # parse
|
281
|
-
|
282
|
-
def commit
|
283
|
-
do_ocicall(@ctx) { @svc.commit }
|
284
|
-
self
|
285
|
-
end # commit
|
286
|
-
|
287
|
-
def rollback
|
288
|
-
do_ocicall(@ctx) { @svc.rollback }
|
289
|
-
self
|
290
|
-
end # rollback
|
291
|
-
|
292
|
-
def autocommit?
|
293
|
-
(@ctx[CTX_EXECFLAG] & OCI_COMMIT_ON_SUCCESS) == OCI_COMMIT_ON_SUCCESS
|
294
|
-
end # autocommit?
|
295
|
-
|
296
|
-
# add alias compatible with 'Oracle7 Module for Ruby'.
|
297
|
-
alias autocommit autocommit?
|
298
|
-
|
299
|
-
def autocommit=(ac)
|
300
|
-
if ac
|
301
|
-
commit()
|
302
|
-
@ctx[CTX_EXECFLAG] |= OCI_COMMIT_ON_SUCCESS
|
303
|
-
else
|
304
|
-
@ctx[CTX_EXECFLAG] &= ~OCI_COMMIT_ON_SUCCESS
|
305
|
-
end
|
306
|
-
ac
|
307
|
-
end # autocommit=
|
308
|
-
|
309
|
-
def prefetch_rows=(rows)
|
310
|
-
@prefetch_rows = rows
|
311
|
-
end
|
312
|
-
|
313
|
-
def non_blocking?
|
314
|
-
@svc.attrGet(OCI_ATTR_NONBLOCKING_MODE)
|
315
|
-
end # non_blocking?
|
316
|
-
|
317
|
-
def non_blocking=(nb)
|
318
|
-
if (nb ? true : false) != non_blocking?
|
319
|
-
# If the argument and the current status are different,
|
320
|
-
# toggle blocking / non-blocking.
|
321
|
-
@srv = @svc.attrGet(OCI_ATTR_SERVER) unless @srv
|
322
|
-
@srv.attrSet(OCI_ATTR_NONBLOCKING_MODE, nil)
|
323
|
-
end
|
324
|
-
end # non_blocking=
|
325
|
-
|
326
|
-
def break
|
327
|
-
@ctx[CTX_MUTEX].synchronize do
|
328
|
-
@svc.break()
|
329
|
-
unless @ctx[CTX_THREAD].nil?
|
330
|
-
@ctx[CTX_THREAD].wakeup()
|
331
|
-
@ctx[CTX_THREAD] = nil
|
332
|
-
if @svc.respond_to?("reset")
|
333
|
-
begin
|
334
|
-
@svc.reset()
|
335
|
-
rescue OCIError
|
336
|
-
raise if $!.code != 1013 # ORA-01013
|
337
|
-
end
|
338
|
-
end
|
339
|
-
end
|
340
|
-
end
|
341
|
-
end # break
|
342
|
-
|
343
|
-
def long_read_len
|
344
|
-
@ctx[OCI8::Util::CTX_LONG_READ_LEN]
|
345
|
-
end
|
346
|
-
|
347
|
-
def long_read_len=(len)
|
348
|
-
@ctx[OCI8::Util::CTX_LONG_READ_LEN] = len
|
349
|
-
end
|
350
|
-
|
351
|
-
def describe_table(table_name)
|
352
|
-
desc = @@env.alloc(OCIDescribe)
|
353
|
-
desc.attrSet(OCI_ATTR_DESC_PUBLIC, -1)
|
354
|
-
do_ocicall(@ctx) { desc.describeAny(@svc, table_name.to_s, OCI_PTYPE_UNK) }
|
355
|
-
param = desc.attrGet(OCI_ATTR_PARAM)
|
356
|
-
|
357
|
-
case param.attrGet(OCI_ATTR_PTYPE)
|
358
|
-
when OCI_PTYPE_TABLE
|
359
|
-
OCI8::Metadata::Table.new(param)
|
360
|
-
when OCI_PTYPE_VIEW
|
361
|
-
OCI8::Metadata::View.new(param)
|
362
|
-
when OCI_PTYPE_SYN
|
363
|
-
schema_name = param.attrGet(OCI_ATTR_SCHEMA_NAME)
|
364
|
-
name = param.attrGet(OCI_ATTR_NAME)
|
365
|
-
link = param.attrGet(OCI_ATTR_LINK)
|
366
|
-
if link.length != 0
|
367
|
-
translated_name = schema_name + '.' + name + '@' + link
|
368
|
-
else
|
369
|
-
translated_name = schema_name + '.' + name
|
370
|
-
end
|
371
|
-
describe_table(translated_name)
|
372
|
-
else
|
373
|
-
raise OCIError.new("ORA-04043: object #{table_name} does not exist", 4043)
|
374
|
-
end
|
375
|
-
end
|
376
|
-
|
377
|
-
module BindType
|
378
|
-
# get/set String
|
379
|
-
String = Object.new
|
380
|
-
class << String
|
381
|
-
def fix_type(env, val, length, precision, scale)
|
382
|
-
[OCI8::SQLT_CHR, val, length || (val.nil? ? nil : val.length)]
|
383
|
-
end
|
384
|
-
end
|
385
|
-
|
386
|
-
# get/set RAW
|
387
|
-
RAW = Object.new
|
388
|
-
class << RAW
|
389
|
-
def fix_type(env, val, length, precision, scale)
|
390
|
-
[OCI8::SQLT_BIN, val, length || (val.nil? ? nil : val.length)]
|
391
|
-
end
|
392
|
-
end
|
393
|
-
|
394
|
-
# get/set OraDate
|
395
|
-
OraDate = Object.new
|
396
|
-
class << OraDate
|
397
|
-
def fix_type(env, val, length, precision, scale)
|
398
|
-
[OCI8::SQLT_DAT, val, nil]
|
399
|
-
end
|
400
|
-
end
|
401
|
-
|
402
|
-
# get/set Time
|
403
|
-
Time = Object.new
|
404
|
-
class << Time
|
405
|
-
def fix_type(env, val, length, precision, scale)
|
406
|
-
[OCI8::SQLT_DAT, val, nil]
|
407
|
-
end
|
408
|
-
def decorate(b)
|
409
|
-
def b.set(val)
|
410
|
-
super(val && ::OraDate.new(val.year, val.mon, val.mday, val.hour, val.min, val.sec))
|
411
|
-
end
|
412
|
-
def b.get()
|
413
|
-
(val = super()) && val.to_time
|
414
|
-
end
|
415
|
-
end
|
416
|
-
end
|
417
|
-
|
418
|
-
# get/set Date
|
419
|
-
Date = Object.new
|
420
|
-
class << Date
|
421
|
-
def fix_type(env, val, length, precision, scale)
|
422
|
-
[OCI8::SQLT_DAT, val, nil]
|
423
|
-
end
|
424
|
-
def decorate(b)
|
425
|
-
def b.set(val)
|
426
|
-
super(val && ::OraDate.new(val.year, val.mon, val.mday))
|
427
|
-
end
|
428
|
-
def b.get()
|
429
|
-
(val = super()) && val.to_date
|
430
|
-
end
|
431
|
-
end
|
432
|
-
end
|
433
|
-
|
434
|
-
if defined? ::DateTime # ruby 1.8.0 or upper
|
435
|
-
# get/set DateTime
|
436
|
-
DateTime = Object.new
|
437
|
-
class << DateTime
|
438
|
-
def fix_type(env, val, length, precision, scale)
|
439
|
-
[OCI8::SQLT_DAT, val, nil]
|
440
|
-
end
|
441
|
-
def decorate(b)
|
442
|
-
def b.set(val)
|
443
|
-
super(val && ::OraDate.new(val.year, val.mon, val.mday, val.hour, val.min, val.sec))
|
444
|
-
end
|
445
|
-
def b.get()
|
446
|
-
(val = super()) && val.to_datetime
|
447
|
-
end
|
448
|
-
end
|
449
|
-
end
|
450
|
-
end
|
451
|
-
|
452
|
-
# get/set Float
|
453
|
-
Float = Object.new
|
454
|
-
class << Float
|
455
|
-
def fix_type(env, val, length, precision, scale)
|
456
|
-
[::Float, val, nil]
|
457
|
-
end
|
458
|
-
end
|
459
|
-
|
460
|
-
if defined? OCI_TYPECODE_BDOUBLE
|
461
|
-
BinaryDouble = Object.new
|
462
|
-
class << BinaryDouble
|
463
|
-
def fix_type(env, val, length, precision, scale)
|
464
|
-
[SQLT_IBDOUBLE, val, nil]
|
465
|
-
end
|
466
|
-
end
|
467
|
-
end
|
468
|
-
|
469
|
-
# get/set Fixnum
|
470
|
-
Fixnum = Object.new
|
471
|
-
class << Fixnum
|
472
|
-
def fix_type(env, val, length, precision, scale)
|
473
|
-
[::Fixnum, val, nil]
|
474
|
-
end
|
475
|
-
end
|
476
|
-
|
477
|
-
# get/set Integer
|
478
|
-
Integer = Object.new
|
479
|
-
class << Integer
|
480
|
-
def fix_type(env, val, length, precision, scale)
|
481
|
-
[::Integer, val, nil]
|
482
|
-
end
|
483
|
-
end
|
484
|
-
|
485
|
-
# get/set OraNumber
|
486
|
-
OraNumber = Object.new
|
487
|
-
class << OraNumber
|
488
|
-
def fix_type(env, val, length, precision, scale)
|
489
|
-
[::OraNumber, val, nil]
|
490
|
-
end
|
491
|
-
end
|
492
|
-
|
493
|
-
# get/set Number (for OCI8::SQLT_NUM)
|
494
|
-
Number = Object.new
|
495
|
-
class << Number
|
496
|
-
def fix_type(env, val, length, precision, scale)
|
497
|
-
if scale == -127
|
498
|
-
if precision == 0
|
499
|
-
# NUMBER declared without its scale and precision. (Oracle 9.2.0.3 or above)
|
500
|
-
::OCI8::BindType::Mapping[:number_no_prec_setting].fix_type(env, val, length, precision, scale)
|
501
|
-
else
|
502
|
-
# FLOAT or FLOAT(p)
|
503
|
-
[::Float, val, nil]
|
504
|
-
end
|
505
|
-
elsif scale == 0
|
506
|
-
if precision == 0
|
507
|
-
# NUMBER whose scale and precision is unknown
|
508
|
-
# or
|
509
|
-
# NUMBER declared without its scale and precision. (Oracle 9.2.0.2 or below)
|
510
|
-
::OCI8::BindType::Mapping[:number_unknown_prec].fix_type(env, val, length, precision, scale)
|
511
|
-
elsif precision <= 9
|
512
|
-
# NUMBER(p, 0); p is less than or equals to the precision of Fixnum
|
513
|
-
[::Fixnum, val, nil]
|
514
|
-
else
|
515
|
-
# NUMBER(p, 0); p is greater than the precision of Fixnum
|
516
|
-
[::Integer, val, nil]
|
517
|
-
end
|
518
|
-
else
|
519
|
-
# NUMBER(p, s)
|
520
|
-
if precision < 15 # the precision of double.
|
521
|
-
[::Float, val, nil]
|
522
|
-
else
|
523
|
-
# use BigDecimal instead?
|
524
|
-
[::OraNumber, val, nil]
|
525
|
-
end
|
526
|
-
end
|
527
|
-
end
|
528
|
-
end
|
529
|
-
|
530
|
-
# get/set OCIRowid
|
531
|
-
OCIRowid = Object.new
|
532
|
-
class << OCIRowid
|
533
|
-
def fix_type(env, val, length, precision, scale)
|
534
|
-
[OCI8::SQLT_RDD, nil, val]
|
535
|
-
end
|
536
|
-
end
|
537
|
-
|
538
|
-
# get/set BLOB
|
539
|
-
BLOB = Object.new
|
540
|
-
class << BLOB
|
541
|
-
def check_type(val)
|
542
|
-
raise ArgumentError, "invalid argument: #{val.class} (expect OCI8::BLOB)" unless val.is_a? OCI8::BLOB
|
543
|
-
end
|
544
|
-
def fix_type(env, val, length, precision, scale)
|
545
|
-
unless val.nil?
|
546
|
-
check_type(val)
|
547
|
-
val = val.instance_variable_get(:@locator)
|
548
|
-
end
|
549
|
-
[OCI8::SQLT_BLOB, nil, val]
|
550
|
-
end
|
551
|
-
def decorate(b)
|
552
|
-
def b.set(val)
|
553
|
-
check_type(val)
|
554
|
-
val = val.instance_variable_get(:@locator)
|
555
|
-
super(val)
|
556
|
-
end
|
557
|
-
def b.get()
|
558
|
-
(val = super()) && OCI8::BLOB.new(@svc, val.clone(@svc))
|
559
|
-
end
|
560
|
-
end
|
561
|
-
end
|
562
|
-
|
563
|
-
# get/set CLOB
|
564
|
-
CLOB = Object.new
|
565
|
-
class << CLOB
|
566
|
-
def check_type(val)
|
567
|
-
raise ArgumentError, "invalid argument: #{val.class} (expect OCI8::CLOB)" unless val.is_a? OCI8::CLOB
|
568
|
-
end
|
569
|
-
def fix_type(env, val, length, precision, scale)
|
570
|
-
unless val.nil?
|
571
|
-
check_type(val)
|
572
|
-
val = val.instance_variable_get(:@locator)
|
573
|
-
end
|
574
|
-
[OCI8::SQLT_CLOB, nil, val]
|
575
|
-
end
|
576
|
-
def decorate(b)
|
577
|
-
def b.set(val)
|
578
|
-
check_type(val)
|
579
|
-
val = val.instance_variable_get(:@locator)
|
580
|
-
super(val)
|
581
|
-
end
|
582
|
-
def b.get()
|
583
|
-
(val = super()) && OCI8::CLOB.new(@svc, val.clone(@svc))
|
584
|
-
end
|
585
|
-
end
|
586
|
-
end
|
587
|
-
|
588
|
-
# get/set NCLOB
|
589
|
-
NCLOB = Object.new
|
590
|
-
class << NCLOB
|
591
|
-
def check_type(val)
|
592
|
-
raise ArgumentError, "invalid argument: #{val.class} (expect OCI8::NCLOB)" unless val.is_a? OCI8::NCLOB
|
593
|
-
end
|
594
|
-
def fix_type(env, val, length, precision, scale)
|
595
|
-
unless val.nil?
|
596
|
-
check_type(val)
|
597
|
-
val = val.instance_variable_get(:@locator)
|
598
|
-
end
|
599
|
-
[OCI8::SQLT_CLOB, nil, val]
|
600
|
-
end
|
601
|
-
def decorate(b)
|
602
|
-
b.attrSet(OCI_ATTR_CHARSET_FORM, SQLCS_NCHAR)
|
603
|
-
def b.set(val)
|
604
|
-
check_type(val)
|
605
|
-
val = val.instance_variable_get(:@locator)
|
606
|
-
super(val)
|
607
|
-
end
|
608
|
-
def b.get()
|
609
|
-
(val = super()) && OCI8::NCLOB.new(@svc, val.clone(@svc))
|
610
|
-
end
|
611
|
-
end
|
612
|
-
end
|
613
|
-
|
614
|
-
# get/set BFILE
|
615
|
-
BFILE = Object.new
|
616
|
-
class << BFILE
|
617
|
-
def check_type(val)
|
618
|
-
raise ArgumentError, "invalid argument: #{val.class} (expect OCI8::BFILE)" unless val.is_a? OCI8::BFILE
|
619
|
-
end
|
620
|
-
def fix_type(env, val, length, precision, scale)
|
621
|
-
unless val.nil?
|
622
|
-
check_type(val)
|
623
|
-
val = val.instance_variable_get(:@locator)
|
624
|
-
end
|
625
|
-
[OCI8::SQLT_BFILE, nil, val]
|
626
|
-
end
|
627
|
-
def decorate(b)
|
628
|
-
def b.set(val)
|
629
|
-
check_type(val)
|
630
|
-
val = val.instance_variable_get(:@locator)
|
631
|
-
super(val)
|
632
|
-
end
|
633
|
-
def b.get()
|
634
|
-
(val = super()) && OCI8::BFILE.new(@svc, val.clone(@svc))
|
635
|
-
end
|
636
|
-
end
|
637
|
-
end
|
638
|
-
|
639
|
-
# get Cursor
|
640
|
-
Cursor = Object.new
|
641
|
-
class << Cursor
|
642
|
-
def fix_type(env, val, length, precision, scale)
|
643
|
-
[OCI8::SQLT_RSET, nil, val]
|
644
|
-
end
|
645
|
-
def decorate(b)
|
646
|
-
def b.get()
|
647
|
-
(val = super()) && OCI8::Cursor.new(@env, @svc, @ctx, val)
|
648
|
-
end
|
649
|
-
def b.pre_fetch_hook()
|
650
|
-
set(@env.alloc(OCIStmt))
|
651
|
-
end
|
652
|
-
end
|
653
|
-
end
|
654
|
-
|
655
|
-
Mapping = {}
|
656
|
-
end # BindType
|
657
|
-
|
658
|
-
class Cursor
|
659
|
-
|
660
|
-
include OCI8::Util
|
661
|
-
|
662
|
-
# for backward compatibility
|
663
|
-
def self.select_number_as=(val) # :nodoc:
|
664
|
-
if val == ::Fixnum
|
665
|
-
bind_type = ::OCI8::BindType::Fixnum
|
666
|
-
elsif val == ::Integer
|
667
|
-
bind_type = ::OCI8::BindType::Integer
|
668
|
-
elsif val == ::Float
|
669
|
-
bind_type = ::OCI8::BindType::Float
|
670
|
-
else
|
671
|
-
raise ArgumentError, "must be Fixnum, Integer or Float"
|
672
|
-
end
|
673
|
-
::OCI8::BindType::Mapping[:number_unknown_prec] = bind_type
|
674
|
-
end
|
675
|
-
|
676
|
-
# for backward compatibility
|
677
|
-
def self.select_number_as # :nodoc:
|
678
|
-
::OCI8::BindType::Mapping[:number_unknown_prec].fix_type(nil, nil, nil, nil, nil)[0]
|
679
|
-
end
|
680
|
-
|
681
|
-
def initialize(env, svc, ctx, stmt = nil)
|
682
|
-
if Process.pid != svc.pid
|
683
|
-
raise "The connection cannot be reused in the forked process."
|
684
|
-
end
|
685
|
-
@env = env
|
686
|
-
@svc = svc
|
687
|
-
@ctx = ctx
|
688
|
-
@binds = nil
|
689
|
-
@parms = []
|
690
|
-
@defns = nil
|
691
|
-
if stmt.nil?
|
692
|
-
@stmt = @env.alloc(OCIStmt)
|
693
|
-
@stmttype = nil
|
694
|
-
else
|
695
|
-
@stmt = stmt
|
696
|
-
@stmttype = @stmt.attrGet(OCI_ATTR_STMT_TYPE)
|
697
|
-
define_columns()
|
698
|
-
end
|
699
|
-
end # initialize
|
700
|
-
|
701
|
-
def parse(sql)
|
702
|
-
free_binds()
|
703
|
-
@parms = []
|
704
|
-
@stmt.prepare(sql)
|
705
|
-
@stmttype = do_ocicall(@ctx) { @stmt.attrGet(OCI_ATTR_STMT_TYPE) }
|
706
|
-
end # parse
|
707
|
-
|
708
|
-
def define(pos, type, length = nil)
|
709
|
-
@defns = [] if @defns.nil?
|
710
|
-
if type == String and length.nil?
|
711
|
-
length = 4000
|
712
|
-
end
|
713
|
-
b = bind_or_define(:define, pos, nil, type, length, nil, nil, false)
|
714
|
-
@defns[pos].free() unless @defns[pos].nil?
|
715
|
-
@defns[pos] = b
|
716
|
-
self
|
717
|
-
end # define
|
718
|
-
|
719
|
-
def bind_param(key, val, type = nil, length = nil)
|
720
|
-
@binds = {} if @binds.nil?
|
721
|
-
b = bind_or_define(:bind, key, val, type, length, nil, nil, false)
|
722
|
-
@binds[key].free() unless @binds[key].nil?
|
723
|
-
@binds[key] = b
|
724
|
-
self
|
725
|
-
end # bind_param
|
726
|
-
|
727
|
-
# get bind value
|
728
|
-
def [](key)
|
729
|
-
if @binds.nil? or @binds[key].nil?
|
730
|
-
return nil
|
731
|
-
end
|
732
|
-
@binds[key].get()
|
733
|
-
end
|
734
|
-
|
735
|
-
# set bind value
|
736
|
-
def []=(key, val)
|
737
|
-
if @binds.nil? or @binds[key].nil?
|
738
|
-
return nil
|
739
|
-
end
|
740
|
-
@binds[key].set(val)
|
741
|
-
end
|
742
|
-
|
743
|
-
# get bind keys
|
744
|
-
def keys
|
745
|
-
if @binds.nil?
|
746
|
-
[]
|
747
|
-
else
|
748
|
-
@binds.keys
|
749
|
-
end
|
750
|
-
end
|
751
|
-
|
752
|
-
def exec(*bindvars)
|
753
|
-
bind_params(*bindvars)
|
754
|
-
case @stmttype
|
755
|
-
when OCI_STMT_SELECT
|
756
|
-
do_ocicall(@ctx) { @stmt.execute(@svc, 0, OCI_DEFAULT) }
|
757
|
-
define_columns()
|
758
|
-
else
|
759
|
-
do_ocicall(@ctx) { @stmt.execute(@svc, 1, @ctx[CTX_EXECFLAG]) }
|
760
|
-
@stmt.attrGet(OCI_ATTR_ROW_COUNT)
|
761
|
-
end
|
762
|
-
end # exec
|
763
|
-
|
764
|
-
def type
|
765
|
-
@stmttype
|
766
|
-
end
|
767
|
-
|
768
|
-
def row_count
|
769
|
-
@stmt.attrGet(OCI_ATTR_ROW_COUNT)
|
770
|
-
end
|
771
|
-
|
772
|
-
def get_col_names
|
773
|
-
@parms.collect do |p|
|
774
|
-
do_ocicall(@ctx) { p.attrGet(OCI_ATTR_NAME) }
|
775
|
-
end
|
776
|
-
end # get_col_names
|
777
|
-
|
778
|
-
# add alias compatible with 'Oracle7 Module for Ruby'.
|
779
|
-
alias getColNames get_col_names
|
780
|
-
|
781
|
-
def column_metadata
|
782
|
-
@parms.collect do |p|
|
783
|
-
OCI8::Metadata::Column.new(p)
|
784
|
-
end
|
785
|
-
end
|
786
|
-
|
787
|
-
def fetch
|
788
|
-
if iterator?
|
789
|
-
while ret = fetch_a_row()
|
790
|
-
yield(ret)
|
791
|
-
end
|
792
|
-
else
|
793
|
-
fetch_a_row()
|
794
|
-
end
|
795
|
-
end # fetch
|
796
|
-
|
797
|
-
def fetch_hash
|
798
|
-
if iterator?
|
799
|
-
while ret = fetch_a_hash_row()
|
800
|
-
yield(ret)
|
801
|
-
end
|
802
|
-
else
|
803
|
-
fetch_a_hash_row
|
804
|
-
end
|
805
|
-
end # fetch_hash
|
806
|
-
|
807
|
-
def close
|
808
|
-
@env = nil
|
809
|
-
@svc = nil
|
810
|
-
free_defns()
|
811
|
-
free_binds()
|
812
|
-
@stmt.free()
|
813
|
-
@parms = nil
|
814
|
-
@stmttype = nil
|
815
|
-
end # close
|
816
|
-
|
817
|
-
# Get the rowid of the last inserted/updated/deleted row.
|
818
|
-
def rowid
|
819
|
-
# get the binary rowid
|
820
|
-
rid = @stmt.attrGet(OCI_ATTR_ROWID)
|
821
|
-
# convert it to a string rowid.
|
822
|
-
if rid.respond_to? :to_s
|
823
|
-
# (Oracle 9.0 or upper)
|
824
|
-
rid.to_s
|
825
|
-
else
|
826
|
-
# (Oracle 8.1 or lower)
|
827
|
-
stmt = @env.alloc(OCIStmt)
|
828
|
-
stmt.prepare('begin :1 := :2; end;')
|
829
|
-
b = stmt.bindByPos(1, OCI8::SQLT_CHR, 64)
|
830
|
-
stmt.bindByPos(2, OCI8::SQLT_RDD, rid)
|
831
|
-
do_ocicall(@ctx) { stmt.execute(@svc, 1, OCI_DEFAULT) }
|
832
|
-
str_rid = b.get()
|
833
|
-
stmt.free()
|
834
|
-
str_rid
|
835
|
-
end
|
836
|
-
end
|
837
|
-
|
838
|
-
def prefetch_rows=(rows)
|
839
|
-
@stmt.attrSet(OCI_ATTR_PREFETCH_ROWS, rows)
|
840
|
-
end
|
841
|
-
|
842
|
-
private
|
843
|
-
|
844
|
-
def bind_or_define(bind_type, key, val, type, length, precision, scale, strict_check)
|
845
|
-
if type.nil?
|
846
|
-
if val.nil?
|
847
|
-
raise "bind type is not given." if type.nil?
|
848
|
-
else
|
849
|
-
if val.class == Class
|
850
|
-
type = val
|
851
|
-
val = nil
|
852
|
-
else
|
853
|
-
type = val.class
|
854
|
-
end
|
855
|
-
end
|
856
|
-
end
|
857
|
-
|
858
|
-
binder = OCI8::BindType::Mapping[type]
|
859
|
-
if binder
|
860
|
-
type, val, option = binder.fix_type(@env, val, length, precision, scale)
|
861
|
-
else
|
862
|
-
if strict_check
|
863
|
-
raise "unsupported datatype: #{SQLT_NAMES[type] ? SQLT_NAMES[type] : type}"
|
864
|
-
else
|
865
|
-
option = length
|
866
|
-
end
|
867
|
-
end
|
868
|
-
|
869
|
-
case bind_type
|
870
|
-
when :bind
|
871
|
-
if key.is_a? Fixnum
|
872
|
-
b = @stmt.bindByPos(key, type, option)
|
873
|
-
else
|
874
|
-
b = @stmt.bindByName(key, type, option)
|
875
|
-
end
|
876
|
-
when :define
|
877
|
-
b = @stmt.defineByPos(key, type, option)
|
878
|
-
end
|
879
|
-
b.set_handle(@env, @svc, @ctx)
|
880
|
-
|
881
|
-
if binder && binder.respond_to?(:decorate)
|
882
|
-
# decorate the bind handle.
|
883
|
-
binder.decorate(b)
|
884
|
-
end
|
885
|
-
|
886
|
-
b.set(val) unless val.nil?
|
887
|
-
b
|
888
|
-
end # bind_or_define
|
889
|
-
|
890
|
-
def define_columns
|
891
|
-
num_cols = @stmt.attrGet(OCI_ATTR_PARAM_COUNT)
|
892
|
-
1.upto(num_cols) do |i|
|
893
|
-
@parms[i - 1] = @stmt.paramGet(i)
|
894
|
-
end
|
895
|
-
@defns = Array.new(@parms.size) if @defns.nil?
|
896
|
-
1.upto(num_cols) do |i|
|
897
|
-
@defns[i] = define_a_column(i) if @defns[i].nil?
|
898
|
-
end
|
899
|
-
num_cols
|
900
|
-
end # define_columns
|
901
|
-
|
902
|
-
def define_a_column(i)
|
903
|
-
p = @parms[i - 1]
|
904
|
-
datatype = do_ocicall(@ctx) { p.attrGet(OCI_ATTR_DATA_TYPE) }
|
905
|
-
datasize = do_ocicall(@ctx) { p.attrGet(OCI_ATTR_DATA_SIZE) }
|
906
|
-
precision = do_ocicall(@ctx) { p.attrGet(OCI_ATTR_PRECISION) }
|
907
|
-
scale = do_ocicall(@ctx) { p.attrGet(OCI_ATTR_SCALE) }
|
908
|
-
csfrm = nil
|
909
|
-
|
910
|
-
case datatype
|
911
|
-
when SQLT_CHR, SQLT_AFC
|
912
|
-
# character size may become large on character set conversion.
|
913
|
-
# The length of a half-width kana is one in Shift_JIS, two in EUC-JP,
|
914
|
-
# three in UTF-8.
|
915
|
-
datasize *= 3
|
916
|
-
when SQLT_LNG, SQLT_LBI
|
917
|
-
datasize = @ctx[OCI8::Util::CTX_LONG_READ_LEN]
|
918
|
-
when SQLT_CLOB
|
919
|
-
datatype = :nclob if p.attrGet(OCI_ATTR_CHARSET_FORM) == SQLCS_NCHAR
|
920
|
-
when SQLT_BIN
|
921
|
-
datasize *= 2 if OCI8::BindType::Mapping[datatype] == OCI8::BindType::String
|
922
|
-
when SQLT_RDD
|
923
|
-
datasize = 64
|
924
|
-
end
|
925
|
-
|
926
|
-
bind_or_define(:define, i, nil, datatype, datasize, precision, scale, true)
|
927
|
-
end # define_a_column
|
928
|
-
|
929
|
-
def bind_params(*bindvars)
|
930
|
-
bindvars.each_with_index do |val, i|
|
931
|
-
if val.is_a? Array
|
932
|
-
bind_param(i + 1, val[0], val[1], val[2])
|
933
|
-
else
|
934
|
-
bind_param(i + 1, val)
|
935
|
-
end
|
936
|
-
end
|
937
|
-
end # bind_params
|
938
|
-
|
939
|
-
def fetch_a_row
|
940
|
-
@defns.each do |d|
|
941
|
-
d.pre_fetch_hook if d.respond_to? :pre_fetch_hook
|
942
|
-
end
|
943
|
-
res = do_ocicall(@ctx) { @stmt.fetch() }
|
944
|
-
return nil if res.nil?
|
945
|
-
res.collect do |r| r.get() end
|
946
|
-
end # fetch_a_row
|
947
|
-
|
948
|
-
def fetch_a_hash_row
|
949
|
-
if rs = fetch_a_row()
|
950
|
-
ret = {}
|
951
|
-
@parms.each do |p|
|
952
|
-
ret[p.attrGet(OCI_ATTR_NAME)] = rs.shift
|
953
|
-
end
|
954
|
-
ret
|
955
|
-
else
|
956
|
-
nil
|
957
|
-
end
|
958
|
-
end # fetch_a_hash_row
|
959
|
-
|
960
|
-
def free_defns
|
961
|
-
unless @defns.nil?
|
962
|
-
@defns.each do |b|
|
963
|
-
b.free() unless b.nil?
|
964
|
-
end
|
965
|
-
end
|
966
|
-
@defns = nil
|
967
|
-
end # free_defns
|
968
|
-
|
969
|
-
def free_binds
|
970
|
-
unless @binds.nil?
|
971
|
-
@binds.each_value do |b|
|
972
|
-
b.free()
|
973
|
-
end
|
974
|
-
end
|
975
|
-
@binds = nil
|
976
|
-
end # free_binds
|
977
|
-
end # OCI8::Cursor
|
978
|
-
|
979
|
-
class LOB
|
980
|
-
attr :pos
|
981
|
-
def initialize(svc, val)
|
982
|
-
svc = svc.instance_variable_get(:@svc) if svc.is_a? OCI8
|
983
|
-
raise "invalid argument" unless svc.is_a? OCISvcCtx
|
984
|
-
@env = svc.instance_variable_get(:@env)
|
985
|
-
@svc = svc
|
986
|
-
@csid = 0
|
987
|
-
@pos = 0
|
988
|
-
if val.is_a? OCILobLocator
|
989
|
-
@locator = val
|
990
|
-
else
|
991
|
-
@locator = @env.alloc(OCILobLocator)
|
992
|
-
@locator.create_temporary(@svc, @csid, @csfrm, @lobtype, false, nil)
|
993
|
-
val.nil? || write(val.to_s)
|
994
|
-
end
|
995
|
-
end
|
996
|
-
|
997
|
-
def available?
|
998
|
-
@locator.is_initialized?(@env)
|
999
|
-
end
|
1000
|
-
|
1001
|
-
def truncate(len)
|
1002
|
-
raise "uninitialized LOB" unless available?
|
1003
|
-
@locator.trim(@svc, len)
|
1004
|
-
self
|
1005
|
-
end
|
1006
|
-
|
1007
|
-
def read(readlen = nil)
|
1008
|
-
rest = self.size - @pos
|
1009
|
-
return nil if rest == 0 # eof.
|
1010
|
-
if readlen.nil? or readlen > rest
|
1011
|
-
readlen = rest # read until EOF.
|
1012
|
-
end
|
1013
|
-
begin
|
1014
|
-
rv = @locator.read(@svc, @pos + 1, readlen, @csid, @csfrm)
|
1015
|
-
rescue OCIError
|
1016
|
-
raise if $!.code != 22289
|
1017
|
-
# ORA-22289: cannot perform FILEREAD operation on an unopened file or LOB.
|
1018
|
-
open
|
1019
|
-
retry
|
1020
|
-
end
|
1021
|
-
@pos += readlen
|
1022
|
-
rv
|
1023
|
-
end
|
1024
|
-
|
1025
|
-
def write(data)
|
1026
|
-
raise "uninitialized LOB" unless available?
|
1027
|
-
size = @locator.write(@svc, @pos + 1, data, @csid, @csfrm)
|
1028
|
-
@pos += size
|
1029
|
-
size
|
1030
|
-
end
|
1031
|
-
|
1032
|
-
def size
|
1033
|
-
raise "uninitialized LOB" unless available?
|
1034
|
-
begin
|
1035
|
-
rv = @locator.getLength(@svc)
|
1036
|
-
rescue OCIError
|
1037
|
-
raise if $!.code != 22289
|
1038
|
-
# ORA-22289: cannot perform FILEREAD operation on an unopened file or LOB.
|
1039
|
-
open
|
1040
|
-
retry
|
1041
|
-
end
|
1042
|
-
rv
|
1043
|
-
end
|
1044
|
-
|
1045
|
-
def size=(len)
|
1046
|
-
raise "uninitialized LOB" unless available?
|
1047
|
-
@locator.trim(@svc, len)
|
1048
|
-
len
|
1049
|
-
end
|
1050
|
-
|
1051
|
-
def chunk_size # in bytes.
|
1052
|
-
raise "uninitialized LOB" unless available?
|
1053
|
-
@locator.getChunkSize(@svc)
|
1054
|
-
end
|
1055
|
-
|
1056
|
-
def eof?
|
1057
|
-
@pos == size
|
1058
|
-
end
|
1059
|
-
|
1060
|
-
def tell
|
1061
|
-
@pos
|
1062
|
-
end
|
1063
|
-
|
1064
|
-
def seek(pos, whence = IO::SEEK_SET)
|
1065
|
-
length = size
|
1066
|
-
case whence
|
1067
|
-
when IO::SEEK_SET
|
1068
|
-
@pos = pos
|
1069
|
-
when IO::SEEK_CUR
|
1070
|
-
@pos += pos
|
1071
|
-
when IO::SEEK_END
|
1072
|
-
@pos = length + pos
|
1073
|
-
end
|
1074
|
-
@pos = length if @pos >= length
|
1075
|
-
@pos = 0 if @pos < 0
|
1076
|
-
self
|
1077
|
-
end
|
1078
|
-
|
1079
|
-
def rewind
|
1080
|
-
@pos = 0
|
1081
|
-
self
|
1082
|
-
end
|
1083
|
-
|
1084
|
-
def close
|
1085
|
-
@locator.free()
|
1086
|
-
end
|
1087
|
-
|
1088
|
-
end
|
1089
|
-
|
1090
|
-
class BLOB < LOB
|
1091
|
-
def initialize(*arg)
|
1092
|
-
@lobtype = 1
|
1093
|
-
@csfrm = SQLCS_IMPLICIT
|
1094
|
-
super(*arg)
|
1095
|
-
end
|
1096
|
-
end
|
1097
|
-
|
1098
|
-
class CLOB < LOB
|
1099
|
-
def initialize(*arg)
|
1100
|
-
@lobtype = 2
|
1101
|
-
@csfrm = SQLCS_IMPLICIT
|
1102
|
-
super(*arg)
|
1103
|
-
end
|
1104
|
-
end
|
1105
|
-
|
1106
|
-
class NCLOB < LOB
|
1107
|
-
def initialize(*arg)
|
1108
|
-
@lobtype = 2
|
1109
|
-
@csfrm = SQLCS_NCHAR
|
1110
|
-
super(*arg)
|
1111
|
-
end
|
1112
|
-
end
|
1113
|
-
|
1114
|
-
class BFILE < LOB
|
1115
|
-
attr_reader :dir_alias
|
1116
|
-
attr_reader :filename
|
1117
|
-
def initialize(svc, locator)
|
1118
|
-
raise "invalid argument" unless svc.is_a? OCISvcCtx
|
1119
|
-
raise "invalid argument" unless locator.is_a? OCIFileLocator
|
1120
|
-
@env = svc.instance_variable_get(:@env)
|
1121
|
-
@svc = svc
|
1122
|
-
@locator = locator
|
1123
|
-
@pos = 0
|
1124
|
-
@dir_alias, @filename = @locator.name(@env)
|
1125
|
-
end
|
1126
|
-
|
1127
|
-
def dir_alias=(val)
|
1128
|
-
@locator.set_name(@env, val, @filename)
|
1129
|
-
@dir_alias = val
|
1130
|
-
end
|
1131
|
-
|
1132
|
-
def filename=(val)
|
1133
|
-
@locator.set_name(@env, @dir_alias, val)
|
1134
|
-
@filename = val
|
1135
|
-
end
|
1136
|
-
|
1137
|
-
def truncate(len)
|
1138
|
-
raise RuntimeError, "cannot modify a read-only BFILE object"
|
1139
|
-
end
|
1140
|
-
def write(data)
|
1141
|
-
raise RuntimeError, "cannot modify a read-only BFILE object"
|
1142
|
-
end
|
1143
|
-
def size=(len)
|
1144
|
-
raise RuntimeError, "cannot modify a read-only BFILE object"
|
1145
|
-
end
|
1146
|
-
|
1147
|
-
def open
|
1148
|
-
begin
|
1149
|
-
@locator.open(@svc, :file_readonly)
|
1150
|
-
rescue OCIError
|
1151
|
-
raise if $!.code != 22290
|
1152
|
-
# ORA-22290: operation would exceed the maximum number of opened files or LOBs.
|
1153
|
-
@svc.close_all_files
|
1154
|
-
@locator.open(@svc, :file_readonly)
|
1155
|
-
end
|
1156
|
-
end
|
1157
|
-
|
1158
|
-
def exists?
|
1159
|
-
@locator.exists?(@svc)
|
1160
|
-
end
|
1161
|
-
end
|
1162
|
-
|
1163
|
-
# bind or explicitly define
|
1164
|
-
BindType::Mapping[::String] = BindType::String
|
1165
|
-
BindType::Mapping[::OCI8::RAW] = BindType::RAW
|
1166
|
-
BindType::Mapping[::OraDate] = BindType::OraDate
|
1167
|
-
BindType::Mapping[::Time] = BindType::Time
|
1168
|
-
BindType::Mapping[::Date] = BindType::Date
|
1169
|
-
BindType::Mapping[::DateTime] = BindType::DateTime if defined? DateTime
|
1170
|
-
BindType::Mapping[::OCIRowid] = BindType::OCIRowid
|
1171
|
-
BindType::Mapping[::OCI8::BLOB] = BindType::BLOB
|
1172
|
-
BindType::Mapping[::OCI8::CLOB] = BindType::CLOB
|
1173
|
-
BindType::Mapping[::OCI8::NCLOB] = BindType::NCLOB
|
1174
|
-
BindType::Mapping[::OCI8::BFILE] = BindType::BFILE
|
1175
|
-
BindType::Mapping[::OCI8::Cursor] = BindType::Cursor
|
1176
|
-
|
1177
|
-
# implicitly define
|
1178
|
-
|
1179
|
-
# datatype type size prec scale
|
1180
|
-
# -------------------------------------------------
|
1181
|
-
# CHAR(1) SQLT_AFC 1 0 0
|
1182
|
-
# CHAR(10) SQLT_AFC 10 0 0
|
1183
|
-
BindType::Mapping[OCI8::SQLT_AFC] = BindType::String
|
1184
|
-
|
1185
|
-
# datatype type size prec scale
|
1186
|
-
# -------------------------------------------------
|
1187
|
-
# VARCHAR(1) SQLT_CHR 1 0 0
|
1188
|
-
# VARCHAR(10) SQLT_CHR 10 0 0
|
1189
|
-
# VARCHAR2(1) SQLT_CHR 1 0 0
|
1190
|
-
# VARCHAR2(10) SQLT_CHR 10 0 0
|
1191
|
-
BindType::Mapping[OCI8::SQLT_CHR] = BindType::String
|
1192
|
-
|
1193
|
-
# datatype type size prec scale
|
1194
|
-
# -------------------------------------------------
|
1195
|
-
# RAW(1) SQLT_BIN 1 0 0
|
1196
|
-
# RAW(10) SQLT_BIN 10 0 0
|
1197
|
-
BindType::Mapping[OCI8::SQLT_BIN] = BindType::RAW
|
1198
|
-
|
1199
|
-
# datatype type size prec scale
|
1200
|
-
# -------------------------------------------------
|
1201
|
-
# LONG SQLT_LNG 0 0 0
|
1202
|
-
BindType::Mapping[OCI8::SQLT_LNG] = BindType::String
|
1203
|
-
|
1204
|
-
# datatype type size prec scale
|
1205
|
-
# -------------------------------------------------
|
1206
|
-
# LONG RAW SQLT_LBI 0 0 0
|
1207
|
-
BindType::Mapping[OCI8::SQLT_LBI] = BindType::RAW
|
1208
|
-
|
1209
|
-
# datatype type size prec scale
|
1210
|
-
# -------------------------------------------------
|
1211
|
-
# CLOB SQLT_CLOB 4000 0 0
|
1212
|
-
BindType::Mapping[OCI8::SQLT_CLOB] = BindType::CLOB
|
1213
|
-
BindType::Mapping[:nclob] = BindType::NCLOB # if OCI_ATTR_CHARSET_FORM is SQLCS_NCHAR.
|
1214
|
-
|
1215
|
-
# datatype type size prec scale
|
1216
|
-
# -------------------------------------------------
|
1217
|
-
# BLOB SQLT_BLOB 4000 0 0
|
1218
|
-
BindType::Mapping[OCI8::SQLT_BLOB] = BindType::BLOB
|
1219
|
-
|
1220
|
-
# datatype type size prec scale
|
1221
|
-
# -------------------------------------------------
|
1222
|
-
# BFILE SQLT_BFILE 4000 0 0
|
1223
|
-
BindType::Mapping[OCI8::SQLT_BFILE] = BindType::BFILE
|
1224
|
-
|
1225
|
-
# datatype type size prec scale
|
1226
|
-
# -------------------------------------------------
|
1227
|
-
# DATE SQLT_DAT 7 0 0
|
1228
|
-
BindType::Mapping[OCI8::SQLT_DAT] = BindType::OraDate
|
1229
|
-
|
1230
|
-
BindType::Mapping[OCI8::SQLT_TIMESTAMP] = BindType::OraDate
|
1231
|
-
|
1232
|
-
# datatype type size prec scale
|
1233
|
-
# -------------------------------------------------
|
1234
|
-
# ROWID SQLT_RDD 4 0 0
|
1235
|
-
BindType::Mapping[OCI8::SQLT_RDD] = BindType::String
|
1236
|
-
|
1237
|
-
# datatype type size prec scale
|
1238
|
-
# -----------------------------------------------------
|
1239
|
-
# FLOAT SQLT_NUM 22 126 -127
|
1240
|
-
# FLOAT(1) SQLT_NUM 22 1 -127
|
1241
|
-
# FLOAT(126) SQLT_NUM 22 126 -127
|
1242
|
-
# DOUBLE PRECISION SQLT_NUM 22 126 -127
|
1243
|
-
# REAL SQLT_NUM 22 63 -127
|
1244
|
-
# calculated value SQLT_NUM 22 0 0
|
1245
|
-
# NUMBER SQLT_NUM 22 0 0 (Oracle 9.2.0.2 or below)
|
1246
|
-
# NUMBER SQLT_NUM 22 0 -127 (Oracle 9.2.0.3 or above)
|
1247
|
-
# NUMBER(1) SQLT_NUM 22 1 0
|
1248
|
-
# NUMBER(38) SQLT_NUM 22 38 0
|
1249
|
-
# NUMBER(1, 0) SQLT_NUM 22 1 0
|
1250
|
-
# NUMBER(38, 0) SQLT_NUM 22 38 0
|
1251
|
-
# NUMERIC SQLT_NUM 22 38 0
|
1252
|
-
# INT SQLT_NUM 22 38 0
|
1253
|
-
# INTEGER SQLT_NUM 22 38 0
|
1254
|
-
# SMALLINT SQLT_NUM 22 38 0
|
1255
|
-
BindType::Mapping[OCI8::SQLT_NUM] = BindType::Number
|
1256
|
-
|
1257
|
-
# This parameter specify the ruby datatype for
|
1258
|
-
# calculated number values whose precision is unknown in advance.
|
1259
|
-
# select col1 * 1.1 from tab1;
|
1260
|
-
# For Oracle 9.2.0.2 or below, this is also used for NUMBER
|
1261
|
-
# datatypes that have no explicit setting of their precision
|
1262
|
-
# and scale.
|
1263
|
-
BindType::Mapping[:number_unknown_prec] = BindType::Float
|
1264
|
-
|
1265
|
-
# This parameter specify the ruby datatype for NUMBER datatypes
|
1266
|
-
# that have no explicit setting of their precision and scale.
|
1267
|
-
# create table tab1 (col1 number);
|
1268
|
-
# select col1 from tab1;
|
1269
|
-
# note: This is available only on Oracle 9.2.0.3 or above.
|
1270
|
-
# see: Oracle 9.2.0.x Patch Set Notes.
|
1271
|
-
BindType::Mapping[:number_no_prec_setting] = BindType::Float
|
1272
|
-
|
1273
|
-
# datatype type size prec scale
|
1274
|
-
# -------------------------------------------------
|
1275
|
-
# BINARY FLOAT SQLT_IBFLOAT 4 0 0
|
1276
|
-
# BINARY DOUBLE SQLT_IBDOUBLE 8 0 0
|
1277
|
-
if defined? BindType::BinaryDouble
|
1278
|
-
BindType::Mapping[OCI8::SQLT_IBFLOAT] = BindType::BinaryDouble
|
1279
|
-
BindType::Mapping[OCI8::SQLT_IBDOUBLE] = BindType::BinaryDouble
|
1280
|
-
else
|
1281
|
-
BindType::Mapping[OCI8::SQLT_IBFLOAT] = BindType::Float
|
1282
|
-
BindType::Mapping[OCI8::SQLT_IBDOUBLE] = BindType::Float
|
1283
|
-
end
|
1284
|
-
|
1285
|
-
# cursor in result set.
|
1286
|
-
BindType::Mapping[SQLT_RSET] = BindType::Cursor
|
1287
|
-
end # OCI8
|
1288
|
-
|
1289
|
-
class OraDate
|
1290
|
-
def to_time
|
1291
|
-
begin
|
1292
|
-
Time.local(year, month, day, hour, minute, second)
|
1293
|
-
rescue ArgumentError
|
1294
|
-
msg = format("out of range of Time (expect between 1970-01-01 00:00:00 UTC and 2037-12-31 23:59:59, but %04d-%02d-%02d %02d:%02d:%02d %s)", year, month, day, hour, minute, second, Time.at(0).zone)
|
1295
|
-
raise RangeError.new(msg)
|
1296
|
-
end
|
1297
|
-
end
|
1298
|
-
|
1299
|
-
def to_date
|
1300
|
-
Date.new(year, month, day)
|
1301
|
-
end
|
1302
|
-
|
1303
|
-
if defined? DateTime # ruby 1.8.0 or upper
|
1304
|
-
def to_datetime
|
1305
|
-
DateTime.new(year, month, day, hour, minute, second)
|
1306
|
-
end
|
1307
|
-
end
|
1308
|
-
|
1309
|
-
def yaml_initialize(type, val) # :nodoc:
|
1310
|
-
initialize(*val.split(/[ -\/:]+/).collect do |i| i.to_i end)
|
1311
|
-
end
|
1312
|
-
|
1313
|
-
def to_yaml(opts = {}) # :nodoc:
|
1314
|
-
YAML.quick_emit(object_id, opts) do |out|
|
1315
|
-
out.scalar(taguri, self.to_s, :plain)
|
1316
|
-
end
|
1317
|
-
end
|
1318
|
-
|
1319
|
-
def to_json(options=nil) # :nodoc:
|
1320
|
-
to_datetime.to_json(options)
|
1321
|
-
end
|
1322
|
-
end
|
1323
|
-
|
1324
|
-
class OraNumber
|
1325
|
-
def yaml_initialize(type, val) # :nodoc:
|
1326
|
-
initialize(val)
|
1327
|
-
end
|
1328
|
-
|
1329
|
-
def to_yaml(opts = {}) # :nodoc:
|
1330
|
-
YAML.quick_emit(object_id, opts) do |out|
|
1331
|
-
out.scalar(taguri, self.to_s, :plain)
|
1332
|
-
end
|
1333
|
-
end
|
1334
|
-
|
1335
|
-
def to_json(options=nil) # :nodoc:
|
1336
|
-
to_s
|
54
|
+
# Returns an OCI8::OracleVersion of the Oracle client version.
|
55
|
+
#
|
56
|
+
# If this library is configured without '--with-runtime-check',
|
57
|
+
# and compiled for Oracle 10.1 or lower, the major and minor
|
58
|
+
# numbers are determined at compile-time. The rests are zeros.
|
59
|
+
#
|
60
|
+
# If this library is configured with '--with-runtime-check'
|
61
|
+
# and the runtime Oracle library is Oracle 10.1 or lower, the
|
62
|
+
# major and minor numbers are determined at run-time. The
|
63
|
+
# rests are zeros.
|
64
|
+
#
|
65
|
+
# Otherwise, it is the version retrieved from an OCI function
|
66
|
+
# OCIClientVersion().
|
67
|
+
def self.oracle_client_version
|
68
|
+
@@oracle_client_version
|
1337
69
|
end
|
1338
70
|
end
|
1339
71
|
|
72
|
+
require 'oci8/datetime.rb'
|
73
|
+
require 'oci8/oci8.rb'
|
74
|
+
require 'oci8/metadata.rb'
|
75
|
+
require 'oci8/compat.rb'
|
76
|
+
require 'oci8/object.rb'
|
1340
77
|
|
1341
|
-
#
|
1342
|
-
# OCI8::Metadata::Column
|
1343
|
-
#
|
1344
78
|
class OCI8
|
1345
|
-
|
1346
|
-
|
1347
|
-
# Abstract super class for Metadata classes.
|
1348
|
-
class Base
|
1349
|
-
# This class's code was copied from svn trunk whick will be ruby-oci8 2.0.
|
1350
|
-
|
1351
|
-
# SQLT values to name
|
1352
|
-
DATA_TYPE_MAP = {} # :nodoc:
|
1353
|
-
TYPE_PROC_MAP = {} # :nodoc:
|
1354
|
-
|
1355
|
-
# SQLT_CHR
|
1356
|
-
DATA_TYPE_MAP[1] = :varchar2
|
1357
|
-
TYPE_PROC_MAP[1] = Proc.new do |p|
|
1358
|
-
if p.charset_form == :nchar
|
1359
|
-
"NVARCHAR2(#{p.char_size})"
|
1360
|
-
else
|
1361
|
-
if (p.respond_to? :char_used?) && (p.char_used?)
|
1362
|
-
"VARCHAR2(#{p.char_size} CHAR)"
|
1363
|
-
else
|
1364
|
-
"VARCHAR2(#{p.data_size})"
|
1365
|
-
end
|
1366
|
-
end
|
1367
|
-
end
|
1368
|
-
|
1369
|
-
# SQLT_NUM
|
1370
|
-
DATA_TYPE_MAP[2] = :number
|
1371
|
-
TYPE_PROC_MAP[2] = Proc.new do |p|
|
1372
|
-
begin
|
1373
|
-
case p.scale
|
1374
|
-
when -127
|
1375
|
-
case p.precision
|
1376
|
-
when 0
|
1377
|
-
"NUMBER"
|
1378
|
-
when 126
|
1379
|
-
"FLOAT"
|
1380
|
-
else
|
1381
|
-
"FLOAT(#{p.precision})"
|
1382
|
-
end
|
1383
|
-
when 0
|
1384
|
-
case p.precision
|
1385
|
-
when 0
|
1386
|
-
"NUMBER"
|
1387
|
-
else
|
1388
|
-
"NUMBER(#{p.precision})"
|
1389
|
-
end
|
1390
|
-
else
|
1391
|
-
"NUMBER(#{p.precision},#{p.scale})"
|
1392
|
-
end
|
1393
|
-
rescue OCIError
|
1394
|
-
"NUMBER"
|
1395
|
-
end
|
1396
|
-
end
|
1397
|
-
|
1398
|
-
# SQLT_LNG
|
1399
|
-
DATA_TYPE_MAP[8] = :long
|
1400
|
-
TYPE_PROC_MAP[8] = "LONG"
|
1401
|
-
|
1402
|
-
# SQLT_DAT
|
1403
|
-
DATA_TYPE_MAP[12] = :date
|
1404
|
-
TYPE_PROC_MAP[12] = "DATE"
|
1405
|
-
|
1406
|
-
# SQLT_BIN
|
1407
|
-
DATA_TYPE_MAP[23] = :raw
|
1408
|
-
TYPE_PROC_MAP[23] = Proc.new do |p|
|
1409
|
-
"RAW(#{p.data_size})"
|
1410
|
-
end
|
1411
|
-
|
1412
|
-
# SQLT_LBI
|
1413
|
-
DATA_TYPE_MAP[24] = :long_raw
|
1414
|
-
TYPE_PROC_MAP[24] = "LONG RAW"
|
1415
|
-
|
1416
|
-
# SQLT_AFC
|
1417
|
-
DATA_TYPE_MAP[96] = :char
|
1418
|
-
TYPE_PROC_MAP[96] = Proc.new do |p|
|
1419
|
-
if p.charset_form == :nchar
|
1420
|
-
"NCHAR(#{p.char_size})"
|
1421
|
-
else
|
1422
|
-
if (p.respond_to? :char_used?) && (p.char_used?)
|
1423
|
-
"CHAR(#{p.char_size} CHAR)"
|
1424
|
-
else
|
1425
|
-
"CHAR(#{p.data_size})"
|
1426
|
-
end
|
1427
|
-
end
|
1428
|
-
end
|
1429
|
-
|
1430
|
-
# SQLT_IBFLOAT
|
1431
|
-
DATA_TYPE_MAP[100] = :binary_float
|
1432
|
-
TYPE_PROC_MAP[100] = "BINARY_FLOAT"
|
1433
|
-
|
1434
|
-
# SQLT_IBDOUBLE
|
1435
|
-
DATA_TYPE_MAP[101] = :binary_double
|
1436
|
-
TYPE_PROC_MAP[101] = "BINARY_DOUBLE"
|
1437
|
-
|
1438
|
-
# SQLT_RDD
|
1439
|
-
DATA_TYPE_MAP[104] = :rowid
|
1440
|
-
TYPE_PROC_MAP[104] = "ROWID"
|
1441
|
-
|
1442
|
-
# SQLT_NTY
|
1443
|
-
DATA_TYPE_MAP[108] = :named_type
|
1444
|
-
TYPE_PROC_MAP[108] = "Object"
|
1445
|
-
|
1446
|
-
# SQLT_REF
|
1447
|
-
DATA_TYPE_MAP[110] = :ref
|
1448
|
-
TYPE_PROC_MAP[110] = "REF"
|
1449
|
-
|
1450
|
-
# SQLT_CLOB
|
1451
|
-
DATA_TYPE_MAP[112] = :clob
|
1452
|
-
TYPE_PROC_MAP[112] = Proc.new do |p|
|
1453
|
-
if p.charset_form == :nchar
|
1454
|
-
"NCLOB"
|
1455
|
-
else
|
1456
|
-
"CLOB"
|
1457
|
-
end
|
1458
|
-
end
|
1459
|
-
|
1460
|
-
# SQLT_BLOB
|
1461
|
-
DATA_TYPE_MAP[113] = :blob
|
1462
|
-
TYPE_PROC_MAP[113] = "BLOB"
|
1463
|
-
|
1464
|
-
# SQLT_BFILE
|
1465
|
-
DATA_TYPE_MAP[114] = :bfile
|
1466
|
-
TYPE_PROC_MAP[114] = "BFILE"
|
1467
|
-
|
1468
|
-
# SQLT_TIMESTAMP
|
1469
|
-
DATA_TYPE_MAP[187] = :timestamp
|
1470
|
-
TYPE_PROC_MAP[187] = Proc.new do |p|
|
1471
|
-
fsprecision = p.fsprecision
|
1472
|
-
if fsprecision == 6
|
1473
|
-
"TIMESTAMP"
|
1474
|
-
else
|
1475
|
-
"TIMESTAMP(#{fsprecision})"
|
1476
|
-
end
|
1477
|
-
end
|
1478
|
-
|
1479
|
-
# SQLT_TIMESTAMP_TZ
|
1480
|
-
DATA_TYPE_MAP[188] = :timestamp_tz
|
1481
|
-
TYPE_PROC_MAP[188] = Proc.new do |p|
|
1482
|
-
fsprecision = p.fsprecision
|
1483
|
-
if fsprecision == 6
|
1484
|
-
"TIMESTAMP WITH TIME ZONE"
|
1485
|
-
else
|
1486
|
-
"TIMESTAMP(#{fsprecision}) WITH TIME ZONE"
|
1487
|
-
end
|
1488
|
-
end
|
1489
|
-
|
1490
|
-
# SQLT_INTERVAL_YM
|
1491
|
-
DATA_TYPE_MAP[189] = :interval_ym
|
1492
|
-
TYPE_PROC_MAP[189] = Proc.new do |p|
|
1493
|
-
lfprecision = p.lfprecision
|
1494
|
-
if lfprecision == 2
|
1495
|
-
"INTERVAL YEAR TO MONTH"
|
1496
|
-
else
|
1497
|
-
"INTERVAL YEAR(#{lfprecision}) TO MONTH"
|
1498
|
-
end
|
1499
|
-
end
|
1500
|
-
|
1501
|
-
# SQLT_INTERVAL_DS
|
1502
|
-
DATA_TYPE_MAP[190] = :interval_ds
|
1503
|
-
TYPE_PROC_MAP[190] = Proc.new do |p|
|
1504
|
-
lfprecision = p.lfprecision
|
1505
|
-
fsprecision = p.fsprecision
|
1506
|
-
if lfprecision == 2 && fsprecision == 6
|
1507
|
-
"INTERVAL DAY TO SECOND"
|
1508
|
-
else
|
1509
|
-
"INTERVAL DAY(#{lfprecision}) TO SECOND(#{fsprecision})"
|
1510
|
-
end
|
1511
|
-
end
|
1512
|
-
|
1513
|
-
# SQLT_TIMESTAMP_LTZ
|
1514
|
-
DATA_TYPE_MAP[232] = :timestamp_ltz
|
1515
|
-
TYPE_PROC_MAP[232] = Proc.new do |p|
|
1516
|
-
fsprecision = p.fsprecision
|
1517
|
-
if fsprecision == 6
|
1518
|
-
"TIMESTAMP WITH LOCAL TIME ZONE"
|
1519
|
-
else
|
1520
|
-
"TIMESTAMP(#{fsprecision}) WITH LOCAL TIME ZONE"
|
1521
|
-
end
|
1522
|
-
end
|
1523
|
-
|
1524
|
-
def inspect # :nodoc:
|
1525
|
-
"#<#{self.class.name}:(#{@obj_id}) #{@obj_schema}.#{@obj_name}>"
|
1526
|
-
end
|
1527
|
-
|
1528
|
-
private
|
1529
|
-
|
1530
|
-
def __data_type(p)
|
1531
|
-
DATA_TYPE_MAP[p.attrGet(OCI_ATTR_DATA_TYPE)] || p.attrGet(OCI_ATTR_DATA_TYPE)
|
1532
|
-
end
|
1533
|
-
|
1534
|
-
def __type_string(p)
|
1535
|
-
type = TYPE_PROC_MAP[p.attrGet(OCI_ATTR_DATA_TYPE)] || "unknown(#{p.attrGet(OCI_ATTR_DATA_TYPE)})"
|
1536
|
-
type = type.call(self) if type.is_a? Proc
|
1537
|
-
if respond_to?(:nullable?) && !nullable?
|
1538
|
-
type + " NOT NULL"
|
1539
|
-
else
|
1540
|
-
type
|
1541
|
-
end
|
1542
|
-
end
|
1543
|
-
|
1544
|
-
def initialize_table_or_view(param)
|
1545
|
-
@num_cols = param.attrGet(OCI_ATTR_NUM_COLS)
|
1546
|
-
@obj_id = param.attrGet(OCI_ATTR_OBJ_ID)
|
1547
|
-
@obj_name = param.attrGet(OCI_ATTR_OBJ_NAME)
|
1548
|
-
@obj_schema = param.attrGet(OCI_ATTR_OBJ_SCHEMA)
|
1549
|
-
colparam = param.attrGet(OCI_ATTR_LIST_COLUMNS)
|
1550
|
-
@columns = []
|
1551
|
-
1.upto @num_cols do |i|
|
1552
|
-
@columns << OCI8::Metadata::Column.new(colparam.paramGet(i))
|
1553
|
-
end
|
1554
|
-
end
|
1555
|
-
end
|
1556
|
-
|
1557
|
-
class Table < Base
|
1558
|
-
attr_reader :num_cols
|
1559
|
-
attr_reader :obj_name
|
1560
|
-
attr_reader :obj_schema
|
1561
|
-
attr_reader :columns
|
1562
|
-
|
1563
|
-
def initialize(param)
|
1564
|
-
initialize_table_or_view(param)
|
1565
|
-
end
|
1566
|
-
end
|
1567
|
-
|
1568
|
-
class View < Base
|
1569
|
-
attr_reader :num_cols
|
1570
|
-
attr_reader :obj_name
|
1571
|
-
attr_reader :obj_schema
|
1572
|
-
attr_reader :columns
|
1573
|
-
|
1574
|
-
def initialize(param)
|
1575
|
-
initialize_table_or_view(param)
|
1576
|
-
end
|
1577
|
-
end
|
1578
|
-
|
1579
|
-
class Column < Base
|
1580
|
-
attr_reader :name
|
1581
|
-
attr_reader :type_string
|
1582
|
-
attr_reader :data_type
|
1583
|
-
attr_reader :charset_form
|
1584
|
-
def nullable?; @nullable; end
|
1585
|
-
|
1586
|
-
# string data type
|
1587
|
-
def char_used?; @char_used; end if defined? OCI_ATTR_CHAR_USED
|
1588
|
-
attr_reader :char_size if defined? OCI_ATTR_CHAR_SIZE
|
1589
|
-
attr_reader :data_size
|
1590
|
-
attr_reader :charset_id
|
1591
|
-
|
1592
|
-
# number data type
|
1593
|
-
attr_reader :precision
|
1594
|
-
attr_reader :scale
|
1595
|
-
|
1596
|
-
# interval
|
1597
|
-
if defined? OCI_ATTR_FSPRECISION and defined? OCI_ATTR_LFPRECISION
|
1598
|
-
# Oracle 8i or upper has OCI_ATTR_FSPRECISION and OCI_ATTR_LFPRECISION
|
1599
|
-
@@is_fsprecision_available = true
|
1600
|
-
else
|
1601
|
-
@@is_fsprecision_available = false
|
1602
|
-
end
|
1603
|
-
attr_reader :fsprecision
|
1604
|
-
attr_reader :lfprecision
|
1605
|
-
|
1606
|
-
def initialize(param)
|
1607
|
-
@name = param.attrGet(OCI_ATTR_NAME)
|
1608
|
-
@data_type = __data_type(param)
|
1609
|
-
|
1610
|
-
@data_size = param.attrGet(OCI_ATTR_DATA_SIZE)
|
1611
|
-
@char_used = param.attrGet(OCI_ATTR_CHAR_USED) if defined? OCI_ATTR_CHAR_USED
|
1612
|
-
@char_size = param.attrGet(OCI_ATTR_CHAR_SIZE) if defined? OCI_ATTR_CHAR_SIZE
|
1613
|
-
|
1614
|
-
@precision = param.attrGet(OCI_ATTR_PRECISION)
|
1615
|
-
@scale = param.attrGet(OCI_ATTR_SCALE)
|
1616
|
-
@nullable = param.attrGet(OCI_ATTR_IS_NULL)
|
1617
|
-
@charset_id = param.attrGet(OCI_ATTR_CHARSET_ID)
|
1618
|
-
@charset_form = case param.attrGet(OCI_ATTR_CHARSET_FORM)
|
1619
|
-
when 0: nil
|
1620
|
-
when 1; :implicit
|
1621
|
-
when 2; :nchar
|
1622
|
-
when 3; :explicit
|
1623
|
-
when 4; :flexible
|
1624
|
-
when 5; :lit_null
|
1625
|
-
else raise "unknown charset_form #{param.attrGet(OCI_ATTR_CHARSET_FORM)}"
|
1626
|
-
end
|
1627
|
-
|
1628
|
-
@fsprecision = nil
|
1629
|
-
@lfprecision = nil
|
1630
|
-
if @@is_fsprecision_available
|
1631
|
-
begin
|
1632
|
-
@fsprecision = param.attrGet(OCI_ATTR_FSPRECISION)
|
1633
|
-
@lfprecision = param.attrGet(OCI_ATTR_LFPRECISION)
|
1634
|
-
rescue OCIError
|
1635
|
-
raise if $!.code != 24316 # ORA-24316: illegal handle type
|
1636
|
-
# Oracle 8i could not use OCI_ATTR_FSPRECISION and
|
1637
|
-
# OCI_ATTR_LFPRECISION even though it defines these
|
1638
|
-
# constants in oci.h.
|
1639
|
-
@@is_fsprecision_available = false
|
1640
|
-
end
|
1641
|
-
end
|
1642
|
-
|
1643
|
-
@type_string = __type_string(param)
|
1644
|
-
end
|
1645
|
-
|
1646
|
-
def to_s
|
1647
|
-
%Q{"#{@name}" #{@type_string}}
|
1648
|
-
end
|
1649
|
-
|
1650
|
-
def inspect # :nodoc:
|
1651
|
-
"#<#{self.class.name}: #{@name} #{@type_string}>"
|
1652
|
-
end
|
1653
|
-
end
|
1654
|
-
end
|
79
|
+
VERSION = '@@OCI8_MODULE_VERSION@@'
|
80
|
+
CLIENT_VERSION = '@@OCI8_CLIENT_VERSION@@'
|
1655
81
|
end
|