ruby-oci8-master 2.0.7

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.
Files changed (84) hide show
  1. data/ChangeLog +2321 -0
  2. data/Makefile +88 -0
  3. data/NEWS +303 -0
  4. data/README +76 -0
  5. data/VERSION +1 -0
  6. data/dist-files +83 -0
  7. data/doc/api.en.html +527 -0
  8. data/doc/api.en.rd +554 -0
  9. data/doc/api.ja.html +525 -0
  10. data/doc/api.ja.rd +557 -0
  11. data/doc/manual.css +35 -0
  12. data/ext/oci8/.document +18 -0
  13. data/ext/oci8/MANIFEST +18 -0
  14. data/ext/oci8/apiwrap.c.tmpl +182 -0
  15. data/ext/oci8/apiwrap.h.tmpl +61 -0
  16. data/ext/oci8/apiwrap.rb +91 -0
  17. data/ext/oci8/apiwrap.yml +1455 -0
  18. data/ext/oci8/attr.c +105 -0
  19. data/ext/oci8/bind.c +366 -0
  20. data/ext/oci8/connection_pool.c +199 -0
  21. data/ext/oci8/encoding.c +289 -0
  22. data/ext/oci8/env.c +178 -0
  23. data/ext/oci8/error.c +378 -0
  24. data/ext/oci8/extconf.rb +179 -0
  25. data/ext/oci8/lob.c +805 -0
  26. data/ext/oci8/metadata.c +232 -0
  27. data/ext/oci8/object.c +727 -0
  28. data/ext/oci8/oci8.c +1156 -0
  29. data/ext/oci8/oci8.h +574 -0
  30. data/ext/oci8/oci8lib.c +527 -0
  31. data/ext/oci8/ocidatetime.c +484 -0
  32. data/ext/oci8/ocihandle.c +751 -0
  33. data/ext/oci8/ocinumber.c +1612 -0
  34. data/ext/oci8/oraconf.rb +1119 -0
  35. data/ext/oci8/oradate.c +611 -0
  36. data/ext/oci8/oranumber_util.c +352 -0
  37. data/ext/oci8/oranumber_util.h +24 -0
  38. data/ext/oci8/post-config.rb +5 -0
  39. data/ext/oci8/stmt.c +673 -0
  40. data/ext/oci8/thread_util.c +85 -0
  41. data/ext/oci8/thread_util.h +30 -0
  42. data/ext/oci8/win32.c +137 -0
  43. data/lib/.document +1 -0
  44. data/lib/dbd/OCI8.rb +591 -0
  45. data/lib/oci8.rb.in +94 -0
  46. data/lib/oci8/.document +8 -0
  47. data/lib/oci8/bindtype.rb +349 -0
  48. data/lib/oci8/compat.rb +113 -0
  49. data/lib/oci8/connection_pool.rb +99 -0
  50. data/lib/oci8/datetime.rb +611 -0
  51. data/lib/oci8/encoding-init.rb +74 -0
  52. data/lib/oci8/encoding.yml +537 -0
  53. data/lib/oci8/metadata.rb +2132 -0
  54. data/lib/oci8/object.rb +581 -0
  55. data/lib/oci8/oci8.rb +721 -0
  56. data/lib/oci8/ocihandle.rb +425 -0
  57. data/lib/oci8/oracle_version.rb +144 -0
  58. data/lib/oci8/properties.rb +73 -0
  59. data/metaconfig +142 -0
  60. data/pre-distclean.rb +7 -0
  61. data/ruby-oci8.gemspec +63 -0
  62. data/setup.rb +1331 -0
  63. data/test/README +4 -0
  64. data/test/config.rb +122 -0
  65. data/test/test_all.rb +51 -0
  66. data/test/test_appinfo.rb +63 -0
  67. data/test/test_array_dml.rb +333 -0
  68. data/test/test_bind_raw.rb +46 -0
  69. data/test/test_bind_time.rb +178 -0
  70. data/test/test_break.rb +96 -0
  71. data/test/test_clob.rb +82 -0
  72. data/test/test_connstr.rb +81 -0
  73. data/test/test_datetime.rb +582 -0
  74. data/test/test_dbi.rb +366 -0
  75. data/test/test_dbi_clob.rb +53 -0
  76. data/test/test_encoding.rb +100 -0
  77. data/test/test_error.rb +88 -0
  78. data/test/test_metadata.rb +1399 -0
  79. data/test/test_oci8.rb +434 -0
  80. data/test/test_oracle_version.rb +70 -0
  81. data/test/test_oradate.rb +256 -0
  82. data/test/test_oranumber.rb +746 -0
  83. data/test/test_rowid.rb +33 -0
  84. metadata +137 -0
@@ -0,0 +1,88 @@
1
+ require 'oci8'
2
+ require 'test/unit'
3
+ require File.dirname(__FILE__) + '/config'
4
+
5
+ class TestError < Test::Unit::TestCase
6
+ def setup
7
+ @conn = get_oci8_connection
8
+ end
9
+
10
+ def teardown
11
+ @conn.logoff
12
+ end
13
+
14
+ def test_sql_parse_error
15
+ sql = 'select * from'
16
+ begin
17
+ @conn.exec(sql) # raises "ORA-00903: invalid table name"
18
+ rescue OCIException
19
+ assert_instance_of(OCIError, $!)
20
+ assert_match(/^ORA-00903: /, $!.to_s)
21
+ assert_equal(903, $!.code)
22
+ assert_equal(13, $!.parse_error_offset)
23
+ assert_equal(13, $!.parseErrorOffset) # barkward compatibility
24
+ assert_equal(sql, $!.sql)
25
+ end
26
+ end
27
+
28
+ def test_plsql_parse_error
29
+ sql = <<EOS
30
+ BEGIN
31
+ SELECT dummy INTO l_dummy FROM dual WHERE 1=2;
32
+ END;
33
+ EOS
34
+ begin
35
+ @conn.exec(sql) # raises "ORA-06550: line 2, column 21"
36
+ rescue OCIException
37
+ assert_instance_of(OCIError, $!)
38
+ assert_match(/^ORA-06550: /, $!.to_s)
39
+ assert_equal(6550, $!.code)
40
+ assert_equal(26, $!.parse_error_offset)
41
+ assert_equal(26, $!.parseErrorOffset) # barkward compatibility
42
+ assert_equal(sql, $!.sql)
43
+ end
44
+ end
45
+
46
+ def test_plsql_error_in_execution
47
+ sql = <<EOS
48
+ DECLARE
49
+ l_dummy VARCHAR2(50);
50
+ BEGIN
51
+ SELECT * INTO l_dummy
52
+ FROM (SELECT DUMMY FROM DUAL
53
+ UNION ALL
54
+ SELECT DUMMY FROM DUAL);
55
+ END;
56
+ EOS
57
+ begin
58
+ @conn.exec(sql) # raises "ORA-01422: exact fetch returns more than requested number of rows"
59
+ rescue OCIException
60
+ assert_instance_of(OCIError, $!)
61
+ assert_match(/^ORA-01422: /, $!.to_s)
62
+ assert_equal(1422, $!.code)
63
+ assert_equal(0, $!.parse_error_offset)
64
+ assert_equal(0, $!.parseErrorOffset) # barkward compatibility
65
+ assert_equal(sql, $!.sql)
66
+ end
67
+ end
68
+
69
+ def test_nodata
70
+ sql = <<EOS
71
+ DECLARE
72
+ l_dummy VARCHAR2(50);
73
+ BEGIN
74
+ SELECT dummy INTO l_dummy FROM dual WHERE 1=2;
75
+ END;
76
+ EOS
77
+ begin
78
+ @conn.exec(sql) # raises "ORA-01403: no data found"
79
+ rescue OCIException
80
+ assert_instance_of(OCINoData, $!)
81
+ assert_match(/^ORA-01403: /, $!.to_s)
82
+ assert_equal(1403, $!.code)
83
+ assert_equal(0, $!.parse_error_offset)
84
+ assert_equal(0, $!.parseErrorOffset) # barkward compatibility
85
+ assert_equal(sql, $!.sql)
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,1399 @@
1
+ require 'oci8'
2
+ require 'test/unit'
3
+ require File.dirname(__FILE__) + '/config'
4
+
5
+ class TestMetadata < Test::Unit::TestCase
6
+
7
+ def setup
8
+ @conn = get_oci8_connection
9
+ end
10
+
11
+ def teardown
12
+ @conn.logoff
13
+ end
14
+
15
+ def drop_type(name, drop_body = false)
16
+ if drop_body
17
+ begin
18
+ @conn.exec("DROP TYPE BODY #{name}")
19
+ rescue OCIError
20
+ raise if $!.code != 4043
21
+ end
22
+ end
23
+ begin
24
+ @conn.exec("DROP TYPE #{name}")
25
+ rescue OCIError
26
+ raise if $!.code != 4043
27
+ end
28
+ end
29
+
30
+ class DatatypeData
31
+ @@attributes =
32
+ [:data_type_string,
33
+ :data_type,
34
+ :charset_form,
35
+ :nullable?,
36
+ :data_size,
37
+ :precision,
38
+ :scale,
39
+ ]
40
+ @@attributes +=
41
+ [
42
+ :char_used?,
43
+ :char_size,
44
+ :fsprecision,
45
+ :lfprecision,
46
+ ] if $oracle_version >= OCI8::ORAVER_9_0
47
+
48
+ @@attributes.each do |attr|
49
+ define_method attr do
50
+ @table[attr]
51
+ end
52
+ end
53
+
54
+ def self.attributes
55
+ @@attributes
56
+ end
57
+
58
+ def initialize(hash = {})
59
+ @table = hash
60
+ end
61
+
62
+ def oraver
63
+ @table[:oraver]
64
+ end
65
+ end
66
+
67
+ # Get data_size of NCHAR(1) and that of CHAR(1 CHAR).
68
+ # They depend on the database character set and the
69
+ # client character set.
70
+ conn = OCI8.new($dbuser, $dbpass, $dbname)
71
+ begin
72
+ cursor = conn.exec("select N'1' from dual")
73
+ # cfrm: data_size of NCHAR(1).
74
+ cfrm = cursor.column_metadata[0].data_size
75
+ if $oracle_version >= OCI8::ORAVER_9_0
76
+ # csem: data_size of CHAR(1 CHAR).
77
+ cursor = conn.exec("select CAST('1' AS CHAR(1 char)) from dual")
78
+ csem = cursor.column_metadata[0].data_size
79
+ else
80
+ csem = 1
81
+ end
82
+ ensure
83
+ conn.logoff
84
+ end
85
+
86
+ ora80 = OCI8::ORAVER_8_0
87
+ ora81 = OCI8::ORAVER_8_1
88
+ ora90 = OCI8::ORAVER_9_0
89
+ ora101 = OCI8::ORAVER_10_1
90
+
91
+ @@column_test_data =
92
+ [
93
+ DatatypeData.new(:data_type_string => "CHAR(10) NOT NULL",
94
+ :oraver => ora80,
95
+ :data_type => :char,
96
+ :charset_form => :implicit,
97
+ :nullable? => false,
98
+ :char_used? => false,
99
+ :char_size => 10,
100
+ :data_size => 10,
101
+ :precision => 0,
102
+ :scale => 0,
103
+ :fsprecision => 0,
104
+ :lfprecision => 0
105
+ ),
106
+ DatatypeData.new(:data_type_string => "CHAR(10 CHAR)",
107
+ :oraver => ora90,
108
+ :data_type => :char,
109
+ :charset_form => :implicit,
110
+ :nullable? => true,
111
+ :char_used? => true,
112
+ :char_size => 10,
113
+ :data_size => 10 * csem,
114
+ :precision => 0,
115
+ :scale => 0,
116
+ :fsprecision => 0,
117
+ :lfprecision => 0
118
+ ),
119
+ DatatypeData.new(:data_type_string => "NCHAR(10)",
120
+ :oraver => ora80,
121
+ :data_type => :char,
122
+ :charset_form => :nchar,
123
+ :nullable? => true,
124
+ :char_used? => true,
125
+ :char_size => 10,
126
+ :data_size => 10 * cfrm,
127
+ :precision => 0,
128
+ :scale => 0,
129
+ :fsprecision => 0,
130
+ :lfprecision => 0
131
+ ),
132
+ DatatypeData.new(:data_type_string => "VARCHAR2(10)",
133
+ :oraver => ora80,
134
+ :data_type => :varchar2,
135
+ :charset_form => :implicit,
136
+ :nullable? => true,
137
+ :char_used? => false,
138
+ :char_size => 10,
139
+ :data_size => 10,
140
+ :precision => 0,
141
+ :scale => 0,
142
+ :fsprecision => 0,
143
+ :lfprecision => 0
144
+ ),
145
+ DatatypeData.new(:data_type_string => "VARCHAR2(10 CHAR)",
146
+ :oraver => ora90,
147
+ :data_type => :varchar2,
148
+ :charset_form => :implicit,
149
+ :nullable? => true,
150
+ :char_used? => true,
151
+ :char_size => 10,
152
+ :data_size => 10 * csem,
153
+ :precision => 0,
154
+ :scale => 0,
155
+ :fsprecision => 0,
156
+ :lfprecision => 0
157
+ ),
158
+ DatatypeData.new(:data_type_string => "NVARCHAR2(10)",
159
+ :oraver => ora80,
160
+ :data_type => :varchar2,
161
+ :charset_form => :nchar,
162
+ :nullable? => true,
163
+ :char_used? => true,
164
+ :char_size => 10,
165
+ :data_size => 10 * cfrm,
166
+ :precision => 0,
167
+ :scale => 0,
168
+ :fsprecision => 0,
169
+ :lfprecision => 0
170
+ ),
171
+ DatatypeData.new(:data_type_string => "RAW(10)",
172
+ :oraver => ora80,
173
+ :data_type => :raw,
174
+ :charset_form => nil,
175
+ :nullable? => true,
176
+ :char_used? => false,
177
+ :char_size => 0,
178
+ :data_size => 10,
179
+ :precision => 0,
180
+ :scale => 0,
181
+ :fsprecision => 0,
182
+ :lfprecision => 0
183
+ ),
184
+
185
+ # Skip tests for data_size of CLOB, NCLOB and BLOB
186
+ # because their values depend on how they are described.
187
+ #
188
+ # Oracle 10g XE 10.2.0.1.0 on Linux:
189
+ # +----------------+-----------+
190
+ # | | data_size |
191
+ # +----------------+-----------+
192
+ # | implicitly(*1) | 4000 |
193
+ # | explicitly(*2) | 86 |
194
+ # +----------------+-----------+
195
+ #
196
+ # *1 explicitly described by column definition.
197
+ # *2 implicitly described by select list.
198
+ DatatypeData.new(:data_type_string => "CLOB",
199
+ :oraver => ora81,
200
+ :data_type => :clob,
201
+ :charset_form => :implicit,
202
+ :nullable? => true,
203
+ :char_used? => false,
204
+ :char_size => 0,
205
+ :data_size => :skip,
206
+ :precision => 0,
207
+ :scale => 0,
208
+ :fsprecision => 0,
209
+ :lfprecision => 0
210
+ ),
211
+ DatatypeData.new(:data_type_string => "NCLOB",
212
+ :oraver => ora81,
213
+ :data_type => :clob,
214
+ :charset_form => :nchar,
215
+ :nullable? => true,
216
+ :char_used? => false,
217
+ :char_size => 0,
218
+ :data_size => :skip,
219
+ :precision => 0,
220
+ :scale => 0,
221
+ :fsprecision => 0,
222
+ :lfprecision => 0
223
+ ),
224
+ DatatypeData.new(:data_type_string => "BLOB",
225
+ :oraver => ora80,
226
+ :data_type => :blob,
227
+ :charset_form => nil,
228
+ :nullable? => true,
229
+ :char_used? => false,
230
+ :char_size => 0,
231
+ :data_size => :skip,
232
+ :precision => 0,
233
+ :scale => 0,
234
+ :fsprecision => 0,
235
+ :lfprecision => 0
236
+ ),
237
+ DatatypeData.new(:data_type_string => "BFILE",
238
+ :oraver => ora80,
239
+ :data_type => :bfile,
240
+ :charset_form => nil,
241
+ :nullable? => true,
242
+ :char_used? => false,
243
+ :char_size => 0,
244
+ :data_size => 530,
245
+ :precision => 0,
246
+ :scale => 0,
247
+ :fsprecision => 0,
248
+ :lfprecision => 0
249
+ ),
250
+
251
+ # Skip tests for fsprecision and lfprecision for NUMBER and FLOAT
252
+ # because their values depend on how they are described.
253
+ #
254
+ # Oracle 10g XE 10.2.0.1.0 on Linux:
255
+ # +-----------------------------+-------------+-------------+
256
+ # | | fsprecision | lfprecision |
257
+ # +----------------+------------+-------------+-------------+
258
+ # | NUMBER | implicitly | 129 | 0 |
259
+ # | | explicitly | 0 | 129 |
260
+ # +----------------+------------+-------------+-------------+
261
+ # | NUMBER(10) | implicitly | 0 | 10 |
262
+ # | | explicitly | 10 | 0 |
263
+ # +----------------+------------+-------------+-------------+
264
+ # | NUMBER(10,2) | implicitly | 2 | 10 |
265
+ # | | explicitly | 10 | 2 |
266
+ # +----------------+------------+-------------+-------------+
267
+ # | FLOAT | implicitly | 129 | 126 |
268
+ # | | explicitly | 126 | 129 |
269
+ # +----------------+------------+-------------+-------------+
270
+ # | FLOAT(10) | implicitly | 129 | 10 |
271
+ # | | explicitly | 10 | 129 |
272
+ # +----------------+------------+-------------+-------------+
273
+ DatatypeData.new(:data_type_string => "NUMBER",
274
+ :oraver => ora80,
275
+ :data_type => :number,
276
+ :charset_form => nil,
277
+ :nullable? => true,
278
+ :char_used? => false,
279
+ :char_size => 0,
280
+ :data_size => 22,
281
+ :precision => 0,
282
+ :scale => $oracle_version > ora90 ? -127 : 0,
283
+ :fsprecision => :skip,
284
+ :lfprecision => :skip
285
+ ),
286
+ DatatypeData.new(:data_type_string => "NUMBER(10)",
287
+ :oraver => ora80,
288
+ :data_type => :number,
289
+ :charset_form => nil,
290
+ :nullable? => true,
291
+ :char_used? => false,
292
+ :char_size => 0,
293
+ :data_size => 22,
294
+ :precision => 10,
295
+ :scale => 0,
296
+ :fsprecision => :skip,
297
+ :lfprecision => :skip
298
+ ),
299
+ DatatypeData.new(:data_type_string => "NUMBER(10,2)",
300
+ :oraver => ora80,
301
+ :data_type => :number,
302
+ :charset_form => nil,
303
+ :nullable? => true,
304
+ :char_used? => false,
305
+ :char_size => 0,
306
+ :data_size => 22,
307
+ :precision => 10,
308
+ :scale => 2,
309
+ :fsprecision => :skip,
310
+ :lfprecision => :skip
311
+ ),
312
+ DatatypeData.new(:data_type_string => "FLOAT",
313
+ :oraver => ora80,
314
+ :data_type => :number,
315
+ :charset_form => nil,
316
+ :nullable? => true,
317
+ :char_used? => false,
318
+ :char_size => 0,
319
+ :data_size => 22,
320
+ :precision => 126,
321
+ :scale => -127,
322
+ :fsprecision => :skip,
323
+ :lfprecision => :skip
324
+ ),
325
+ DatatypeData.new(:data_type_string => "FLOAT(10)",
326
+ :oraver => ora80,
327
+ :data_type => :number,
328
+ :charset_form => nil,
329
+ :nullable? => true,
330
+ :char_used? => false,
331
+ :char_size => 0,
332
+ :data_size => 22,
333
+ :precision => 10,
334
+ :scale => -127,
335
+ :fsprecision => :skip,
336
+ :lfprecision => :skip
337
+ ),
338
+ DatatypeData.new(:data_type_string => "BINARY_FLOAT",
339
+ :oraver => ora101,
340
+ :data_type => :binary_float,
341
+ :charset_form => nil,
342
+ :nullable? => true,
343
+ :char_used? => false,
344
+ :char_size => 0,
345
+ :data_size => 4,
346
+ :precision => 0,
347
+ :scale => 0,
348
+ :fsprecision => 0,
349
+ :lfprecision => 0
350
+ ),
351
+ DatatypeData.new(:data_type_string => "BINARY_DOUBLE",
352
+ :oraver => ora101,
353
+ :data_type => :binary_double,
354
+ :charset_form => nil,
355
+ :nullable? => true,
356
+ :char_used? => false,
357
+ :char_size => 0,
358
+ :data_size => 8,
359
+ :precision => 0,
360
+ :scale => 0,
361
+ :fsprecision => 0,
362
+ :lfprecision => 0
363
+ ),
364
+ DatatypeData.new(:data_type_string => "DATE",
365
+ :oraver => ora80,
366
+ :data_type => :date,
367
+ :charset_form => nil,
368
+ :nullable? => true,
369
+ :char_used? => false,
370
+ :char_size => 0,
371
+ :data_size => 7,
372
+ :precision => 0,
373
+ :scale => 0,
374
+ :fsprecision => 0,
375
+ :lfprecision => 0
376
+ ),
377
+
378
+ # Skip tests for precision and lfprecision for TIMESTAMP
379
+ # because their values depend on how they are described.
380
+ #
381
+ # Oracle 10g XE 10.2.0.1.0 on Linux:
382
+ # +------------------------------------------------+-----------+-------------+
383
+ # | | precision | lfprecision |
384
+ # +-----------------------------------+------------+-----------+-------------+
385
+ # | TIMESTAMP | implicitly | 0 | 0 |
386
+ # | | explicitly | 6 | 6 |
387
+ # +-----------------------------------+------------+-----------+-------------+
388
+ # | TIMESTAMP(9) | implicitly | 0 | 0 |
389
+ # | | explicitly | 9 | 9 |
390
+ # +-----------------------------------+------------+-----------+-------------+
391
+ # | TIMESTAMP WITH TIME ZONE | implicitly | 0 | 0 |
392
+ # | | explicitly | 6 | 6 |
393
+ # +-----------------------------------+------------+-----------+-------------+
394
+ # | TIMESTAMP(9) WITH TIME ZONE | implicitly | 0 | 0 |
395
+ # | | explicitly | 9 | 9 |
396
+ # +-----------------------------------+------------+-----------+-------------+
397
+ # | TIMESTAMP WITH LOCAL TIME ZONE | implicitly | 0 | 0 |
398
+ # | | explicitly | 6 | 6 |
399
+ # +-----------------------------------+------------+-----------+-------------+
400
+ # | TIMESTAMP(9) WITH LOCAL TIME ZONE | implicitly | 0 | 0 |
401
+ # | | explicitly | 9 | 9 |
402
+ # +-----------------------------------+------------+-----------+-------------+
403
+ DatatypeData.new(:data_type_string => "TIMESTAMP",
404
+ :oraver => ora90,
405
+ :data_type => :timestamp,
406
+ :charset_form => nil,
407
+ :nullable? => true,
408
+ :char_used? => false,
409
+ :char_size => 0,
410
+ :data_size => 11,
411
+ :precision => :skip,
412
+ :scale => 6,
413
+ :fsprecision => 6,
414
+ :lfprecision => :skip
415
+ ),
416
+ DatatypeData.new(:data_type_string => "TIMESTAMP(9)",
417
+ :oraver => ora90,
418
+ :data_type => :timestamp,
419
+ :charset_form => nil,
420
+ :nullable? => true,
421
+ :char_used? => false,
422
+ :char_size => 0,
423
+ :data_size => 11,
424
+ :precision => :skip,
425
+ :scale => 9,
426
+ :fsprecision => 9,
427
+ :lfprecision => :skip
428
+ ),
429
+ DatatypeData.new(:data_type_string => "TIMESTAMP WITH TIME ZONE",
430
+ :oraver => ora90,
431
+ :data_type => :timestamp_tz,
432
+ :charset_form => nil,
433
+ :nullable? => true,
434
+ :char_used? => false,
435
+ :char_size => 0,
436
+ :data_size => 13,
437
+ :precision => :skip,
438
+ :scale => 6,
439
+ :fsprecision => 6,
440
+ :lfprecision => :skip
441
+ ),
442
+ DatatypeData.new(:data_type_string => "TIMESTAMP(9) WITH TIME ZONE",
443
+ :oraver => ora90,
444
+ :data_type => :timestamp_tz,
445
+ :charset_form => nil,
446
+ :nullable? => true,
447
+ :char_used? => false,
448
+ :char_size => 0,
449
+ :data_size => 13,
450
+ :precision => :skip,
451
+ :scale => 9,
452
+ :fsprecision => 9,
453
+ :lfprecision => :skip
454
+ ),
455
+ DatatypeData.new(:data_type_string => "TIMESTAMP WITH LOCAL TIME ZONE",
456
+ :oraver => ora90,
457
+ :data_type => :timestamp_ltz,
458
+ :charset_form => nil,
459
+ :nullable? => true,
460
+ :char_used? => false,
461
+ :char_size => 0,
462
+ :data_size => 11,
463
+ :precision => :skip,
464
+ :scale => 6,
465
+ :fsprecision => 6,
466
+ :lfprecision => :skip
467
+ ),
468
+ DatatypeData.new(:data_type_string => "TIMESTAMP(9) WITH LOCAL TIME ZONE",
469
+ :oraver => ora90,
470
+ :data_type => :timestamp_ltz,
471
+ :charset_form => nil,
472
+ :nullable? => true,
473
+ :char_used? => false,
474
+ :char_size => 0,
475
+ :data_size => 11,
476
+ :precision => :skip,
477
+ :scale => 9,
478
+ :fsprecision => 9,
479
+ :lfprecision => :skip
480
+ ),
481
+
482
+ # Skip tsets for scale and fsprecision for INTERVAL YEAR TO MONTH
483
+ # because their values depend on how they are described.
484
+ #
485
+ # Oracle 10g XE 10.2.0.1.0 on Linux:
486
+ # +-------------------------------------------+-----------+-------------+
487
+ # | | scale | fsprecision |
488
+ # +------------------------------+------------+-----------+-------------+
489
+ # | INTERVAL YEAR TO MONTH | implicitly | 0 | 0 |
490
+ # | | explicitly | 2 | 2 |
491
+ # +------------------------------+------------+-----------+-------------+
492
+ # | INTERVAL YEAR(4) TO MONTH | implicitly | 0 | 0 |
493
+ # | | explicitly | 4 | 4 |
494
+ # +------------------------------+------------+-----------+-------------+
495
+ DatatypeData.new(:data_type_string => "INTERVAL YEAR TO MONTH",
496
+ :oraver => ora90,
497
+ :data_type => :interval_ym,
498
+ :charset_form => nil,
499
+ :nullable? => true,
500
+ :char_used? => false,
501
+ :char_size => 0,
502
+ :data_size => 5,
503
+ :precision => 2,
504
+ :scale => :skip,
505
+ :fsprecision => :skip,
506
+ :lfprecision => 2
507
+ ),
508
+ DatatypeData.new(:data_type_string => "INTERVAL YEAR(4) TO MONTH",
509
+ :oraver => ora90,
510
+ :data_type => :interval_ym,
511
+ :charset_form => nil,
512
+ :nullable? => true,
513
+ :char_used? => false,
514
+ :char_size => 0,
515
+ :data_size => 5,
516
+ :precision => 4,
517
+ :scale => :skip,
518
+ :fsprecision => :skip,
519
+ :lfprecision => 4
520
+ ),
521
+ # Skip tests for precision and scale for INTERVAL DAY TO SECOND
522
+ # because their values depend on how they are described.
523
+ #
524
+ # Oracle 10g XE 10.2.0.1.0 on Linux:
525
+ # +-------------------------------------------+-----------+-----------+
526
+ # | | precision | scale |
527
+ # +------------------------------+------------+-----------+-----------+
528
+ # | INTERVAL DAY TO SECOND | implicitly | 2 | 6 |
529
+ # | | explicitly | 6 | 2 |
530
+ # +------------------------------+------------+-----------+-----------+
531
+ # | INTERVAL DAY(4) TO SECOND(9) | implicitly | 4 | 9 |
532
+ # | | explicitly | 9 | 4 |
533
+ # +------------------------------+------------+-----------+-----------+
534
+ DatatypeData.new(:data_type_string => "INTERVAL DAY TO SECOND",
535
+ :oraver => ora90,
536
+ :data_type => :interval_ds,
537
+ :charset_form => nil,
538
+ :nullable? => true,
539
+ :char_used? => false,
540
+ :char_size => 0,
541
+ :data_size => 11,
542
+ :precision => :skip,
543
+ :scale => :skip,
544
+ :fsprecision => 6,
545
+ :lfprecision => 2
546
+ ),
547
+ DatatypeData.new(:data_type_string => "INTERVAL DAY(4) TO SECOND(9)",
548
+ :oraver => ora90,
549
+ :data_type => :interval_ds,
550
+ :charset_form => nil,
551
+ :nullable? => true,
552
+ :char_used? => false,
553
+ :char_size => 0,
554
+ :data_size => 11,
555
+ :precision => :skip,
556
+ :scale => :skip,
557
+ :fsprecision => 9,
558
+ :lfprecision => 4
559
+ ),
560
+ # Object Types
561
+ DatatypeData.new(:data_type_string => "MDSYS.SDO_GEOMETRY",
562
+ :oraver => ora101,
563
+ :data_type => :named_type,
564
+ :charset_form => nil,
565
+ :nullable? => true,
566
+ :char_used? => false,
567
+ :char_size => 0,
568
+ :data_size => :skip, # 1 when explicitly, 2000 when implicitly.
569
+ :precision => 0,
570
+ :scale => 0,
571
+ :fsprecision => 0,
572
+ :lfprecision => 0
573
+ ),
574
+ =begin # uncomment after ref is supported.
575
+ DatatypeData.new(:data_type_string => "REF MDSYS.SDO_GEOMETRY",
576
+ :oraver => ora101,
577
+ :data_type => :ref,
578
+ :charset_form => nil,
579
+ :nullable? => true,
580
+ :char_used? => false,
581
+ :char_size => 0,
582
+ :data_size => :skip,
583
+ :precision => 0,
584
+ :scale => 0,
585
+ :fsprecision => 0,
586
+ :lfprecision => 0,
587
+ ),
588
+ =end
589
+ ]
590
+
591
+ def test_error_describe_table
592
+ drop_table('test_table')
593
+ begin
594
+ @conn.describe_table('test_table')
595
+ flunk("expects ORA-4043 but no error")
596
+ rescue OCIError
597
+ flunk("expects ORA-4043 but ORA-#{$!.code}") if $!.code != 4043
598
+ end
599
+ @conn.exec('create sequence test_table')
600
+ begin
601
+ begin
602
+ @conn.describe_table('test_table')
603
+ flunk('expects ORA-4043 but no error')
604
+ rescue OCIError
605
+ flunk("expects ORA-4043 but ORA-#{$!.code}") if $!.code != 4043
606
+ end
607
+ ensure
608
+ @conn.exec('drop sequence test_table')
609
+ end
610
+ end
611
+
612
+ def assert_object_id(object_name, object_id, owner_name = nil)
613
+ owner_name ||= @conn.username
614
+ expected_val = @conn.select_one('select object_id from all_objects where owner = :1 and object_name = :2', owner_name, object_name)[0]
615
+ assert_equal(expected_val, object_id, "ID of #{object_name}")
616
+ end
617
+
618
+ def test_table_metadata
619
+ drop_table('test_table')
620
+
621
+ # Relational table
622
+ @conn.exec(<<-EOS)
623
+ CREATE TABLE test_table (col1 number(38,0), col2 varchar2(60))
624
+ STORAGE (
625
+ INITIAL 100k
626
+ NEXT 100k
627
+ MINEXTENTS 1
628
+ MAXEXTENTS UNLIMITED
629
+ PCTINCREASE 0)
630
+ EOS
631
+ [
632
+ @conn.describe_any('test_table'),
633
+ @conn.describe_table('test_table'),
634
+ @conn.describe_schema(@conn.username).objects.detect do |obj|
635
+ obj.obj_name == 'TEST_TABLE'
636
+ end
637
+ ].each do |desc|
638
+ assert_object_id('TEST_TABLE', desc.obj_id)
639
+ assert_equal('TEST_TABLE', desc.obj_name)
640
+ assert_equal(@conn.username, desc.obj_schema)
641
+ assert_equal(2, desc.num_cols)
642
+ assert_nil(desc.type_metadata)
643
+ assert_equal(false, desc.is_temporary?)
644
+ assert_equal(false, desc.is_typed?)
645
+ assert_nil(desc.duration)
646
+ assert_not_nil(desc.dba)
647
+ assert_not_nil(desc.tablespace)
648
+ assert_equal(false, desc.clustered?)
649
+ assert_equal(false, desc.partitioned?)
650
+ assert_equal(false, desc.index_only?)
651
+ assert_instance_of(Array, desc.columns)
652
+ assert_instance_of(OCI8::Metadata::Column, desc.columns[0])
653
+ end
654
+ drop_table('test_table')
655
+
656
+ # Transaction-specific temporary table
657
+ @conn.exec(<<-EOS)
658
+ CREATE GLOBAL TEMPORARY TABLE test_table (col1 number(38,0), col2 varchar2(60))
659
+ EOS
660
+ [
661
+ @conn.describe_any('test_table'),
662
+ @conn.describe_table('test_table'),
663
+ @conn.describe_schema(@conn.username).objects.detect do |obj|
664
+ obj.obj_name == 'TEST_TABLE'
665
+ end
666
+ ].each do |desc|
667
+ assert_object_id('TEST_TABLE', desc.obj_id)
668
+ assert_equal('TEST_TABLE', desc.obj_name)
669
+ assert_equal(@conn.username, desc.obj_schema)
670
+ assert_equal(2, desc.num_cols)
671
+ assert_nil(desc.type_metadata)
672
+ assert_equal(true, desc.is_temporary?)
673
+ assert_equal(false, desc.is_typed?)
674
+ assert_equal(:transaction, desc.duration)
675
+ assert_not_nil(desc.dba)
676
+ assert_not_nil(desc.tablespace)
677
+ assert_equal(false, desc.clustered?)
678
+ assert_equal(false, desc.partitioned?)
679
+ assert_equal(false, desc.index_only?)
680
+ assert_instance_of(Array, desc.columns)
681
+ assert_instance_of(OCI8::Metadata::Column, desc.columns[0])
682
+ end
683
+ drop_table('test_table')
684
+
685
+ # Session-specific temporary table
686
+ @conn.exec(<<-EOS)
687
+ CREATE GLOBAL TEMPORARY TABLE test_table (col1 number(38,0), col2 varchar2(60))
688
+ ON COMMIT PRESERVE ROWS
689
+ EOS
690
+ [
691
+ @conn.describe_any('test_table'),
692
+ @conn.describe_table('test_table'),
693
+ @conn.describe_schema(@conn.username).objects.detect do |obj|
694
+ obj.obj_name == 'TEST_TABLE'
695
+ end
696
+ ].each do |desc|
697
+ assert_object_id('TEST_TABLE', desc.obj_id)
698
+ assert_equal('TEST_TABLE', desc.obj_name)
699
+ assert_equal(@conn.username, desc.obj_schema)
700
+ assert_equal(2, desc.num_cols)
701
+ assert_nil(desc.type_metadata)
702
+ assert_equal(true, desc.is_temporary?)
703
+ assert_equal(false, desc.is_typed?)
704
+ assert_equal(:session, desc.duration)
705
+ assert_not_nil(desc.dba)
706
+ assert_not_nil(desc.tablespace)
707
+ assert_equal(false, desc.clustered?)
708
+ assert_equal(false, desc.partitioned?)
709
+ assert_equal(false, desc.index_only?)
710
+ assert_instance_of(Array, desc.columns)
711
+ assert_instance_of(OCI8::Metadata::Column, desc.columns[0])
712
+ end
713
+ drop_table('test_table')
714
+
715
+ # Object table
716
+ @conn.exec(<<-EOS)
717
+ CREATE OR REPLACE TYPE test_type AS OBJECT (col1 number(38,0), col2 varchar2(60))
718
+ EOS
719
+ @conn.exec(<<-EOS)
720
+ CREATE TABLE test_table OF test_type
721
+ EOS
722
+ [
723
+ @conn.describe_any('test_table'),
724
+ @conn.describe_table('test_table'),
725
+ @conn.describe_schema(@conn.username).objects.detect do |obj|
726
+ obj.obj_name == 'TEST_TABLE'
727
+ end
728
+ ].each do |desc|
729
+ assert_object_id('TEST_TABLE', desc.obj_id)
730
+ assert_equal('TEST_TABLE', desc.obj_name)
731
+ assert_equal(@conn.username, desc.obj_schema)
732
+ assert_equal(2, desc.num_cols)
733
+ assert_instance_of(OCI8::Metadata::Type, desc.type_metadata)
734
+ assert_equal(false, desc.is_temporary?)
735
+ assert_equal(true, desc.is_typed?)
736
+ assert_equal(nil, desc.duration)
737
+ assert_not_nil(desc.dba)
738
+ assert_not_nil(desc.tablespace)
739
+ assert_equal(false, desc.clustered?)
740
+ assert_equal(false, desc.partitioned?)
741
+ assert_equal(false, desc.index_only?)
742
+ assert_instance_of(Array, desc.columns)
743
+ assert_instance_of(OCI8::Metadata::Column, desc.columns[0])
744
+ end
745
+ drop_table('test_table')
746
+ @conn.exec('DROP TYPE TEST_TYPE')
747
+
748
+ # Index-organized table
749
+ @conn.exec(<<-EOS)
750
+ CREATE TABLE test_table (col1 number(38,0) PRIMARY KEY, col2 varchar2(60))
751
+ ORGANIZATION INDEX
752
+ EOS
753
+ [
754
+ @conn.describe_any('test_table'),
755
+ @conn.describe_table('test_table'),
756
+ @conn.describe_schema(@conn.username).objects.detect do |obj|
757
+ obj.obj_name == 'TEST_TABLE'
758
+ end
759
+ ].each do |desc|
760
+ assert_object_id('TEST_TABLE', desc.obj_id)
761
+ assert_equal('TEST_TABLE', desc.obj_name)
762
+ assert_equal(@conn.username, desc.obj_schema)
763
+ assert_equal(2, desc.num_cols)
764
+ assert_nil(desc.type_metadata)
765
+ assert_equal(false, desc.is_temporary?)
766
+ assert_equal(false, desc.is_typed?)
767
+ assert_equal(nil, desc.duration)
768
+ assert_not_nil(desc.dba)
769
+ assert_not_nil(desc.tablespace)
770
+ assert_equal(false, desc.clustered?)
771
+ assert_equal(false, desc.partitioned?)
772
+ assert_equal(true, desc.index_only?)
773
+ assert_instance_of(Array, desc.columns)
774
+ assert_instance_of(OCI8::Metadata::Column, desc.columns[0])
775
+ end
776
+ drop_table('test_table')
777
+ end # test_table_metadata
778
+
779
+ def test_view_metadata
780
+ @conn.exec('CREATE OR REPLACE VIEW test_view as SELECT * FROM tab')
781
+ [
782
+ @conn.describe_any('test_view'),
783
+ @conn.describe_view('test_view'),
784
+ @conn.describe_table('test_view'),
785
+ @conn.describe_schema(@conn.username).objects.detect do |obj|
786
+ obj.obj_name == 'TEST_VIEW'
787
+ end
788
+ ].each do |desc|
789
+ assert_object_id('TEST_VIEW', desc.obj_id)
790
+ assert_equal('TEST_VIEW', desc.obj_name)
791
+ assert_equal(@conn.username, desc.obj_schema)
792
+ assert_equal(3, desc.num_cols)
793
+ assert_instance_of(Array, desc.columns)
794
+ assert_instance_of(OCI8::Metadata::Column, desc.columns[0])
795
+ end
796
+ @conn.exec('DROP VIEW test_view')
797
+ end # test_view_metadata
798
+
799
+ def test_procedure_metadata
800
+ @conn.exec(<<-EOS)
801
+ CREATE OR REPLACE PROCEDURE test_proc(arg1 IN INTEGER, arg2 OUT varchar2) IS
802
+ BEGIN
803
+ NULL;
804
+ END;
805
+ EOS
806
+ [
807
+ @conn.describe_any('test_proc'),
808
+ @conn.describe_procedure('test_proc'),
809
+ @conn.describe_schema(@conn.username).objects.detect do |obj|
810
+ obj.obj_name == 'TEST_PROC'
811
+ end
812
+ ].each do |desc|
813
+ assert_instance_of(OCI8::Metadata::Procedure, desc)
814
+ assert_object_id('TEST_PROC', desc.obj_id)
815
+ assert_equal('TEST_PROC', desc.obj_name)
816
+ assert_equal('TEST_PROC', desc.name)
817
+ assert_equal(@conn.username, desc.obj_schema)
818
+ assert_equal(false, desc.is_invoker_rights?)
819
+ assert_equal(nil, desc.overload_id)
820
+ assert_instance_of(Array, desc.arguments)
821
+ assert_equal(2, desc.arguments.length)
822
+ assert_instance_of(OCI8::Metadata::Argument, desc.arguments[0])
823
+ end
824
+
825
+ @conn.exec(<<-EOS)
826
+ CREATE OR REPLACE PROCEDURE test_proc(arg1 IN INTEGER, arg2 OUT varchar2)
827
+ AUTHID CURRENT_USER
828
+ IS
829
+ BEGIN
830
+ NULL;
831
+ END;
832
+ EOS
833
+ [
834
+ @conn.describe_any('test_proc'),
835
+ @conn.describe_procedure('test_proc'),
836
+ @conn.describe_schema(@conn.username).objects.detect do |obj|
837
+ obj.obj_name == 'TEST_PROC'
838
+ end
839
+ ].each do |desc|
840
+ assert_instance_of(OCI8::Metadata::Procedure, desc)
841
+ assert_object_id('TEST_PROC', desc.obj_id)
842
+ assert_equal('TEST_PROC', desc.obj_name)
843
+ assert_equal(@conn.username, desc.obj_schema)
844
+ assert_equal(true, desc.is_invoker_rights?)
845
+ assert_equal(nil, desc.overload_id)
846
+ assert_instance_of(Array, desc.arguments)
847
+ assert_equal(2, desc.arguments.length)
848
+ assert_instance_of(OCI8::Metadata::Argument, desc.arguments[0])
849
+ end
850
+
851
+ @conn.exec('DROP PROCEDURE test_proc');
852
+
853
+ @conn.exec(<<-EOS)
854
+ CREATE OR REPLACE PACKAGE TEST_PKG IS
855
+ PROCEDURE test_proc(arg1 IN INTEGER, arg2 OUT varchar2);
856
+ END;
857
+ EOS
858
+ desc = @conn.describe_package('test_pkg').subprograms[0]
859
+ assert_instance_of(OCI8::Metadata::Procedure, desc)
860
+ assert_equal(nil, desc.obj_id)
861
+ assert_equal('TEST_PROC', desc.obj_name)
862
+ assert_equal(nil, desc.obj_schema)
863
+ assert_equal(false, desc.is_invoker_rights?)
864
+ assert_equal(0, desc.overload_id)
865
+ assert_instance_of(Array, desc.arguments)
866
+ assert_equal(2, desc.arguments.length)
867
+ assert_instance_of(OCI8::Metadata::Argument, desc.arguments[0])
868
+
869
+ @conn.exec(<<-EOS)
870
+ CREATE OR REPLACE PACKAGE TEST_PKG AUTHID CURRENT_USER
871
+ IS
872
+ PROCEDURE test_proc(arg1 IN INTEGER, arg2 OUT varchar2);
873
+ PROCEDURE test_proc(arg1 IN INTEGER);
874
+ END;
875
+ EOS
876
+ desc = @conn.describe_package('test_pkg').subprograms
877
+ assert_instance_of(OCI8::Metadata::Procedure, desc[0])
878
+ assert_equal(nil, desc[0].obj_id)
879
+ assert_equal('TEST_PROC', desc[0].obj_name)
880
+ assert_equal(nil, desc[0].obj_schema)
881
+ assert_equal(true, desc[0].is_invoker_rights?)
882
+ assert_equal(2, desc[0].overload_id)
883
+ assert_instance_of(Array, desc[0].arguments)
884
+ assert_equal(2, desc[0].arguments.length)
885
+ assert_instance_of(OCI8::Metadata::Argument, desc[0].arguments[0])
886
+
887
+ descs = @conn.describe_package('test_pkg').subprograms
888
+ assert_instance_of(OCI8::Metadata::Procedure, desc[1])
889
+ assert_equal(nil, desc[1].obj_id)
890
+ assert_equal('TEST_PROC', desc[1].obj_name)
891
+ assert_equal(nil, desc[1].obj_schema)
892
+ assert_equal(true, desc[1].is_invoker_rights?)
893
+ assert_equal(1, desc[1].overload_id)
894
+ assert_instance_of(Array, desc[1].arguments)
895
+ assert_equal(1, desc[1].arguments.length)
896
+ assert_instance_of(OCI8::Metadata::Argument, desc[1].arguments[0])
897
+ end # test_procedure_metadata
898
+
899
+ def test_function_metadata
900
+ @conn.exec(<<-EOS)
901
+ CREATE OR REPLACE FUNCTION test_func(arg1 IN INTEGER, arg2 OUT varchar2) RETURN NUMBER IS
902
+ BEGIN
903
+ RETURN arg1;
904
+ END;
905
+ EOS
906
+ [
907
+ @conn.describe_any('test_func'),
908
+ @conn.describe_function('test_func'),
909
+ @conn.describe_schema(@conn.username).objects.detect do |obj|
910
+ obj.obj_name == 'TEST_FUNC'
911
+ end
912
+ ].each do |desc|
913
+ assert_instance_of(OCI8::Metadata::Function, desc)
914
+ assert_object_id('TEST_FUNC', desc.obj_id)
915
+ assert_equal('TEST_FUNC', desc.obj_name)
916
+ assert_equal('TEST_FUNC', desc.name)
917
+ assert_equal(@conn.username, desc.obj_schema)
918
+ assert_equal(false, desc.is_invoker_rights?)
919
+ assert_equal(nil, desc.overload_id)
920
+ assert_instance_of(Array, desc.arguments)
921
+ assert_equal(3, desc.arguments.length)
922
+ assert_instance_of(OCI8::Metadata::Argument, desc.arguments[0])
923
+ end
924
+
925
+ @conn.exec(<<-EOS)
926
+ CREATE OR REPLACE FUNCTION test_func(arg1 IN INTEGER, arg2 OUT varchar2) RETURN NUMBER
927
+ AUTHID CURRENT_USER
928
+ IS
929
+ BEGIN
930
+ RETURN arg1;
931
+ END;
932
+ EOS
933
+ [
934
+ @conn.describe_any('test_func'),
935
+ @conn.describe_function('test_func'),
936
+ @conn.describe_schema(@conn.username).objects.detect do |obj|
937
+ obj.obj_name == 'TEST_FUNC'
938
+ end
939
+ ].each do |desc|
940
+ assert_instance_of(OCI8::Metadata::Function, desc)
941
+ assert_object_id('TEST_FUNC', desc.obj_id)
942
+ assert_equal('TEST_FUNC', desc.obj_name)
943
+ assert_equal(@conn.username, desc.obj_schema)
944
+ assert_equal(true, desc.is_invoker_rights?)
945
+ assert_equal(nil, desc.overload_id)
946
+ assert_instance_of(Array, desc.arguments)
947
+ assert_equal(3, desc.arguments.length)
948
+ assert_instance_of(OCI8::Metadata::Argument, desc.arguments[0])
949
+ end
950
+
951
+ @conn.exec('DROP FUNCTION test_func');
952
+
953
+ @conn.exec(<<-EOS)
954
+ CREATE OR REPLACE PACKAGE TEST_PKG IS
955
+ FUNCTION test_func(arg1 IN INTEGER, arg2 OUT varchar2) RETURN NUMBER;
956
+ END;
957
+ EOS
958
+ desc = @conn.describe_package('test_pkg').subprograms[0]
959
+ assert_instance_of(OCI8::Metadata::Function, desc)
960
+ assert_equal(nil, desc.obj_id)
961
+ assert_equal('TEST_FUNC', desc.obj_name)
962
+ assert_equal(nil, desc.obj_schema)
963
+ assert_equal(false, desc.is_invoker_rights?)
964
+ assert_equal(0, desc.overload_id)
965
+ assert_instance_of(Array, desc.arguments)
966
+ assert_equal(3, desc.arguments.length)
967
+ assert_instance_of(OCI8::Metadata::Argument, desc.arguments[0])
968
+
969
+ @conn.exec(<<-EOS)
970
+ CREATE OR REPLACE PACKAGE TEST_PKG AUTHID CURRENT_USER
971
+ IS
972
+ FUNCTION test_func(arg1 IN INTEGER, arg2 OUT varchar2) RETURN NUMBER;
973
+ FUNCTION test_func(arg1 IN INTEGER) RETURN NUMBER;
974
+ END;
975
+ EOS
976
+ desc = @conn.describe_package('test_pkg').subprograms
977
+ assert_instance_of(OCI8::Metadata::Function, desc[0])
978
+ assert_equal(nil, desc[0].obj_id)
979
+ assert_equal('TEST_FUNC', desc[0].obj_name)
980
+ assert_equal(nil, desc[0].obj_schema)
981
+ assert_equal(true, desc[0].is_invoker_rights?)
982
+ assert_equal(2, desc[0].overload_id)
983
+ assert_instance_of(Array, desc[0].arguments)
984
+ assert_equal(3, desc[0].arguments.length)
985
+ assert_instance_of(OCI8::Metadata::Argument, desc[0].arguments[0])
986
+
987
+ descs = @conn.describe_package('test_pkg').subprograms
988
+ assert_instance_of(OCI8::Metadata::Function, desc[1])
989
+ assert_equal(nil, desc[1].obj_id)
990
+ assert_equal('TEST_FUNC', desc[1].obj_name)
991
+ assert_equal(nil, desc[1].obj_schema)
992
+ assert_equal(true, desc[1].is_invoker_rights?)
993
+ assert_equal(1, desc[1].overload_id)
994
+ assert_instance_of(Array, desc[1].arguments)
995
+ assert_equal(2, desc[1].arguments.length)
996
+ assert_instance_of(OCI8::Metadata::Argument, desc[1].arguments[0])
997
+ end # test_function_metadata
998
+
999
+ def test_package_metadata
1000
+ @conn.exec(<<-EOS)
1001
+ CREATE OR REPLACE PACKAGE TEST_PKG IS
1002
+ FUNCTION test_func(arg1 IN INTEGER, arg2 OUT varchar2) RETURN NUMBER;
1003
+ END;
1004
+ EOS
1005
+ [
1006
+ @conn.describe_any('test_pkg'),
1007
+ @conn.describe_package('test_pkg'),
1008
+ @conn.describe_schema(@conn.username).objects.detect do |obj|
1009
+ obj.obj_name == 'TEST_PKG'
1010
+ end
1011
+ ].each do |desc|
1012
+ assert_instance_of(OCI8::Metadata::Package, desc)
1013
+ assert_object_id('TEST_PKG', desc.obj_id)
1014
+ assert_equal('TEST_PKG', desc.obj_name)
1015
+ assert_equal(@conn.username, desc.obj_schema)
1016
+ assert_equal(false, desc.is_invoker_rights?)
1017
+ assert_instance_of(Array, desc.subprograms)
1018
+ assert_equal(1, desc.subprograms.length)
1019
+ assert_instance_of(OCI8::Metadata::Function, desc.subprograms[0])
1020
+ end
1021
+
1022
+ @conn.exec(<<-EOS)
1023
+ CREATE OR REPLACE PACKAGE TEST_PKG AUTHID CURRENT_USER IS
1024
+ PROCEDURE test_proc(arg1 IN INTEGER, arg2 OUT varchar2);
1025
+ END;
1026
+ EOS
1027
+ [
1028
+ @conn.describe_any('test_pkg'),
1029
+ @conn.describe_package('test_pkg'),
1030
+ @conn.describe_schema(@conn.username).objects.detect do |obj|
1031
+ obj.obj_name == 'TEST_PKG'
1032
+ end
1033
+ ].each do |desc|
1034
+ assert_instance_of(OCI8::Metadata::Package, desc)
1035
+ assert_object_id('TEST_PKG', desc.obj_id)
1036
+ assert_equal('TEST_PKG', desc.obj_name)
1037
+ assert_equal(@conn.username, desc.obj_schema)
1038
+ assert_equal(true, desc.is_invoker_rights?)
1039
+ assert_instance_of(Array, desc.subprograms)
1040
+ assert_equal(1, desc.subprograms.length)
1041
+ assert_instance_of(OCI8::Metadata::Procedure, desc.subprograms[0])
1042
+ end
1043
+ end # test_package_metadata
1044
+
1045
+ def test_type_metadata
1046
+ drop_type('TEST_TYPE_ORDER_METHOD')
1047
+ drop_type('TEST_TYPE_MAP_METHOD')
1048
+ drop_type('TEST_TYPE_HAS_BFILE')
1049
+ drop_type('TEST_TYPE_HAS_BLOB')
1050
+ drop_type('TEST_TYPE_HAS_NCLOB')
1051
+ drop_type('TEST_TYPE_HAS_CLOB')
1052
+ drop_type('TEST_TYPE_INCOMPLETE')
1053
+ drop_type('TEST_TYPE_GRANDCHILD')
1054
+ drop_type('TEST_TYPE_VARRAY')
1055
+ drop_type('TEST_TYPE_NESTEAD_TABLE')
1056
+ drop_type('TEST_TYPE_CHILD')
1057
+ drop_type('TEST_TYPE_PARENT')
1058
+ expected_values = []
1059
+
1060
+ @conn.exec(<<-EOS)
1061
+ CREATE TYPE test_type_parent AS OBJECT (
1062
+ col1 number(38,0),
1063
+ col2 varchar2(60)
1064
+ )
1065
+ NOT INSTANTIABLE
1066
+ NOT FINAL
1067
+ EOS
1068
+ expected_values << {
1069
+ :obj_name => 'TEST_TYPE_PARENT',
1070
+ :typecode => :named_type,
1071
+ :collection_typecode => nil,
1072
+ :is_incomplete_type? => false,
1073
+ :is_system_type? => false,
1074
+ :is_predefined_type? => false,
1075
+ :is_transient_type? => false,
1076
+ :is_system_generated_type? => false,
1077
+ :has_nested_table? => false,
1078
+ :has_lob? => false,
1079
+ :has_file? => false,
1080
+ :collection_element => nil,
1081
+ :num_type_attrs => 2,
1082
+ :num_type_methods => 0,
1083
+ :map_method => nil,
1084
+ :order_method => nil,
1085
+ :is_invoker_rights? => false,
1086
+ :is_final_type? => false,
1087
+ :is_instantiable_type? => false,
1088
+ :is_subtype? => false,
1089
+ :supertype_schema_name => nil,
1090
+ :supertype_name => nil,
1091
+ :type_attrs => [:array, 2, OCI8::Metadata::TypeAttr],
1092
+ :type_methods => [:array, 0],
1093
+ }
1094
+ @conn.exec(<<-EOS)
1095
+ CREATE TYPE test_type_child UNDER test_type_parent (
1096
+ lob BLOB
1097
+ )
1098
+ NOT FINAL
1099
+ EOS
1100
+ expected_values << {
1101
+ :obj_name => 'TEST_TYPE_CHILD',
1102
+ :typecode => :named_type,
1103
+ :collection_typecode => nil,
1104
+ :is_incomplete_type? => false,
1105
+ :is_system_type? => false,
1106
+ :is_predefined_type? => false,
1107
+ :is_transient_type? => false,
1108
+ :is_system_generated_type? => false,
1109
+ :has_nested_table? => false,
1110
+ :has_lob? => true,
1111
+ :has_file? => false,
1112
+ :collection_element => nil,
1113
+ :num_type_attrs => 3,
1114
+ :num_type_methods => 0,
1115
+ :map_method => nil,
1116
+ :order_method => nil,
1117
+ :is_invoker_rights? => false,
1118
+ :is_final_type? => false,
1119
+ :is_instantiable_type? => true,
1120
+ :is_subtype? => true,
1121
+ :supertype_schema_name => @conn.username,
1122
+ :supertype_name => 'TEST_TYPE_PARENT',
1123
+ :type_attrs => [:array, 3, OCI8::Metadata::TypeAttr],
1124
+ :type_methods => [:array, 0],
1125
+ }
1126
+ @conn.exec(<<-EOS)
1127
+ CREATE TYPE test_type_nestead_table AS TABLE OF test_type_child
1128
+ EOS
1129
+ expected_values << {
1130
+ :obj_name => 'TEST_TYPE_NESTEAD_TABLE',
1131
+ :typecode => :named_collection,
1132
+ :collection_typecode => :table,
1133
+ :is_incomplete_type? => false,
1134
+ :is_system_type? => false,
1135
+ :is_predefined_type? => false,
1136
+ :is_transient_type? => false,
1137
+ :is_system_generated_type? => false,
1138
+ :has_nested_table? => true,
1139
+ :has_lob? => true,
1140
+ :has_file? => false,
1141
+ :collection_element => [:type, OCI8::Metadata::Collection],
1142
+ :num_type_attrs => 0,
1143
+ :num_type_methods => 0,
1144
+ :map_method => nil,
1145
+ :order_method => nil,
1146
+ :is_invoker_rights? => false,
1147
+ :is_final_type? => true,
1148
+ :is_instantiable_type? => true,
1149
+ :is_subtype? => false,
1150
+ :supertype_schema_name => nil,
1151
+ :supertype_name => nil,
1152
+ :type_attrs => [:array, 0],
1153
+ :type_methods => [:array, 0],
1154
+ }
1155
+ @conn.exec(<<-EOS)
1156
+ CREATE TYPE test_type_varray AS VARRAY(10) OF test_type_child
1157
+ EOS
1158
+ expected_values << {
1159
+ :obj_name => 'TEST_TYPE_VARRAY',
1160
+ :typecode => :named_collection,
1161
+ :collection_typecode => :varray,
1162
+ :is_incomplete_type? => false,
1163
+ :is_system_type? => false,
1164
+ :is_predefined_type? => false,
1165
+ :is_transient_type? => false,
1166
+ :is_system_generated_type? => false,
1167
+ :has_nested_table? => false,
1168
+ :has_lob? => true,
1169
+ :has_file? => false,
1170
+ :collection_element => [:type, OCI8::Metadata::Collection],
1171
+ :num_type_attrs => 0,
1172
+ :num_type_methods => 0,
1173
+ :map_method => nil,
1174
+ :order_method => nil,
1175
+ :is_invoker_rights? => false,
1176
+ :is_final_type? => true,
1177
+ :is_instantiable_type? => true,
1178
+ :is_subtype? => false,
1179
+ :supertype_schema_name => nil,
1180
+ :supertype_name => nil,
1181
+ :type_attrs => [:array, 0],
1182
+ :type_methods => [:array, 0],
1183
+ }
1184
+ @conn.exec(<<-EOS)
1185
+ CREATE TYPE test_type_grandchild UNDER test_type_child (
1186
+ table_column test_type_nestead_table,
1187
+ file_column BFILE
1188
+ )
1189
+ EOS
1190
+ expected_values << {
1191
+ :obj_name => 'TEST_TYPE_GRANDCHILD',
1192
+ :typecode => :named_type,
1193
+ :collection_typecode => nil,
1194
+ :is_incomplete_type? => false,
1195
+ :is_system_type? => false,
1196
+ :is_predefined_type? => false,
1197
+ :is_transient_type? => false,
1198
+ :is_system_generated_type? => false,
1199
+ :has_nested_table? => true,
1200
+ :has_lob? => true,
1201
+ :has_file? => true,
1202
+ :collection_element => nil,
1203
+ :num_type_attrs => 5,
1204
+ :num_type_methods => 0,
1205
+ :map_method => nil,
1206
+ :order_method => nil,
1207
+ :is_invoker_rights? => false,
1208
+ :is_final_type? => true,
1209
+ :is_instantiable_type? => true,
1210
+ :is_subtype? => true,
1211
+ :supertype_schema_name => @conn.username,
1212
+ :supertype_name => 'TEST_TYPE_CHILD',
1213
+ :type_attrs => [:array, 5, OCI8::Metadata::TypeAttr],
1214
+ :type_methods => [:array, 0],
1215
+ }
1216
+ @conn.exec(<<-EOS)
1217
+ CREATE TYPE test_type_incomplete
1218
+ EOS
1219
+ expected_values << {
1220
+ :obj_name => 'TEST_TYPE_INCOMPLETE',
1221
+ :typecode => :named_type,
1222
+ :collection_typecode => nil,
1223
+ :is_incomplete_type? => true,
1224
+ :is_system_type? => false,
1225
+ :is_predefined_type? => false,
1226
+ :is_transient_type? => false,
1227
+ :is_system_generated_type? => false,
1228
+ :has_nested_table? => false,
1229
+ :has_lob? => false,
1230
+ :has_file? => false,
1231
+ :collection_element => nil,
1232
+ :num_type_attrs => 0,
1233
+ :num_type_methods => 0,
1234
+ :map_method => nil,
1235
+ :order_method => nil,
1236
+ :is_invoker_rights? => false,
1237
+ :is_final_type? => true,
1238
+ :is_instantiable_type? => true,
1239
+ :is_subtype? => false,
1240
+ :supertype_schema_name => nil,
1241
+ :supertype_name => nil,
1242
+ :type_attrs => [:array, 0],
1243
+ :type_methods => [:array, 0],
1244
+ }
1245
+
1246
+ @conn.exec(<<-EOS)
1247
+ CREATE TYPE test_type_has_clob AS OBJECT (lob CLOB)
1248
+ EOS
1249
+ expected_values << {
1250
+ :obj_name => 'TEST_TYPE_HAS_CLOB',
1251
+ :has_lob? => true,
1252
+ :has_file? => false,
1253
+ }
1254
+ if $oracle_version >= OCI8::ORAVER_9_2
1255
+ @conn.exec(<<-EOS)
1256
+ CREATE TYPE test_type_has_nclob AS OBJECT (lob NCLOB)
1257
+ EOS
1258
+ expected_values << {
1259
+ :obj_name => 'TEST_TYPE_HAS_NCLOB',
1260
+ :has_lob? => true,
1261
+ :has_file? => false,
1262
+ }
1263
+ end
1264
+ @conn.exec(<<-EOS)
1265
+ CREATE TYPE test_type_has_blob AS OBJECT (lob BLOB)
1266
+ EOS
1267
+ expected_values << {
1268
+ :obj_name => 'TEST_TYPE_HAS_BLOB',
1269
+ :has_lob? => true,
1270
+ :has_file? => false,
1271
+ }
1272
+ @conn.exec(<<-EOS)
1273
+ CREATE TYPE test_type_has_bfile AS OBJECT (lob BFILE)
1274
+ EOS
1275
+ expected_values << {
1276
+ :obj_name => 'TEST_TYPE_HAS_BFILE',
1277
+ :has_lob? => false,
1278
+ :has_file? => true,
1279
+ }
1280
+ @conn.exec(<<-EOS)
1281
+ CREATE TYPE test_type_map_method AS OBJECT (
1282
+ x integer,
1283
+ y integer,
1284
+ MAP MEMBER FUNCTION area RETURN NUMBER
1285
+ )
1286
+ EOS
1287
+ expected_values << {
1288
+ :obj_name => 'TEST_TYPE_MAP_METHOD',
1289
+ :map_method => [:type, OCI8::Metadata::TypeMethod],
1290
+ :order_method => nil,
1291
+ }
1292
+ @conn.exec(<<-EOS)
1293
+ CREATE TYPE test_type_order_method AS OBJECT (
1294
+ x integer,
1295
+ y integer,
1296
+ ORDER MEMBER FUNCTION match(l test_type_order_method) RETURN INTEGER
1297
+ )
1298
+ EOS
1299
+ expected_values << {
1300
+ :obj_name => 'TEST_TYPE_ORDER_METHOD',
1301
+ :map_method => nil,
1302
+ :order_method => [:type, OCI8::Metadata::TypeMethod],
1303
+ }
1304
+
1305
+ expected_values.each do |elem|
1306
+ [
1307
+ @conn.describe_any(elem[:obj_name]),
1308
+ @conn.describe_type(elem[:obj_name]),
1309
+ @conn.describe_schema(@conn.username).objects.detect do |obj|
1310
+ obj.obj_name == elem[:obj_name]
1311
+ end,
1312
+ ].each do |desc|
1313
+ assert_object_id(elem[:obj_name], desc.obj_id)
1314
+ assert_equal(@conn.username, desc.obj_schema)
1315
+ assert_equal(elem[:obj_name], desc.name)
1316
+ assert_equal(@conn.username, desc.schema_name)
1317
+
1318
+ elem.each do |key, val|
1319
+ msg = elem[:obj_name] + '.' + key.to_s
1320
+ if val.is_a? Array
1321
+ case val[0]
1322
+ when :array
1323
+ assert_instance_of(Array, desc.send(key), msg)
1324
+ assert_equal(val[1], desc.send(key).length)
1325
+ assert_instance_of(val[2], desc.send(key)[0]) if val[1] > 0
1326
+ when :type
1327
+ assert_instance_of(val[1], desc.send(key), msg)
1328
+ else
1329
+ raise "Invalid test case: #{elem[:obj_name]}.#{key} : #{val[0]}"
1330
+ end
1331
+ else
1332
+ assert_equal(val, desc.send(key), msg)
1333
+ end
1334
+ end
1335
+ end
1336
+ end
1337
+
1338
+ drop_type('TEST_TYPE_ORDER_METHOD')
1339
+ drop_type('TEST_TYPE_MAP_METHOD')
1340
+ drop_type('TEST_TYPE_HAS_BFILE')
1341
+ drop_type('TEST_TYPE_HAS_BLOB')
1342
+ drop_type('TEST_TYPE_HAS_NCLOB')
1343
+ drop_type('TEST_TYPE_HAS_CLOB')
1344
+ drop_type('TEST_TYPE_INCOMPLETE')
1345
+ drop_type('TEST_TYPE_GRANDCHILD')
1346
+ drop_type('TEST_TYPE_VARRAY')
1347
+ drop_type('TEST_TYPE_NESTEAD_TABLE')
1348
+ drop_type('TEST_TYPE_CHILD')
1349
+ drop_type('TEST_TYPE_PARENT')
1350
+ end # test_type_metadata
1351
+
1352
+ def test_column_metadata
1353
+ if $oracle_version < OCI8::ORAVER_8_1
1354
+ begin
1355
+ @conn.describe_table('tab').columns
1356
+ rescue RuntimeError
1357
+ assert_equal("This feature is unavailable on Oracle 8.0", $!.to_s)
1358
+ end
1359
+ return
1360
+ end
1361
+
1362
+ coldef = @@column_test_data.find_all do |c|
1363
+ $oracle_version >= c.oraver
1364
+ end
1365
+
1366
+ drop_table('test_table')
1367
+ sql = <<-EOS
1368
+ CREATE TABLE test_table (#{idx = 0; coldef.collect do |c| idx += 1; "C#{idx} " + c.data_type_string; end.join(',')})
1369
+ STORAGE (
1370
+ INITIAL 100k
1371
+ NEXT 100k
1372
+ MINEXTENTS 1
1373
+ MAXEXTENTS UNLIMITED
1374
+ PCTINCREASE 0)
1375
+ EOS
1376
+ @conn.exec(sql)
1377
+
1378
+ [
1379
+ @conn.describe_any('test_table').columns,
1380
+ @conn.describe_table('test_table').columns,
1381
+ @conn.describe_schema(@conn.username).objects.detect do |obj|
1382
+ obj.obj_name == 'TEST_TABLE'
1383
+ end.columns,
1384
+ @conn.exec('select * from test_table').column_metadata,
1385
+ ].each do |columns|
1386
+ columns.each_with_index do |column, i|
1387
+ assert_equal("C#{i + 1}", column.name, "'#{coldef[i].data_type_string}': name")
1388
+ DatatypeData.attributes.each do |attr|
1389
+ expected_val = coldef[i].send(attr)
1390
+ if expected_val != :skip
1391
+ assert_equal(expected_val, column.send(attr), "'#{coldef[i].data_type_string}': #{attr})")
1392
+ end
1393
+ end
1394
+ end
1395
+ end
1396
+ drop_table('test_table')
1397
+ end # test_column_metadata
1398
+
1399
+ end # TestMetadata