ruby-plsql 0.8.0 → 0.9.0

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/History.txt +2 -0
  3. data/VERSION +1 -1
  4. data/lib/plsql/connection.rb +14 -14
  5. data/lib/plsql/helpers.rb +3 -3
  6. data/lib/plsql/jdbc_connection.rb +3 -3
  7. data/lib/plsql/oci_connection.rb +8 -4
  8. data/lib/plsql/package.rb +3 -3
  9. data/lib/plsql/procedure.rb +32 -17
  10. data/lib/plsql/procedure_call.rb +15 -15
  11. data/lib/plsql/schema.rb +13 -9
  12. data/lib/plsql/sequence.rb +2 -2
  13. data/lib/plsql/table.rb +6 -6
  14. data/lib/plsql/type.rb +7 -7
  15. data/lib/plsql/variable.rb +4 -4
  16. data/lib/plsql/version.rb +1 -1
  17. data/lib/plsql/view.rb +2 -2
  18. metadata +13 -138
  19. data/.github/stale.yml +0 -37
  20. data/.github/workflows/rubocop.yml +0 -37
  21. data/.github/workflows/test.yml +0 -69
  22. data/.rubocop.yml +0 -147
  23. data/.travis/oracle/download.sh +0 -15
  24. data/.travis/oracle/install.sh +0 -32
  25. data/.travis/setup_accounts.sh +0 -9
  26. data/.travis.yml +0 -88
  27. data/Gemfile +0 -24
  28. data/Rakefile +0 -53
  29. data/Vagrantfile +0 -38
  30. data/ci/network/admin/tnsnames.ora +0 -7
  31. data/ci/setup_accounts.sh +0 -9
  32. data/gemfiles/Gemfile.activerecord-5.0 +0 -21
  33. data/gemfiles/Gemfile.activerecord-5.1 +0 -21
  34. data/gemfiles/Gemfile.activerecord-5.2 +0 -21
  35. data/gemfiles/Gemfile.activerecord-6.0 +0 -21
  36. data/gemfiles/Gemfile.activerecord-6.1 +0 -21
  37. data/gemfiles/Gemfile.activerecord-main +0 -21
  38. data/ruby-plsql.gemspec +0 -114
  39. data/spec/plsql/connection_spec.rb +0 -505
  40. data/spec/plsql/package_spec.rb +0 -172
  41. data/spec/plsql/procedure_spec.rb +0 -2390
  42. data/spec/plsql/schema_spec.rb +0 -364
  43. data/spec/plsql/sequence_spec.rb +0 -67
  44. data/spec/plsql/sql_statements_spec.rb +0 -91
  45. data/spec/plsql/table_spec.rb +0 -376
  46. data/spec/plsql/type_spec.rb +0 -299
  47. data/spec/plsql/variable_spec.rb +0 -497
  48. data/spec/plsql/version_spec.rb +0 -8
  49. data/spec/plsql/view_spec.rb +0 -264
  50. data/spec/spec.opts +0 -6
  51. data/spec/spec_helper.rb +0 -121
  52. data/spec/support/create_arunit_user.sql +0 -2
  53. data/spec/support/custom_config.rb.sample +0 -14
  54. data/spec/support/file_check_script.sh +0 -9
  55. data/spec/support/test_db.rb +0 -149
  56. data/spec/support/unlock_and_setup_hr_user.sql +0 -2
@@ -1,2390 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require "spec_helper"
4
-
5
- describe "Parameter type mapping /" do
6
-
7
- shared_examples "Function with string parameters" do |datatype|
8
- before(:all) do
9
- plsql.connect! CONNECTION_PARAMS
10
- plsql.execute <<-SQL
11
- CREATE OR REPLACE FUNCTION test_uppercase
12
- ( p_string #{datatype} )
13
- RETURN #{datatype}
14
- IS
15
- BEGIN
16
- RETURN UPPER(p_string);
17
- END test_uppercase;
18
- SQL
19
- end
20
-
21
- after(:all) do
22
- plsql.execute "DROP FUNCTION test_uppercase"
23
- plsql.logoff
24
- end
25
-
26
- it "should find existing procedure" do
27
- expect(PLSQL::Procedure.find(plsql, :test_uppercase)).not_to be_nil
28
- end
29
-
30
- it "should not find nonexisting procedure" do
31
- expect(PLSQL::Procedure.find(plsql, :qwerty123456)).to be_nil
32
- end
33
-
34
- it "should execute function and return correct value" do
35
- expect(plsql.test_uppercase("xxx")).to eq("XXX")
36
- end
37
-
38
- it "should execute function with named parameters and return correct value" do
39
- expect(plsql.test_uppercase(p_string: "xxx")).to eq("XXX")
40
- end
41
-
42
- it "should raise error if wrong number of arguments is passed" do
43
- expect { plsql.test_uppercase("xxx", "yyy") }.to raise_error(ArgumentError)
44
- end
45
-
46
- it "should raise error if wrong named argument is passed" do
47
- expect { plsql.test_uppercase(p_string2: "xxx") }.to raise_error(ArgumentError)
48
- end
49
-
50
- it "should execute function with schema name specified" do
51
- expect(plsql.hr.test_uppercase("xxx")).to eq("XXX")
52
- end
53
-
54
- it "should process nil parameter as NULL" do
55
- expect(plsql.test_uppercase(nil)).to be_nil
56
- end
57
-
58
- end
59
-
60
- ["VARCHAR", "VARCHAR2"].each do |datatype|
61
- describe "Function with #{datatype} parameters" do
62
- it_should_behave_like "Function with string parameters", datatype
63
- end
64
- end
65
-
66
- shared_examples "Function with numeric" do |ora_data_type, class_, num1, num2, expected, mandatory|
67
- before(:all) do
68
- plsql.connect! CONNECTION_PARAMS
69
- plsql.execute <<-SQL
70
- CREATE OR REPLACE FUNCTION test_sum
71
- ( p_num1 #{ora_data_type}, p_num2 #{ora_data_type} )
72
- RETURN #{ora_data_type}
73
- IS
74
- BEGIN
75
- RETURN p_num1 + p_num2;
76
- END test_sum;
77
- SQL
78
- end
79
-
80
- after(:all) do
81
- plsql.execute "DROP FUNCTION test_sum"
82
- plsql.logoff
83
- end
84
-
85
- it "should get #{ora_data_type} variable type mapped to #{class_.to_s}" do
86
- expect(plsql.test_sum(num1, num2)).to be_a class_
87
- end
88
- it "should process input parameters and return correct result" do
89
- expect(plsql.test_sum(num1, num2)).to eq(expected)
90
- end
91
-
92
- it "should process nil parameter as NULL" do
93
- expect(plsql.test_sum(num1, nil)).to be_nil
94
- end unless mandatory
95
-
96
- end
97
-
98
- @big_number = ("1234567890" * 3).to_i
99
- [
100
- { ora_data_type: "INTEGER", class: Integer, num1: @big_number, num2: @big_number, expected: @big_number * 2 },
101
- { ora_data_type: "NUMBER", class: BigDecimal, num1: 12345.12345, num2: 12345.12345, expected: 24690.2469 },
102
- { ora_data_type: "PLS_INTEGER", class: Integer, num1: 123456789, num2: 123456789, expected: 246913578 },
103
- { ora_data_type: "BINARY_INTEGER", class: Integer, num1: 123456789, num2: 123456789, expected: 246913578 },
104
- { ora_data_type: "SIMPLE_INTEGER", class: Integer, num1: 123456789, num2: 123456789, expected: 246913578, mandatory: true },
105
- { ora_data_type: "NATURAL", class: Integer, num1: 123456789, num2: 123456789, expected: 246913578 },
106
- { ora_data_type: "NATURALN", class: Integer, num1: 123456789, num2: 123456789, expected: 246913578, mandatory: true },
107
- { ora_data_type: "POSITIVE", class: Integer, num1: 123456789, num2: 123456789, expected: 246913578 },
108
- { ora_data_type: "POSITIVEN", class: Integer, num1: 123456789, num2: 123456789, expected: 246913578, mandatory: true },
109
- { ora_data_type: "SIGNTYPE", class: Integer, num1: 1, num2: -1, expected: 0 },
110
- ].each do |row|
111
- ora_data_type, class_, num1, num2, expected, mandatory = row.values
112
- describe ora_data_type do
113
- include_examples "Function with numeric", ora_data_type, class_, num1, num2, expected, mandatory
114
- end
115
- end
116
-
117
- describe "Boolean to NUMBER conversion" do
118
- before(:all) do
119
- plsql.connect! CONNECTION_PARAMS
120
- plsql.execute <<-SQL
121
- CREATE OR REPLACE FUNCTION test_num ( p_num NUMBER) RETURN NUMBER
122
- IS
123
- BEGIN
124
- RETURN p_num;
125
- END test_num;
126
- SQL
127
- end
128
-
129
- after(:all) do
130
- plsql.execute "DROP FUNCTION test_num"
131
- plsql.logoff
132
- end
133
- it "should convert true value to 1 for NUMBER parameter" do
134
- expect(plsql.test_num(true)).to eq(1)
135
- end
136
-
137
- it "should convert false value to 0 for NUMBER parameter" do
138
- expect(plsql.test_num(false)).to eq(0)
139
- end
140
- end
141
-
142
- describe "Function with date parameters" do
143
-
144
- before(:all) do
145
- plsql.connect! CONNECTION_PARAMS
146
- plsql.execute <<-SQL
147
- CREATE OR REPLACE FUNCTION test_date
148
- ( p_date DATE )
149
- RETURN DATE
150
- IS
151
- BEGIN
152
- RETURN p_date + 1;
153
- END test_date;
154
- SQL
155
- end
156
-
157
- before(:each) do
158
- plsql.default_timezone = :local
159
- end
160
-
161
- after(:all) do
162
- plsql.execute "DROP FUNCTION test_date"
163
- plsql.logoff
164
- end
165
-
166
- it "should process Time parameters" do
167
- now = Time.local(2008, 8, 12, 14, 28, 0)
168
- expect(plsql.test_date(now)).to eq(now + 60 * 60 * 24)
169
- end
170
-
171
- it "should process UTC Time parameters" do
172
- plsql.default_timezone = :utc
173
- now = Time.utc(2008, 8, 12, 14, 28, 0)
174
- expect(plsql.test_date(now)).to eq(now + 60 * 60 * 24)
175
- end
176
-
177
- it "should process DateTime parameters" do
178
- now = DateTime.parse(Time.local(2008, 8, 12, 14, 28, 0).iso8601)
179
- result = plsql.test_date(now)
180
- expect(result.class).to eq(Time)
181
- expect(result).to eq(Time.parse((now + 1).strftime("%c")))
182
- end
183
-
184
- it "should process old DateTime parameters" do
185
- now = DateTime.civil(1901, 1, 1, 12, 0, 0, plsql.local_timezone_offset)
186
- result = plsql.test_date(now)
187
- expect(result.class).to eq(Time)
188
- expect(result).to eq(Time.parse((now + 1).strftime("%c")))
189
- end
190
-
191
- it "should process Date parameters" do
192
- now = Date.new(2008, 8, 12)
193
- result = plsql.test_date(now)
194
- expect(result.class).to eq(Time)
195
- expect(result).to eq(Time.parse((now + 1).strftime("%c")))
196
- end
197
-
198
- it "should process old Date parameters" do
199
- now = Date.new(1901, 1, 1)
200
- result = plsql.test_date(now)
201
- expect(result.class).to eq(Time)
202
- expect(result).to eq(Time.parse((now + 1).strftime("%c")))
203
- end
204
-
205
- it "should process nil date parameter as NULL" do
206
- expect(plsql.test_date(nil)).to be_nil
207
- end
208
-
209
- end
210
-
211
- describe "Function with timestamp parameters" do
212
- before(:all) do
213
- plsql.connect! CONNECTION_PARAMS
214
- plsql.execute <<-SQL
215
- CREATE OR REPLACE FUNCTION test_timestamp
216
- ( p_time TIMESTAMP )
217
- RETURN TIMESTAMP
218
- IS
219
- BEGIN
220
- RETURN p_time + NUMTODSINTERVAL(1, 'DAY');
221
- END test_timestamp;
222
- SQL
223
- end
224
-
225
- after(:all) do
226
- plsql.execute "DROP FUNCTION test_timestamp"
227
- plsql.logoff
228
- end
229
-
230
- it "should process timestamp parameters" do
231
- # now = Time.now
232
- now = Time.local(2008, 8, 12, 14, 28, 0)
233
- expect(plsql.test_timestamp(now)).to eq(now + 60 * 60 * 24)
234
- end
235
-
236
- end
237
-
238
- describe "Function or procedure with XMLType parameters" do
239
- before(:all) do
240
- plsql.connect! CONNECTION_PARAMS
241
- @oracle12c_or_higher = !! plsql.connection.select_all(
242
- "select * from product_component_version where product like 'Oracle%' and to_number(substr(version,1,2)) >= 12")
243
- skip "Skip until furtuer investigation for #114" if @oracle12c_or_higher
244
- plsql.execute <<-SQL
245
- CREATE OR REPLACE FUNCTION test_xmltype
246
- ( p_xml XMLTYPE )
247
- RETURN XMLTYPE
248
- IS
249
- BEGIN
250
- RETURN p_xml;
251
- END test_xmltype;
252
- SQL
253
- plsql.execute <<-SQL
254
- CREATE OR REPLACE PROCEDURE test_xmltype2
255
- ( p_xml XMLTYPE, po_xml OUT XMLTYPE )
256
- IS
257
- BEGIN
258
- po_xml := p_xml;
259
- END test_xmltype2;
260
- SQL
261
- end
262
-
263
- after(:all) do
264
- plsql.execute "DROP FUNCTION test_xmltype" unless @oracle12c_or_higher
265
- plsql.execute "DROP PROCEDURE test_xmltype2" unless @oracle12c_or_higher
266
- plsql.logoff
267
- end
268
-
269
- it "should process XMLType parameters" do
270
- xml = "<DUMMY>value</DUMMY>"
271
- result = plsql.test_xmltype(xml)
272
- expect(result).to eq("<DUMMY>value</DUMMY>")
273
- end
274
-
275
- it "should work when passing a NULL value" do
276
- result = plsql.test_xmltype(nil)
277
- expect(result).to be_nil
278
- end
279
-
280
- it "should assign input parameter to putput parameter" do
281
- xml = "<DUMMY>value</DUMMY>"
282
- result = plsql.test_xmltype2(xml)
283
- expect(result[:po_xml]).to eq("<DUMMY>value</DUMMY>")
284
- end
285
- end
286
-
287
- describe "Procedure with output parameters" do
288
- before(:all) do
289
- plsql.connect! CONNECTION_PARAMS
290
- plsql.execute <<-SQL
291
- CREATE OR REPLACE PROCEDURE test_copy
292
- ( p_from VARCHAR2, p_to OUT VARCHAR2, p_to_double OUT VARCHAR2 )
293
- IS
294
- BEGIN
295
- p_to := p_from;
296
- p_to_double := p_from || p_from;
297
- END test_copy;
298
- SQL
299
- end
300
-
301
- after(:all) do
302
- plsql.execute "DROP PROCEDURE test_copy"
303
- plsql.logoff
304
- end
305
-
306
- it "should return hash with output parameters" do
307
- expect(plsql.test_copy("abc", nil, nil)).to eq(p_to: "abc", p_to_double: "abcabc")
308
- end
309
-
310
- it "should return hash with output parameters when called with named parameters" do
311
- expect(plsql.test_copy(p_from: "abc", p_to: nil, p_to_double: nil)).to eq(p_to: "abc", p_to_double: "abcabc")
312
- end
313
-
314
- it "should substitute output parameters with nil if they are not specified" do
315
- expect(plsql.test_copy("abc")).to eq(p_to: "abc", p_to_double: "abcabc")
316
- end
317
-
318
- it "should substitute named output parameters with nil if they are not specified" do
319
- expect(plsql.test_copy(p_from: "abc")).to eq(p_to: "abc", p_to_double: "abcabc")
320
- end
321
-
322
- end
323
-
324
- describe "Package with procedures with same name but different argument lists" do
325
- before(:all) do
326
- plsql.connect! CONNECTION_PARAMS
327
- plsql.execute <<-SQL
328
- CREATE OR REPLACE PACKAGE test_package2 IS
329
- FUNCTION test_procedure ( p_string VARCHAR2 )
330
- RETURN VARCHAR2;
331
- PROCEDURE test_procedure ( p_string VARCHAR2, p_result OUT VARCHAR2 )
332
- ;
333
- PROCEDURE test_procedure ( p_number NUMBER, p_result OUT VARCHAR2 )
334
- ;
335
- FUNCTION test_procedure2 ( p_string VARCHAR2 )
336
- RETURN VARCHAR2;
337
- FUNCTION test_function ( p_string VARCHAR2, p_string2 VARCHAR2 DEFAULT ' ')
338
- RETURN VARCHAR2;
339
- FUNCTION test_function ( p_number NUMBER, p_number2 NUMBER DEFAULT 1 )
340
- RETURN NUMBER;
341
- END;
342
- SQL
343
- plsql.execute <<-SQL
344
- CREATE OR REPLACE PACKAGE BODY test_package2 IS
345
- FUNCTION test_procedure ( p_string VARCHAR2 )
346
- RETURN VARCHAR2
347
- IS
348
- BEGIN
349
- RETURN UPPER(p_string);
350
- END test_procedure;
351
- PROCEDURE test_procedure ( p_string VARCHAR2, p_result OUT VARCHAR2 )
352
- IS
353
- BEGIN
354
- p_result := UPPER(p_string);
355
- END test_procedure;
356
- PROCEDURE test_procedure ( p_number NUMBER, p_result OUT VARCHAR2 )
357
- IS
358
- BEGIN
359
- p_result := LOWER(TO_CHAR(p_number));
360
- END test_procedure;
361
- FUNCTION test_procedure2 ( p_string VARCHAR2 )
362
- RETURN VARCHAR2
363
- IS
364
- BEGIN
365
- RETURN UPPER(p_string);
366
- END test_procedure2;
367
- FUNCTION test_function ( p_string VARCHAR2, p_string2 VARCHAR2)
368
- RETURN VARCHAR2
369
- IS
370
- BEGIN
371
- RETURN p_string||p_string2;
372
- END;
373
- FUNCTION test_function ( p_number NUMBER, p_number2 NUMBER)
374
- RETURN NUMBER
375
- IS
376
- BEGIN
377
- RETURN p_number + p_number2;
378
- END;
379
- END;
380
- SQL
381
-
382
- end
383
-
384
- after(:all) do
385
- plsql.execute "DROP PACKAGE test_package2"
386
- plsql.logoff
387
- end
388
-
389
- it "should find existing package" do
390
- expect(PLSQL::Package.find(plsql, :test_package2)).not_to be_nil
391
- end
392
-
393
- it "should identify overloaded procedure definition" do
394
- @procedure = PLSQL::Procedure.find(plsql, :test_procedure, "TEST_PACKAGE2")
395
- expect(@procedure).not_to be_nil
396
- expect(@procedure).to be_overloaded
397
- end
398
-
399
- it "should identify non-overloaded procedure definition" do
400
- @procedure = PLSQL::Procedure.find(plsql, :test_procedure2, "TEST_PACKAGE2")
401
- expect(@procedure).not_to be_nil
402
- expect(@procedure).not_to be_overloaded
403
- end
404
-
405
- it "should execute correct procedures based on number of arguments and return correct value" do
406
- expect(plsql.test_package2.test_procedure("xxx")).to eq("XXX")
407
- expect(plsql.test_package2.test_procedure("xxx", nil)).to eq(p_result: "XXX")
408
- end
409
-
410
- it "should execute correct procedures based on number of named arguments and return correct value" do
411
- expect(plsql.test_package2.test_procedure(p_string: "xxx")).to eq("XXX")
412
- expect(plsql.test_package2.test_procedure(p_string: "xxx", p_result: nil)).to eq(p_result: "XXX")
413
- end
414
-
415
- it "should raise exception if procedure cannot be found based on number of arguments" do
416
- expect { plsql.test_package2.test_procedure() }.to raise_error(/wrong number or types of arguments/i)
417
- end
418
-
419
- it "should find procedure based on types of arguments" do
420
- expect(plsql.test_package2.test_procedure(111, nil)).to eq(p_result: "111")
421
- end
422
-
423
- it "should find procedure based on names of named arguments" do
424
- expect(plsql.test_package2.test_procedure(p_number: 111, p_result: nil)).to eq(p_result: "111")
425
- end
426
-
427
- it "should find matching procedure based on partial list of named arguments" do
428
- expect(plsql.test_package2.test_function(p_string: "xxx")).to eq("xxx ")
429
- expect(plsql.test_package2.test_function(p_number: 1)).to eq(2)
430
- end
431
-
432
- end
433
-
434
- describe "Function with output parameters" do
435
- before(:all) do
436
- plsql.connect! CONNECTION_PARAMS
437
- plsql.execute <<-SQL
438
- CREATE OR REPLACE FUNCTION test_copy_function
439
- ( p_from VARCHAR2, p_to OUT VARCHAR2, p_to_double OUT VARCHAR2 )
440
- RETURN NUMBER
441
- IS
442
- BEGIN
443
- p_to := p_from;
444
- p_to_double := p_from || p_from;
445
- RETURN LENGTH(p_from);
446
- END test_copy_function;
447
- SQL
448
- end
449
-
450
- after(:all) do
451
- plsql.execute "DROP FUNCTION test_copy_function"
452
- plsql.logoff
453
- end
454
-
455
- it "should return array with return value and hash of output parameters" do
456
- expect(plsql.test_copy_function("abc", nil, nil)).to eq([3, { p_to: "abc", p_to_double: "abcabc" }])
457
- end
458
-
459
- it "should return array with return value and hash of output parameters when called with named parameters" do
460
- expect(plsql.test_copy_function(p_from: "abc", p_to: nil, p_to_double: nil)).to eq(
461
- [3, { p_to: "abc", p_to_double: "abcabc" }]
462
- )
463
- end
464
-
465
- it "should substitute output parameters with nil if they are not specified" do
466
- expect(plsql.test_copy_function("abc")).to eq([3, { p_to: "abc", p_to_double: "abcabc" }])
467
- end
468
-
469
- end
470
-
471
- describe "Function or procedure without parameters" do
472
- before(:all) do
473
- plsql.connect! CONNECTION_PARAMS
474
- plsql.execute <<-SQL
475
- CREATE OR REPLACE FUNCTION test_no_params
476
- RETURN VARCHAR2
477
- IS
478
- BEGIN
479
- RETURN 'dummy';
480
- END test_no_params;
481
- SQL
482
- plsql.execute <<-SQL
483
- CREATE OR REPLACE PROCEDURE test_proc_no_params
484
- IS
485
- BEGIN
486
- NULL;
487
- END test_proc_no_params;
488
- SQL
489
- end
490
-
491
- after(:all) do
492
- plsql.execute "DROP FUNCTION test_no_params"
493
- plsql.execute "DROP PROCEDURE test_proc_no_params"
494
- plsql.logoff
495
- end
496
-
497
- it "should find function" do
498
- expect(PLSQL::Procedure.find(plsql, :test_no_params)).not_to be_nil
499
- end
500
-
501
- it "should return function value" do
502
- expect(plsql.test_no_params).to eq("dummy")
503
- end
504
-
505
- it "should find procedure" do
506
- expect(PLSQL::Procedure.find(plsql, :test_proc_no_params)).not_to be_nil
507
- end
508
-
509
- it "should execute procedure" do
510
- expect(plsql.test_proc_no_params).to be_nil
511
- end
512
-
513
- end
514
-
515
- describe "Function with CLOB parameter and return value" do
516
- before(:all) do
517
- plsql.connect! CONNECTION_PARAMS
518
- plsql.execute <<-SQL
519
- CREATE OR REPLACE FUNCTION test_clob
520
- ( p_clob CLOB )
521
- RETURN CLOB
522
- IS
523
- BEGIN
524
- RETURN p_clob;
525
- END test_clob;
526
- SQL
527
- plsql.execute "CREATE TABLE test_clob_table (clob_col CLOB)"
528
- plsql.execute <<-SQL
529
- CREATE OR REPLACE FUNCTION test_clob_insert
530
- ( p_clob CLOB )
531
- RETURN CLOB
532
- IS
533
- CURSOR clob_cur IS
534
- SELECT clob_col
535
- FROM test_clob_table;
536
-
537
- v_dummy CLOB;
538
- BEGIN
539
- DELETE FROM test_clob_table;
540
- INSERT INTO test_clob_table (clob_col) VALUES (p_clob);
541
-
542
- OPEN clob_cur;
543
- FETCH clob_cur INTO v_dummy;
544
- CLOSE clob_cur;
545
-
546
- RETURN v_dummy;
547
- END test_clob_insert;
548
- SQL
549
- end
550
-
551
- after(:all) do
552
- plsql.execute "DROP FUNCTION test_clob"
553
- plsql.execute "DROP FUNCTION test_clob_insert"
554
- plsql.execute "DROP TABLE test_clob_table"
555
- plsql.logoff
556
- end
557
-
558
- it "should find existing procedure" do
559
- expect(PLSQL::Procedure.find(plsql, :test_clob)).not_to be_nil
560
- end
561
-
562
- it "should execute function and return correct value" do
563
- large_text = "ābčdēfghij" * 10_000
564
- expect(plsql.test_clob(large_text)).to eq(large_text)
565
- end
566
-
567
- unless defined?(JRUBY_VERSION)
568
-
569
- it "should execute function with empty string and return nil (oci8 cannot pass empty CLOB parameter)" do
570
- text = ""
571
- expect(plsql.test_clob(text)).to be_nil
572
- end
573
-
574
- it "should execute function which inserts the CLOB parameter into a table with empty string and return nil" do
575
- text = ""
576
- expect(plsql.test_clob_insert(text)).to be_nil
577
- end
578
-
579
- else
580
-
581
- it "should execute function with empty string and return empty string" do
582
- text = ""
583
- expect(plsql.test_clob(text)).to eq(text)
584
- end
585
-
586
- end
587
-
588
- it "should execute function with nil and return nil" do
589
- expect(plsql.test_clob(nil)).to be_nil
590
- end
591
-
592
- it "should execute function which inserts the CLOB parameter into a table with nil and return nil" do
593
- expect(plsql.test_clob_insert(nil)).to be_nil
594
- end
595
-
596
- end
597
-
598
- describe "Procedrue with CLOB parameter and return value" do
599
- before(:all) do
600
- plsql.connect! CONNECTION_PARAMS
601
- plsql.execute <<-SQL
602
- CREATE OR REPLACE PROCEDURE test_clob_proc
603
- ( p_clob CLOB,
604
- p_return OUT CLOB)
605
- IS
606
- BEGIN
607
- p_return := p_clob;
608
- END test_clob_proc;
609
- SQL
610
- end
611
-
612
- after(:all) do
613
- plsql.execute "DROP PROCEDURE test_clob_proc"
614
- plsql.logoff
615
- end
616
-
617
- it "should find existing procedure" do
618
- expect(PLSQL::Procedure.find(plsql, :test_clob_proc)).not_to be_nil
619
- end
620
-
621
- it "should execute function and return correct value" do
622
- large_text = "ābčdēfghij" * 10_000
623
- expect(plsql.test_clob_proc(large_text)[:p_return]).to eq(large_text)
624
- end
625
- end
626
-
627
- describe "Procedrue with BLOB parameter and return value" do
628
- before(:all) do
629
- plsql.connect! CONNECTION_PARAMS
630
- plsql.execute <<-SQL
631
- CREATE OR REPLACE PROCEDURE test_blob_proc
632
- ( p_blob BLOB,
633
- p_return OUT BLOB)
634
- IS
635
- BEGIN
636
- p_return := p_blob;
637
- END test_blob_proc;
638
- SQL
639
- end
640
-
641
- after(:all) do
642
- plsql.execute "DROP PROCEDURE test_blob_proc"
643
- plsql.logoff
644
- end
645
-
646
- it "should find existing procedure" do
647
- expect(PLSQL::Procedure.find(plsql, :test_blob_proc)).not_to be_nil
648
- end
649
-
650
- it "should execute function and return correct value" do
651
- large_binary = '\000\001\002\003\004\005\006\007\010\011' * 10_000
652
- expect(plsql.test_blob_proc(large_binary)[:p_return]).to eq(large_binary)
653
- end
654
- end
655
-
656
- describe "Function with record parameter" do
657
- before(:all) do
658
- plsql.connect! CONNECTION_PARAMS
659
- plsql.execute "DROP TABLE test_employees" rescue nil
660
- plsql.execute <<-SQL
661
- CREATE TABLE test_employees (
662
- employee_id NUMBER(15),
663
- first_name VARCHAR2(50),
664
- last_name VARCHAR(50),
665
- hire_date DATE
666
- )
667
- SQL
668
- plsql.execute <<-SQL
669
- CREATE OR REPLACE FUNCTION test_full_name (p_employee test_employees%ROWTYPE)
670
- RETURN VARCHAR2
671
- IS
672
- BEGIN
673
- RETURN p_employee.first_name || ' ' || p_employee.last_name;
674
- END test_full_name;
675
- SQL
676
- plsql.execute <<-SQL
677
- CREATE OR REPLACE PACKAGE test_record IS
678
- TYPE t_employee IS RECORD(
679
- employee_id NUMBER(15),
680
- first_name VARCHAR2(50),
681
- last_name VARCHAR(50),
682
- hire_date DATE
683
- );
684
-
685
- TYPE t_candidate IS RECORD(
686
- candidate_id NUMBER(5),
687
- is_approved BOOLEAN
688
- );
689
-
690
- TYPE table_of_records IS TABLE OF test_record.t_employee;
691
-
692
- FUNCTION test_full_name(p_employee t_employee)
693
- RETURN VARCHAR2;
694
-
695
- FUNCTION test_empty_records
696
- RETURN table_of_records;
697
-
698
- FUNCTION is_approved(p_candidate t_candidate)
699
- RETURN BOOLEAN;
700
-
701
- FUNCTION f_set_candidate_status(p_candidate t_candidate, p_status boolean)
702
- RETURN t_candidate;
703
-
704
- PROCEDURE p_set_candidate_status(p_candidate t_candidate, p_status boolean, p_result OUT t_candidate);
705
- END;
706
- SQL
707
- plsql.execute <<-SQL
708
- CREATE OR REPLACE PACKAGE BODY test_record IS
709
- FUNCTION test_full_name (p_employee t_employee)
710
- RETURN VARCHAR2
711
- IS
712
- BEGIN
713
- RETURN p_employee.first_name || ' ' || p_employee.last_name;
714
- END;
715
-
716
- FUNCTION test_empty_records
717
- RETURN table_of_records
718
- IS
719
- CURSOR employees_cur
720
- IS
721
- SELECT
722
- null employee_id,
723
- null first_name,
724
- null last_name,
725
- null hire_date
726
- FROM dual
727
- WHERE 1 = 2;
728
- employees_tab table_of_records;
729
- BEGIN
730
- OPEN employees_cur;
731
- FETCH employees_cur BULK COLLECT INTO employees_tab;
732
- CLOSE employees_cur;
733
- RETURN employees_tab;
734
- END;
735
-
736
- FUNCTION is_approved(p_candidate t_candidate)
737
- RETURN BOOLEAN
738
- IS
739
- BEGIN
740
- RETURN p_candidate.is_approved;
741
- END;
742
-
743
- FUNCTION f_set_candidate_status(p_candidate t_candidate, p_status boolean)
744
- RETURN t_candidate
745
- IS
746
- result t_candidate := p_candidate;
747
- BEGIN
748
- result.is_approved := p_status;
749
- return result;
750
- END;
751
-
752
- PROCEDURE p_set_candidate_status(p_candidate t_candidate, p_status boolean, p_result OUT t_candidate)
753
- IS
754
- BEGIN
755
- p_result := p_candidate;
756
- p_result.is_approved := p_status;
757
- END;
758
- END;
759
- SQL
760
- plsql.execute <<-SQL
761
- CREATE OR REPLACE FUNCTION test_employee_record (p_employee test_employees%ROWTYPE)
762
- RETURN test_employees%ROWTYPE
763
- IS
764
- BEGIN
765
- RETURN p_employee;
766
- END test_employee_record;
767
- SQL
768
- plsql.execute <<-SQL
769
- CREATE OR REPLACE FUNCTION test_employee_record2 (p_employee test_employees%ROWTYPE, x_employee IN OUT test_employees%ROWTYPE)
770
- RETURN test_employees%ROWTYPE
771
- IS
772
- BEGIN
773
- x_employee.employee_id := p_employee.employee_id;
774
- x_employee.first_name := p_employee.first_name;
775
- x_employee.last_name := p_employee.last_name;
776
- x_employee.hire_date := p_employee.hire_date;
777
- RETURN p_employee;
778
- END test_employee_record2;
779
- SQL
780
- @p_employee = {
781
- employee_id: 1,
782
- first_name: "First",
783
- last_name: "Last",
784
- hire_date: Time.local(2000, 01, 31)
785
- }
786
- @p_employee2 = {
787
- "employee_id" => 1,
788
- "FIRST_NAME" => "Second",
789
- "last_name" => "Last",
790
- "hire_date" => Time.local(2000, 01, 31)
791
- }
792
- end
793
-
794
- after(:all) do
795
- plsql.execute "DROP FUNCTION test_full_name"
796
- plsql.execute "DROP PACKAGE test_record"
797
- plsql.execute "DROP FUNCTION test_employee_record"
798
- plsql.execute "DROP FUNCTION test_employee_record2"
799
- plsql.execute "DROP TABLE test_employees"
800
- plsql.logoff
801
- end
802
-
803
- it "should find existing function" do
804
- expect(PLSQL::Procedure.find(plsql, :test_full_name)).not_to be_nil
805
- end
806
-
807
- it "should execute function with named parameter and return correct value" do
808
- expect(plsql.test_full_name(p_employee: @p_employee)).to eq("First Last")
809
- end
810
-
811
- it "should execute function with sequential parameter and return correct value" do
812
- expect(plsql.test_full_name(@p_employee)).to eq("First Last")
813
- end
814
-
815
- it "should execute function with Hash parameter using strings as keys" do
816
- expect(plsql.test_full_name(@p_employee2)).to eq("Second Last")
817
- end
818
-
819
- it "should raise error if wrong field name is passed for record parameter" do
820
- expect do
821
- expect(plsql.test_full_name(@p_employee.merge xxx: "xxx")).to eq("Second Last")
822
- end.to raise_error(ArgumentError)
823
- end
824
-
825
- it "should return empty table of records" do
826
- expect(plsql.test_record.test_empty_records()).to eq([])
827
- end
828
-
829
- it "should return record return value" do
830
- expect(plsql.test_employee_record(@p_employee)).to eq(@p_employee)
831
- end
832
-
833
- it "should return record return value and output record parameter value" do
834
- expect(plsql.test_employee_record2(@p_employee, @p_employee2)).to eq([@p_employee, { x_employee: @p_employee }])
835
- end
836
-
837
- it "should execute package function with parameter with record type defined in package" do
838
- expect(plsql.test_record.test_full_name(@p_employee)).to eq("First Last")
839
- end
840
-
841
- context "functions with record parameters having boolean attributes" do
842
- def new_candidate(status)
843
- { candidate_id: 1, is_approved: status }
844
- end
845
-
846
- [true, false, nil].each do |status|
847
- it "should execute function with record having boolean attribute (#{status})" do
848
- expect(plsql.test_record.is_approved(new_candidate(status))).to eq status
849
- end
850
-
851
- it "procedure should return record with boolean attribute as output parameter (#{status})" do
852
- expect(plsql.test_record.p_set_candidate_status(new_candidate(nil), status)[:p_result]).to eq new_candidate(status)
853
- end
854
-
855
- it "function should return record with boolean attribute (#{status})" do
856
- expect(plsql.test_record.f_set_candidate_status(new_candidate(nil), status)).to eq new_candidate(status)
857
- end
858
- end
859
- end
860
-
861
- end
862
-
863
- describe "Function with boolean parameters" do
864
- before(:all) do
865
- plsql.connect! CONNECTION_PARAMS
866
- plsql.execute <<-SQL
867
- CREATE OR REPLACE FUNCTION test_boolean
868
- ( p_boolean BOOLEAN )
869
- RETURN BOOLEAN
870
- IS
871
- BEGIN
872
- RETURN p_boolean;
873
- END test_boolean;
874
- SQL
875
- plsql.execute <<-SQL
876
- CREATE OR REPLACE PROCEDURE test_boolean2
877
- ( p_boolean BOOLEAN, x_boolean OUT BOOLEAN )
878
- IS
879
- BEGIN
880
- x_boolean := p_boolean;
881
- END test_boolean2;
882
- SQL
883
- end
884
-
885
- after(:all) do
886
- plsql.execute "DROP FUNCTION test_boolean"
887
- plsql.execute "DROP PROCEDURE test_boolean2"
888
- plsql.logoff
889
- end
890
-
891
- it "should accept true value and return true value" do
892
- expect(plsql.test_boolean(true)).to eq(true)
893
- end
894
-
895
- it "should accept false value and return false value" do
896
- expect(plsql.test_boolean(false)).to eq(false)
897
- end
898
-
899
- it "should accept nil value and return nil value" do
900
- expect(plsql.test_boolean(nil)).to be_nil
901
- end
902
-
903
- it "should accept true value and assign true value to output parameter" do
904
- expect(plsql.test_boolean2(true, nil)).to eq(x_boolean: true)
905
- end
906
-
907
- it "should accept false value and assign false value to output parameter" do
908
- expect(plsql.test_boolean2(false, nil)).to eq(x_boolean: false)
909
- end
910
-
911
- it "should accept nil value and assign nil value to output parameter" do
912
- expect(plsql.test_boolean2(nil, nil)).to eq(x_boolean: nil)
913
- end
914
-
915
- end
916
-
917
- describe "Function with object type parameter" do
918
- before(:all) do
919
- plsql.connect! CONNECTION_PARAMS
920
- plsql.execute "DROP TYPE t_employee" rescue nil
921
- plsql.execute "DROP TYPE t_phones" rescue nil
922
- plsql.execute <<-SQL
923
- CREATE OR REPLACE TYPE t_address AS OBJECT (
924
- street VARCHAR2(50),
925
- city VARCHAR2(50),
926
- country VARCHAR2(50)
927
- )
928
- SQL
929
- plsql.execute <<-SQL
930
- CREATE OR REPLACE TYPE t_phone AS OBJECT (
931
- type VARCHAR2(10),
932
- phone_number VARCHAR2(50)
933
- )
934
- SQL
935
- plsql.execute <<-SQL
936
- CREATE OR REPLACE TYPE t_phones AS TABLE OF T_PHONE
937
- SQL
938
- plsql.execute <<-SQL
939
- CREATE OR REPLACE TYPE t_employee AS OBJECT (
940
- employee_id NUMBER(15),
941
- first_name VARCHAR2(50),
942
- last_name VARCHAR(50),
943
- hire_date DATE,
944
- address t_address,
945
- phones t_phones
946
- )
947
- SQL
948
- plsql.execute <<-SQL
949
- CREATE OR REPLACE FUNCTION test_full_name (p_employee t_employee)
950
- RETURN VARCHAR2
951
- IS
952
- BEGIN
953
- RETURN p_employee.first_name || ' ' || p_employee.last_name;
954
- END;
955
- SQL
956
- plsql.execute <<-SQL
957
- CREATE OR REPLACE FUNCTION test_employee_object (p_employee t_employee)
958
- RETURN t_employee
959
- IS
960
- BEGIN
961
- RETURN p_employee;
962
- END;
963
- SQL
964
- plsql.execute <<-SQL
965
- CREATE OR REPLACE FUNCTION test_employee_object2 (p_employee t_employee, x_employee OUT t_employee)
966
- RETURN t_employee
967
- IS
968
- BEGIN
969
- x_employee := p_employee;
970
- RETURN p_employee;
971
- END;
972
- SQL
973
- @p_employee = {
974
- employee_id: 1,
975
- first_name: "First",
976
- last_name: "Last",
977
- hire_date: Time.local(2000, 01, 31),
978
- address: { street: "Main street 1", city: "Riga", country: "Latvia" },
979
- phones: [{ type: "mobile", phone_number: "123456" }, { type: "home", phone_number: "654321" }]
980
- }
981
- end
982
-
983
- after(:all) do
984
- plsql.execute "DROP FUNCTION test_full_name"
985
- plsql.execute "DROP FUNCTION test_employee_object"
986
- plsql.execute "DROP FUNCTION test_employee_object2"
987
- plsql.execute "DROP TYPE t_employee"
988
- plsql.execute "DROP TYPE t_address"
989
- plsql.execute "DROP TYPE t_phones"
990
- plsql.execute "DROP TYPE t_phone"
991
- plsql.logoff
992
- end
993
-
994
- it "should find existing function" do
995
- expect(PLSQL::Procedure.find(plsql, :test_full_name)).not_to be_nil
996
- end
997
-
998
- it "should execute function with named parameter and return correct value" do
999
- expect(plsql.test_full_name(p_employee: @p_employee)).to eq("First Last")
1000
- end
1001
-
1002
- it "should execute function with sequential parameter and return correct value" do
1003
- expect(plsql.test_full_name(@p_employee)).to eq("First Last")
1004
- end
1005
-
1006
- it "should raise error if wrong field name is passed for record parameter" do
1007
- expect do
1008
- plsql.test_full_name(@p_employee.merge xxx: "xxx")
1009
- end.to raise_error(ArgumentError)
1010
- end
1011
-
1012
- it "should return object type return value" do
1013
- expect(plsql.test_employee_object(@p_employee)).to eq(@p_employee)
1014
- end
1015
-
1016
- it "should return object type return value and output object type parameter value" do
1017
- expect(plsql.test_employee_object2(@p_employee, nil)).to eq([@p_employee, { x_employee: @p_employee }])
1018
- end
1019
-
1020
- it "should accept NULL as input parameter" do
1021
- expect(plsql.test_employee_object(nil)).to eq(nil)
1022
- end
1023
-
1024
- end
1025
-
1026
- describe "Function with table parameter" do
1027
- before(:all) do
1028
- plsql.connect! CONNECTION_PARAMS
1029
- # Array of numbers
1030
- plsql.execute <<-SQL
1031
- CREATE OR REPLACE TYPE t_numbers AS TABLE OF NUMBER(15)
1032
- SQL
1033
- plsql.execute <<-SQL
1034
- CREATE OR REPLACE FUNCTION test_sum (p_numbers IN t_numbers)
1035
- RETURN NUMBER
1036
- IS
1037
- l_sum NUMBER(15) := 0;
1038
- BEGIN
1039
- IF p_numbers.COUNT > 0 THEN
1040
- FOR i IN p_numbers.FIRST..p_numbers.LAST LOOP
1041
- IF p_numbers.EXISTS(i) THEN
1042
- l_sum := l_sum + p_numbers(i);
1043
- END IF;
1044
- END LOOP;
1045
- RETURN l_sum;
1046
- ELSE
1047
- RETURN NULL;
1048
- END IF;
1049
- END;
1050
- SQL
1051
-
1052
- plsql.execute <<-SQL
1053
- CREATE OR REPLACE FUNCTION test_increment(p_numbers IN t_numbers, p_increment_by IN NUMBER DEFAULT 1)
1054
- RETURN t_numbers
1055
- IS
1056
- l_numbers t_numbers := t_numbers();
1057
- BEGIN
1058
- FOR i IN p_numbers.FIRST..p_numbers.LAST LOOP
1059
- IF p_numbers.EXISTS(i) THEN
1060
- l_numbers.EXTEND;
1061
- l_numbers(i) := p_numbers(i) + p_increment_by;
1062
- END IF;
1063
- END LOOP;
1064
- RETURN l_numbers;
1065
- END;
1066
- SQL
1067
-
1068
- # Array of strings
1069
- plsql.execute <<-SQL
1070
- CREATE OR REPLACE TYPE t_strings AS TABLE OF VARCHAR2(4000)
1071
- SQL
1072
- plsql.execute <<-SQL
1073
- CREATE OR REPLACE FUNCTION test_copy_strings(p_strings IN t_strings, x_strings OUT t_strings)
1074
- RETURN t_strings
1075
- IS
1076
- BEGIN
1077
- x_strings := t_strings();
1078
- FOR i IN p_strings.FIRST..p_strings.LAST LOOP
1079
- IF p_strings.EXISTS(i) THEN
1080
- x_strings.EXTEND;
1081
- x_strings(i) := p_strings(i);
1082
- END IF;
1083
- END LOOP;
1084
- RETURN x_strings;
1085
- END;
1086
- SQL
1087
-
1088
- # Type definition inside package
1089
- plsql.execute <<-SQL
1090
- CREATE OR REPLACE PACKAGE test_collections IS
1091
- TYPE t_numbers IS TABLE OF NUMBER(15);
1092
- FUNCTION test_sum (p_numbers IN t_numbers)
1093
- RETURN NUMBER;
1094
- FUNCTION test_function_failure (p_numbers IN t_numbers, p_force_failure IN VARCHAR2 DEFAULT 'N')
1095
- RETURN NUMBER;
1096
- FUNCTION test_numbers (p_numbers IN t_numbers, x_numbers OUT t_numbers)
1097
- RETURN t_numbers;
1098
- TYPE t_employee IS RECORD(
1099
- employee_id NUMBER(15),
1100
- first_name VARCHAR2(50),
1101
- last_name VARCHAR(50),
1102
- hire_date DATE
1103
- );
1104
- TYPE t_employees IS TABLE OF test_collections.t_employee;
1105
- FUNCTION test_employees (p_employees IN OUT t_employees)
1106
- RETURN t_employees;
1107
- -- these types with tables in lower level are not yet supported
1108
- TYPE t_employee2 IS RECORD(
1109
- employee_id NUMBER(15),
1110
- first_name VARCHAR2(50),
1111
- last_name VARCHAR(50),
1112
- hire_date DATE,
1113
- numbers test_collections.t_numbers
1114
- );
1115
- FUNCTION test_employee2 (p_employee IN OUT t_employee2)
1116
- RETURN t_employee2;
1117
- TYPE t_employees2 IS TABLE OF t_employee2;
1118
- FUNCTION test_employees2 (p_employees IN OUT t_employees2)
1119
- RETURN t_employees2;
1120
-
1121
- TYPE t_nstring IS RECORD(
1122
- ch_10bytes CHAR(10 BYTE),
1123
- ch_10chars CHAR(10 CHAR),
1124
- nch_10chars NCHAR(10 CHAR),
1125
- str_10bytes VARCHAR2(10 BYTE),
1126
- str_10chars VARCHAR2(10 CHAR),
1127
- nstr_10chars NVARCHAR2(10)
1128
- );
1129
- TYPE t_nstrings IS TABLE OF t_nstring;
1130
- FUNCTION test_nstring (p_strings IN t_nstrings, p_out OUT t_nstrings)
1131
- return NVARCHAR2;
1132
- END;
1133
- SQL
1134
- plsql.execute <<-SQL
1135
- CREATE OR REPLACE PACKAGE BODY test_collections IS
1136
- FUNCTION test_sum (p_numbers IN t_numbers)
1137
- RETURN NUMBER
1138
- IS
1139
- l_sum NUMBER(15) := 0;
1140
- BEGIN
1141
- IF p_numbers.COUNT > 0 THEN
1142
- FOR i IN p_numbers.FIRST..p_numbers.LAST LOOP
1143
- IF p_numbers.EXISTS(i) THEN
1144
- l_sum := l_sum + p_numbers(i);
1145
- END IF;
1146
- END LOOP;
1147
- RETURN l_sum;
1148
- ELSE
1149
- RETURN NULL;
1150
- END IF;
1151
- END;
1152
- FUNCTION test_function_failure (p_numbers IN t_numbers, p_force_failure IN VARCHAR2 DEFAULT 'N')
1153
- RETURN NUMBER
1154
- IS
1155
- BEGIN
1156
- IF p_force_failure = 'Y' THEN
1157
- raise_application_error(-20000, 'Simulate business error to test clearing of temp table.');
1158
- END IF;
1159
- RETURN p_numbers.COUNT;
1160
- END;
1161
- FUNCTION test_numbers (p_numbers IN t_numbers, x_numbers OUT t_numbers)
1162
- RETURN t_numbers
1163
- IS
1164
- BEGIN
1165
- x_numbers := p_numbers;
1166
- RETURN p_numbers;
1167
- END;
1168
- FUNCTION test_employees (p_employees IN OUT t_employees)
1169
- RETURN t_employees
1170
- IS
1171
- BEGIN
1172
- RETURN p_employees;
1173
- END;
1174
- FUNCTION test_employee2 (p_employee IN OUT t_employee2)
1175
- RETURN t_employee2
1176
- IS
1177
- BEGIN
1178
- RETURN p_employee;
1179
- END;
1180
- FUNCTION test_employees2 (p_employees IN OUT t_employees2)
1181
- RETURN t_employees2
1182
- IS
1183
- BEGIN
1184
- RETURN p_employees;
1185
- END;
1186
- FUNCTION test_nstring (p_strings IN t_nstrings, p_out OUT t_nstrings)
1187
- return NVARCHAR2
1188
- IS
1189
- tmp1 NVARCHAR2(2000);
1190
- x pls_integer;
1191
- BEGIN
1192
- p_out := p_strings;
1193
- IF p_strings.count=0 THEN
1194
- RETURN N'';
1195
- END IF;
1196
- x := p_strings.first;
1197
- WHILE x IS NOT NULL LOOP
1198
- tmp1 := tmp1 || rtrim(p_strings(x).nch_10chars) || p_strings(x).nstr_10chars || ',';
1199
- x := p_strings.next(x);
1200
- END LOOP;
1201
- RETURN tmp1;
1202
- END;
1203
- END;
1204
- SQL
1205
- @employees = (1..10).map do |i|
1206
- {
1207
- employee_id: i,
1208
- first_name: "First #{i}",
1209
- last_name: "Last #{i}",
1210
- hire_date: Time.local(2000, 01, i),
1211
- }
1212
- end
1213
- @nstrings = (1..5).map do |i|
1214
- {
1215
- ch_10bytes: "Ch #{i}B ",
1216
- ch_10chars: "Ch #{i}C ",
1217
- nch_10chars: "NCh #{i} ",
1218
- str_10bytes: "Str #{i}C",
1219
- str_10chars: "Str #{i}B",
1220
- nstr_10chars: "NStr #{i}",
1221
- }
1222
- end
1223
-
1224
- # Array of objects
1225
- plsql.execute <<-SQL
1226
- CREATE OR REPLACE TYPE t_phone AS OBJECT (
1227
- type VARCHAR2(10),
1228
- phone_number VARCHAR2(50)
1229
- )
1230
- SQL
1231
- plsql.execute <<-SQL
1232
- CREATE OR REPLACE TYPE t_phones AS TABLE OF T_PHONE
1233
- SQL
1234
- plsql.execute <<-SQL
1235
- CREATE OR REPLACE FUNCTION test_copy_objects(p_phones IN t_phones, x_phones OUT t_phones)
1236
- RETURN t_phones
1237
- IS
1238
- BEGIN
1239
- x_phones := p_phones;
1240
- RETURN x_phones;
1241
- END;
1242
- SQL
1243
- end
1244
-
1245
- after(:all) do
1246
- plsql.execute "DROP FUNCTION test_sum"
1247
- plsql.execute "DROP FUNCTION test_increment"
1248
- plsql.execute "DROP FUNCTION test_copy_strings"
1249
- plsql.execute "DROP PACKAGE test_collections"
1250
- plsql.execute "DROP FUNCTION test_copy_objects"
1251
- plsql.execute "DROP TYPE t_numbers"
1252
- plsql.execute "DROP TYPE t_strings"
1253
- plsql.execute "DROP TYPE t_phones"
1254
- plsql.execute "DROP TYPE t_phone"
1255
- plsql.connection.drop_session_ruby_temporary_tables
1256
- plsql.logoff
1257
- end
1258
-
1259
- it "should find existing function" do
1260
- expect(PLSQL::Procedure.find(plsql, :test_sum)).not_to be_nil
1261
- end
1262
-
1263
- it "should execute function with number array parameter" do
1264
- expect(plsql.test_sum([1, 2, 3, 4])).to eq(10)
1265
- end
1266
-
1267
- it "should return number array return value" do
1268
- expect(plsql.test_increment([1, 2, 3, 4], 1)).to eq([2, 3, 4, 5])
1269
- end
1270
-
1271
- it "should execute function with string array and return string array output parameter" do
1272
- strings = ["1", "2", "3", "4"]
1273
- expect(plsql.test_copy_strings(strings)).to eq([strings, { x_strings: strings }])
1274
- end
1275
-
1276
- it "should execute function with table of numbers type (defined inside package) parameter" do
1277
- expect(plsql.test_collections.test_sum([1, 2, 3, 4])).to eq(10)
1278
- end
1279
-
1280
- it "should clear temporary tables after executing function with table of numbers type even if an error occurs in the package" do
1281
- # this should work fine
1282
- expect(plsql.test_collections.test_function_failure([1, 2, 3, 4], "N")).to eq(4)
1283
- # we will force a package error here to see if things get cleaned up before the next call
1284
- expect { plsql.test_collections.test_function_failure([1, 2, 3, 4], "Y") }.to raise_error(/Simulate business error to test clearing of temp table/)
1285
- # after the error in the first call temporary tables should be cleared
1286
- expect(plsql.test_collections.test_function_failure([5, 6, 7], "N")).to eq(3)
1287
- end
1288
-
1289
- it "should return table of numbers type (defined inside package)" do
1290
- expect(plsql.test_collections.test_numbers([1, 2, 3, 4])).to eq([[1, 2, 3, 4], { x_numbers: [1, 2, 3, 4] }])
1291
- end
1292
-
1293
- it "should clear temporary tables after executing function with table of numbers type (defined inside package) parameter" do
1294
- expect(plsql.test_collections.test_numbers([1, 2, 3, 4])).to eq([[1, 2, 3, 4], { x_numbers: [1, 2, 3, 4] }])
1295
- # after first call temporary tables should be cleared
1296
- expect(plsql.test_collections.test_numbers([1, 2, 3, 4])).to eq([[1, 2, 3, 4], { x_numbers: [1, 2, 3, 4] }])
1297
- end
1298
-
1299
- it "should clear temporary tables when autocommit with table of numbers type (defined inside package) parameter" do
1300
- old_autocommit = plsql.connection.autocommit?
1301
- plsql.connection.autocommit = true
1302
- numbers_array = (1..400).to_a
1303
- expect(plsql.test_collections.test_numbers(numbers_array)).to eq([numbers_array, { x_numbers: numbers_array }])
1304
- # after first call temporary tables should be cleared
1305
- expect(plsql.test_collections.test_numbers(numbers_array)).to eq([numbers_array, { x_numbers: numbers_array }])
1306
- plsql.connection.autocommit = old_autocommit
1307
- end
1308
-
1309
- it "should execute function with table of records type (defined inside package) parameter" do
1310
- expect(plsql.test_collections.test_employees(@employees)).to eq([@employees, { p_employees: @employees }])
1311
- end
1312
-
1313
- it "should execute function with table of records type (defined inside package and includes NVARCHAR columns) parameter" do
1314
- expect(plsql.test_collections.test_nstring(@nstrings)).to eq([(1..5).map { |i| "NCh #{i}NStr #{i}," }.join, { p_out: @nstrings }])
1315
- end
1316
-
1317
- it "should execute function with object array and return object array output parameter" do
1318
- phones = [{ type: "mobile", phone_number: "123456" }, { type: "home", phone_number: "654321" }]
1319
- expect(plsql.test_copy_objects(phones)).to eq([phones, { x_phones: phones }])
1320
- end
1321
-
1322
- it "should execute function with empty object array" do
1323
- phones = []
1324
- expect(plsql.test_copy_objects(phones)).to eq([phones, { x_phones: phones }])
1325
- end
1326
-
1327
- it "should raise error with record parameter that has table as element" do
1328
- expect {
1329
- expect(plsql.test_collections.test_employee2(@employees[0])).to eq([@employees[0], { p_employee: @employees[0] }])
1330
- }.to raise_error(ArgumentError, /TEST_COLLECTIONS\.T_NUMBERS definition inside package is not supported/)
1331
- end
1332
-
1333
- it "should raise error with table of records parameter when record has table as element" do
1334
- expect {
1335
- expect(plsql.test_collections.test_employees2(@employees)).to eq([@employees, { p_employees: @employees }])
1336
- }.to raise_error(ArgumentError, /TEST_COLLECTIONS\.T_NUMBERS definition inside package is not supported/)
1337
- end
1338
-
1339
- end
1340
-
1341
- describe "Function with table indexed by bynary integer parameter" do
1342
- before(:all) do
1343
- plsql.connect! CONNECTION_PARAMS
1344
- plsql.execute <<-SQL
1345
- CREATE TABLE test_employees (
1346
- employee_id NUMBER(15),
1347
- first_name VARCHAR2(50),
1348
- last_name VARCHAR(50),
1349
- hire_date DATE
1350
- )
1351
- SQL
1352
- # Type definition inside package
1353
- plsql.execute <<-SQL
1354
- CREATE OR REPLACE PACKAGE test_collections IS
1355
- TYPE t_numbers IS TABLE OF NUMBER(15)
1356
- INDEX BY BINARY_INTEGER;
1357
- FUNCTION test_sum (p_numbers IN t_numbers)
1358
- RETURN NUMBER;
1359
- FUNCTION test_function_failure (p_numbers IN t_numbers, p_force_failure IN VARCHAR2 DEFAULT 'N')
1360
- RETURN NUMBER;
1361
- FUNCTION test_numbers (p_numbers IN t_numbers, x_numbers OUT t_numbers)
1362
- RETURN t_numbers;
1363
- TYPE t_employee IS RECORD(
1364
- employee_id NUMBER(15),
1365
- first_name VARCHAR2(50),
1366
- last_name VARCHAR(50),
1367
- hire_date DATE
1368
- );
1369
- TYPE t_employees IS TABLE OF test_collections.t_employee
1370
- INDEX BY BINARY_INTEGER;
1371
- FUNCTION test_employees (p_employees IN OUT t_employees)
1372
- RETURN t_employees;
1373
- PROCEDURE test_employees_prc (p_employees IN OUT t_employees);
1374
- PROCEDURE insert_employees(p_employees IN t_employees);
1375
- END;
1376
- SQL
1377
- plsql.execute <<-SQL
1378
- CREATE OR REPLACE PACKAGE BODY test_collections IS
1379
- FUNCTION test_sum (p_numbers IN t_numbers)
1380
- RETURN NUMBER
1381
- IS
1382
- l_sum NUMBER(15) := 0;
1383
- i BINARY_INTEGER;
1384
- BEGIN
1385
- IF p_numbers.COUNT > 0 THEN
1386
- i := p_numbers.FIRST;
1387
- LOOP
1388
- EXIT WHEN i IS NULL;
1389
- l_sum := l_sum + p_numbers(i);
1390
- i := p_numbers.NEXT(i);
1391
- END LOOP;
1392
- RETURN l_sum;
1393
- ELSE
1394
- RETURN NULL;
1395
- END IF;
1396
- END;
1397
- FUNCTION test_function_failure (p_numbers IN t_numbers, p_force_failure IN VARCHAR2 DEFAULT 'N')
1398
- RETURN NUMBER
1399
- IS
1400
- l_sum NUMBER(15) := 0;
1401
- i BINARY_INTEGER;
1402
- BEGIN
1403
- IF p_force_failure = 'Y' THEN
1404
- raise_application_error(-20000, 'Simulate business error to test clearing of temp table.');
1405
- END IF;
1406
- IF p_numbers.COUNT > 0 THEN
1407
- i := p_numbers.FIRST;
1408
- LOOP
1409
- EXIT WHEN i IS NULL;
1410
- l_sum := l_sum + p_numbers(i);
1411
- i := p_numbers.NEXT(i);
1412
- END LOOP;
1413
- RETURN l_sum;
1414
- ELSE
1415
- RETURN NULL;
1416
- END IF;
1417
- END;
1418
- FUNCTION test_numbers (p_numbers IN t_numbers, x_numbers OUT t_numbers)
1419
- RETURN t_numbers
1420
- IS
1421
- BEGIN
1422
- x_numbers := p_numbers;
1423
- RETURN p_numbers;
1424
- END;
1425
- FUNCTION test_employees (p_employees IN OUT t_employees)
1426
- RETURN t_employees
1427
- IS
1428
- BEGIN
1429
- RETURN p_employees;
1430
- END;
1431
- PROCEDURE test_employees_prc (p_employees IN OUT t_employees)
1432
- IS
1433
- BEGIN
1434
- NULL;
1435
- END;
1436
- PROCEDURE insert_employees(p_employees IN t_employees) IS
1437
- BEGIN
1438
- FORALL i IN p_employees.FIRST..p_employees.LAST
1439
- INSERT INTO test_employees VALUES p_employees(i);
1440
- END;
1441
- END;
1442
- SQL
1443
- # test with negative PL/SQL table indexes
1444
- @numbers = Hash[*(1..4).map { |i|[-i, i] }.flatten]
1445
- @numbers2 = Hash[*(5..7).map { |i|[-i, i] }.flatten]
1446
- # test with reversed PL/SQL table indexes
1447
- @employees = Hash[*(1..10).map do |i|
1448
- [11 - i, {
1449
- employee_id: i,
1450
- first_name: "First #{i}",
1451
- last_name: "Last #{i}",
1452
- hire_date: Time.local(2000, 01, i)
1453
- }]
1454
- end.flatten]
1455
- end
1456
-
1457
- after(:all) do
1458
- plsql.execute "DROP PACKAGE test_collections"
1459
- plsql.execute "DROP TABLE test_employees"
1460
- plsql.connection.drop_session_ruby_temporary_tables
1461
- plsql.logoff
1462
- end
1463
-
1464
- it "should clear temporary tables after executing function with index-by table of numbers type even if an error occurs in the package" do
1465
- # this should work fine
1466
- expect(plsql.test_collections.test_function_failure(@numbers, "N")).to eq(10)
1467
- # we will force a package error here to see if things get cleaned up before the next call
1468
- expect { plsql.test_collections.test_function_failure(@numbers, "Y") }.to raise_error(/Simulate business error to test clearing of temp table/)
1469
- # after the error in the first call temporary tables should be cleared
1470
- expect(plsql.test_collections.test_function_failure(@numbers2, "N")).to eq(18)
1471
- end
1472
-
1473
- it "should execute function with index-by table of numbers type (defined inside package) parameter" do
1474
- expect(plsql.test_collections.test_sum(@numbers)).to eq(10)
1475
- end
1476
-
1477
- it "should return index-by table of numbers type (defined inside package)" do
1478
- expect(plsql.test_collections.test_numbers(@numbers)).to eq([@numbers, { x_numbers: @numbers }])
1479
- end
1480
-
1481
- it "should clear temporary tables when autocommit with index-by table of numbers type (defined inside package) parameter" do
1482
- old_autocommit = plsql.connection.autocommit?
1483
- plsql.connection.autocommit = true
1484
- numbers_hash = Hash[*(1..400).map { |i|[i, i] }.flatten]
1485
- expect(plsql.test_collections.test_numbers(numbers_hash)).to eq([numbers_hash, { x_numbers: numbers_hash }])
1486
- # after first call temporary tables should be cleared
1487
- expect(plsql.test_collections.test_numbers(numbers_hash)).to eq([numbers_hash, { x_numbers: numbers_hash }])
1488
- plsql.connection.autocommit = old_autocommit
1489
- end
1490
-
1491
- it "should execute function with index-by table of records type (defined inside package) parameter" do
1492
- expect(plsql.test_collections.test_employees(@employees)).to eq([@employees, { p_employees: @employees }])
1493
- end
1494
-
1495
- it "should execute procedure with index-by table of records type (defined inside package) parameter" do
1496
- expect(plsql.test_collections.test_employees_prc(@employees)).to eq(p_employees: @employees)
1497
- end
1498
-
1499
- it "should create temporary tables in autonomous transaction" do
1500
- old_autocommit = plsql.connection.autocommit?
1501
- plsql.connection.autocommit = false
1502
- plsql.test_employees.insert @employees[1]
1503
- # procedure call should not commit initial insert
1504
- plsql.test_collections.insert_employees(2 => @employees[2], 3 => @employees[3])
1505
- plsql.rollback
1506
- expect(plsql.test_employees.all).to be_empty
1507
- plsql.connection.autocommit = old_autocommit
1508
- end
1509
-
1510
- describe "using Oracle 9.2" do
1511
- before(:all) do
1512
- # get actual database_version
1513
- plsql.connect! CONNECTION_PARAMS
1514
- skip "Skip if the actual database version is 18c or higher" if (plsql.connection.database_version <=> [18, 0, 0, 0]) >= 0
1515
- end
1516
-
1517
- before do
1518
- # simulate Oracle 9.2 connection
1519
- plsql(:oracle_9).connection = get_connection
1520
- allow(plsql(:oracle_9).connection).to receive(:database_version).and_return([9, 2, 0, 0])
1521
- end
1522
-
1523
- after do
1524
- plsql(:oracle_9).logoff
1525
- end
1526
-
1527
- it "should create temporary tables when using Oracle 9.2" do
1528
- expect(plsql(:oracle_9).test_collections.test_numbers(@numbers)).to eq([@numbers, { x_numbers: @numbers }])
1529
- end
1530
-
1531
- end
1532
-
1533
- end
1534
-
1535
- describe "Function with VARRAY parameter" do
1536
- before(:all) do
1537
- plsql.connect! CONNECTION_PARAMS
1538
- # Array of numbers
1539
- plsql.execute <<-SQL
1540
- CREATE OR REPLACE TYPE t_numbers_array AS VARRAY(100) OF NUMBER(15)
1541
- SQL
1542
- plsql.execute <<-SQL
1543
- CREATE OR REPLACE FUNCTION test_sum (p_numbers IN t_numbers_array)
1544
- RETURN NUMBER
1545
- IS
1546
- l_sum NUMBER(15) := 0;
1547
- BEGIN
1548
- IF p_numbers.COUNT > 0 THEN
1549
- FOR i IN p_numbers.FIRST..p_numbers.LAST LOOP
1550
- l_sum := l_sum + p_numbers(i);
1551
- END LOOP;
1552
- RETURN l_sum;
1553
- ELSE
1554
- RETURN NULL;
1555
- END IF;
1556
- END;
1557
- SQL
1558
-
1559
- plsql.execute <<-SQL
1560
- CREATE OR REPLACE FUNCTION test_increment(p_numbers IN t_numbers_array, p_increment_by IN NUMBER DEFAULT 1)
1561
- RETURN t_numbers_array
1562
- IS
1563
- l_numbers t_numbers_array := t_numbers_array();
1564
- BEGIN
1565
- FOR i IN p_numbers.FIRST..p_numbers.LAST LOOP
1566
- l_numbers.EXTEND;
1567
- l_numbers(i) := p_numbers(i) + p_increment_by;
1568
- END LOOP;
1569
- RETURN l_numbers;
1570
- END;
1571
- SQL
1572
-
1573
- # Array of strings
1574
- plsql.execute <<-SQL
1575
- CREATE OR REPLACE TYPE t_strings_array AS VARRAY(100) OF VARCHAR2(4000)
1576
- SQL
1577
- plsql.execute <<-SQL
1578
- CREATE OR REPLACE FUNCTION test_copy_strings(p_strings IN t_strings_array, x_strings OUT t_strings_array)
1579
- RETURN t_strings_array
1580
- IS
1581
- BEGIN
1582
- x_strings := t_strings_array();
1583
- FOR i IN p_strings.FIRST..p_strings.LAST LOOP
1584
- x_strings.EXTEND;
1585
- x_strings(i) := p_strings(i);
1586
- END LOOP;
1587
- RETURN x_strings;
1588
- END;
1589
- SQL
1590
-
1591
- # Array of objects
1592
- plsql.execute "DROP TYPE t_phones_array" rescue nil
1593
- plsql.execute <<-SQL
1594
- CREATE OR REPLACE TYPE t_phone AS OBJECT (
1595
- type VARCHAR2(10),
1596
- phone_number VARCHAR2(50)
1597
- )
1598
- SQL
1599
- plsql.execute <<-SQL
1600
- CREATE OR REPLACE TYPE t_phones_array AS ARRAY(100) OF T_PHONE
1601
- SQL
1602
- plsql.execute <<-SQL
1603
- CREATE OR REPLACE FUNCTION test_copy_objects(p_phones IN t_phones_array, x_phones OUT t_phones_array)
1604
- RETURN t_phones_array
1605
- IS
1606
- BEGIN
1607
- x_phones := p_phones;
1608
- RETURN x_phones;
1609
- END;
1610
- SQL
1611
- end
1612
-
1613
- after(:all) do
1614
- plsql.execute "DROP FUNCTION test_sum"
1615
- plsql.execute "DROP FUNCTION test_increment"
1616
- plsql.execute "DROP FUNCTION test_copy_strings"
1617
- plsql.execute "DROP FUNCTION test_copy_objects"
1618
- plsql.execute "DROP TYPE t_numbers_array"
1619
- plsql.execute "DROP TYPE t_strings_array"
1620
- plsql.execute "DROP TYPE t_phones_array"
1621
- plsql.execute "DROP TYPE t_phone"
1622
- plsql.logoff
1623
- end
1624
-
1625
- it "should find existing function" do
1626
- expect(PLSQL::Procedure.find(plsql, :test_sum)).not_to be_nil
1627
- end
1628
-
1629
- it "should execute function with number array parameter" do
1630
- expect(plsql.test_sum([1, 2, 3, 4])).to eq(10)
1631
- end
1632
-
1633
- it "should return number array return value" do
1634
- expect(plsql.test_increment([1, 2, 3, 4], 1)).to eq([2, 3, 4, 5])
1635
- end
1636
-
1637
- it "should execute function with string array and return string array output parameter" do
1638
- strings = ["1", "2", "3", "4"]
1639
- expect(plsql.test_copy_strings(strings)).to eq([strings, { x_strings: strings }])
1640
- end
1641
-
1642
- it "should execute function with object array and return object array output parameter" do
1643
- phones = [{ type: "mobile", phone_number: "123456" }, { type: "home", phone_number: "654321" }]
1644
- expect(plsql.test_copy_objects(phones)).to eq([phones, { x_phones: phones }])
1645
- end
1646
-
1647
- it "should execute function with empty object array" do
1648
- phones = []
1649
- expect(plsql.test_copy_objects(phones)).to eq([phones, { x_phones: phones }])
1650
- end
1651
-
1652
- end
1653
-
1654
- describe "Function in package with VARRAY parameter" do
1655
- before(:all) do
1656
- plsql.connect! CONNECTION_PARAMS
1657
- plsql.execute <<-SQL
1658
- CREATE OR REPLACE TYPE t_phone AS OBJECT (
1659
- type VARCHAR2(10),
1660
- phone_number VARCHAR2(50)
1661
- )
1662
- SQL
1663
-
1664
- plsql.execute <<-SQL
1665
- CREATE OR REPLACE PACKAGE test_collections IS
1666
- TYPE t_numbers_array IS VARRAY(100) OF NUMBER(15);
1667
- TYPE t_strings_array IS VARRAY(100) OF VARCHAR2(4000);
1668
- TYPE t_phones_array IS ARRAY(100) OF T_PHONE;
1669
- FUNCTION test_sum (p_numbers IN t_numbers_array)
1670
- RETURN NUMBER;
1671
- FUNCTION test_function_failure (p_numbers IN t_numbers_array, p_force_failure IN VARCHAR2 DEFAULT 'N')
1672
- RETURN NUMBER;
1673
- FUNCTION test_increment(p_numbers IN t_numbers_array, p_increment_by IN NUMBER DEFAULT 1)
1674
- RETURN t_numbers_array;
1675
- FUNCTION test_copy_strings(p_strings IN t_strings_array, x_strings OUT t_strings_array)
1676
- RETURN t_strings_array;
1677
- FUNCTION test_copy_objects(p_phones IN t_phones_array, x_phones OUT t_phones_array)
1678
- RETURN t_phones_array;
1679
- END;
1680
- SQL
1681
-
1682
- plsql.execute <<-SQL
1683
- CREATE OR REPLACE PACKAGE BODY test_collections IS
1684
- FUNCTION test_sum (p_numbers IN t_numbers_array)
1685
- RETURN NUMBER
1686
- IS
1687
- l_sum NUMBER(15) := 0;
1688
- BEGIN
1689
- IF p_numbers.COUNT > 0 THEN
1690
- FOR i IN p_numbers.FIRST..p_numbers.LAST LOOP
1691
- l_sum := l_sum + p_numbers(i);
1692
- END LOOP;
1693
- RETURN l_sum;
1694
- ELSE
1695
- RETURN NULL;
1696
- END IF;
1697
- END;
1698
-
1699
- FUNCTION test_function_failure (p_numbers IN t_numbers_array, p_force_failure IN VARCHAR2 DEFAULT 'N')
1700
- RETURN NUMBER
1701
- IS
1702
- l_sum NUMBER(15) := 0;
1703
- BEGIN
1704
- IF p_force_failure = 'Y' THEN
1705
- raise_application_error(-20000, 'Simulate business error to test clearing of temp table.');
1706
- END IF;
1707
- IF p_numbers.COUNT > 0 THEN
1708
- FOR i IN p_numbers.FIRST..p_numbers.LAST LOOP
1709
- l_sum := l_sum + p_numbers(i);
1710
- END LOOP;
1711
- RETURN l_sum;
1712
- ELSE
1713
- RETURN NULL;
1714
- END IF;
1715
- END;
1716
-
1717
- FUNCTION test_increment(p_numbers IN t_numbers_array, p_increment_by IN NUMBER DEFAULT 1)
1718
- RETURN t_numbers_array
1719
- IS
1720
- l_numbers t_numbers_array := t_numbers_array();
1721
- BEGIN
1722
- FOR i IN p_numbers.FIRST..p_numbers.LAST LOOP
1723
- l_numbers.EXTEND;
1724
- l_numbers(i) := p_numbers(i) + p_increment_by;
1725
- END LOOP;
1726
- RETURN l_numbers;
1727
- END;
1728
-
1729
- FUNCTION test_copy_strings(p_strings IN t_strings_array, x_strings OUT t_strings_array)
1730
- RETURN t_strings_array
1731
- IS
1732
- BEGIN
1733
- x_strings := t_strings_array();
1734
- FOR i IN p_strings.FIRST..p_strings.LAST LOOP
1735
- x_strings.EXTEND;
1736
- x_strings(i) := p_strings(i);
1737
- END LOOP;
1738
- RETURN x_strings;
1739
- END;
1740
-
1741
- FUNCTION test_copy_objects(p_phones IN t_phones_array, x_phones OUT t_phones_array)
1742
- RETURN t_phones_array
1743
- IS
1744
- BEGIN
1745
- x_phones := p_phones;
1746
- RETURN x_phones;
1747
- END;
1748
- END;
1749
- SQL
1750
- end
1751
-
1752
- after(:all) do
1753
- plsql.execute "DROP PACKAGE test_collections"
1754
- plsql.execute "DROP TYPE t_phone" rescue nil
1755
- plsql.logoff
1756
- end
1757
-
1758
- it "should execute function with number array parameter" do
1759
- expect(plsql.test_collections.test_sum([1, 2, 3, 4])).to eq(10)
1760
- end
1761
-
1762
- it "should clear temporary tables after executing function with varray of numbers type even if an error occurs in the package" do
1763
- # this should work fine
1764
- expect(plsql.test_collections.test_function_failure([1, 2, 3, 4], "N")).to eq(10)
1765
- # we will force a package error here to see if things get cleaned up before the next call
1766
- expect { plsql.test_collections.test_function_failure([5, 6, 7], "Y") }.to raise_error(/Simulate business error to test clearing of temp table/)
1767
- # after the error in the first call temporary tables should be cleared
1768
- expect(plsql.test_collections.test_function_failure([3, 4, 5, 6], "N")).to eq(18)
1769
- end
1770
-
1771
- it "should return number array return value" do
1772
- expect(plsql.test_collections.test_increment([1, 2, 3, 4], 1)).to eq([2, 3, 4, 5])
1773
- end
1774
-
1775
- it "should execute function with string array and return string array output parameter" do
1776
- strings = ["1", "2", "3", "4"]
1777
- expect(plsql.test_collections.test_copy_strings(strings)).to eq([strings, { x_strings: strings }])
1778
- end
1779
-
1780
- it "should execute function with object array and return object array output parameter" do
1781
- phones = [{ type: "mobile", phone_number: "123456" }, { type: "home", phone_number: "654321" }]
1782
- expect(plsql.test_collections.test_copy_objects(phones)).to eq([phones, { x_phones: phones }])
1783
- end
1784
-
1785
- # This test fails without wcmatthysen's "Procedure-call Fix." pull request.
1786
- # it "should execute function with empty object array" do
1787
- # phones = []
1788
- # plsql.test_collections.test_copy_objects(phones).should == [phones, {:x_phones => phones}]
1789
- # end
1790
-
1791
- end
1792
-
1793
- describe "Function with cursor return value or parameter" do
1794
- before(:all) do
1795
- plsql.connect! CONNECTION_PARAMS
1796
- plsql.execute "DROP TABLE test_employees" rescue nil
1797
- plsql.execute <<-SQL
1798
- CREATE TABLE test_employees (
1799
- employee_id NUMBER(15),
1800
- first_name VARCHAR2(50),
1801
- last_name VARCHAR(50),
1802
- hire_date DATE
1803
- )
1804
- SQL
1805
- plsql.execute <<-SQL
1806
- CREATE OR REPLACE PROCEDURE test_insert_employee(p_employee test_employees%ROWTYPE)
1807
- IS
1808
- BEGIN
1809
- INSERT INTO test_employees
1810
- VALUES p_employee;
1811
- END;
1812
- SQL
1813
- plsql.execute <<-SQL
1814
- CREATE OR REPLACE FUNCTION test_cursor
1815
- RETURN SYS_REFCURSOR
1816
- IS
1817
- l_cursor SYS_REFCURSOR;
1818
- BEGIN
1819
- OPEN l_cursor FOR
1820
- SELECT * FROM test_employees ORDER BY employee_id;
1821
- RETURN l_cursor;
1822
- END;
1823
- SQL
1824
- plsql.execute <<-SQL
1825
- CREATE OR REPLACE PROCEDURE test_cursor_out(x_cursor OUT SYS_REFCURSOR)
1826
- IS
1827
- BEGIN
1828
- OPEN x_cursor FOR
1829
- SELECT * FROM test_employees ORDER BY employee_id;
1830
- END;
1831
- SQL
1832
- plsql.execute <<-SQL
1833
- CREATE OR REPLACE FUNCTION test_cursor_fetch(p_cursor SYS_REFCURSOR)
1834
- RETURN test_employees%ROWTYPE
1835
- IS
1836
- l_record test_employees%ROWTYPE;
1837
- BEGIN
1838
- FETCH p_cursor INTO l_record;
1839
- RETURN l_record;
1840
- END;
1841
- SQL
1842
- @fields = [:employee_id, :first_name, :last_name, :hire_date]
1843
- @employees = (1..10).map do |i|
1844
- {
1845
- employee_id: i,
1846
- first_name: "First #{i}",
1847
- last_name: "Last #{i}",
1848
- hire_date: Time.local(2000, 01, i)
1849
- }
1850
- end
1851
- @employees.each do |e|
1852
- plsql.test_insert_employee(e)
1853
- end
1854
- plsql.connection.commit
1855
- end
1856
-
1857
- after(:all) do
1858
- plsql.execute "DROP FUNCTION test_cursor"
1859
- plsql.execute "DROP PROCEDURE test_cursor_out"
1860
- plsql.execute "DROP PROCEDURE test_insert_employee"
1861
- plsql.execute "DROP FUNCTION test_cursor_fetch"
1862
- plsql.execute "DROP TABLE test_employees"
1863
- plsql.logoff
1864
- end
1865
-
1866
- it "should find existing function" do
1867
- expect(PLSQL::Procedure.find(plsql, :test_cursor)).not_to be_nil
1868
- end
1869
-
1870
- it "should return cursor and fetch first row" do
1871
- expect(plsql.test_cursor do |cursor|
1872
- expect(cursor.fetch).to eq(@fields.map { |f| @employees[0][f] })
1873
- end).to be_nil
1874
- end
1875
-
1876
- it "should close all returned cursors after block is executed" do
1877
- cursor2 = nil
1878
- expect(plsql.test_cursor do |cursor|
1879
- cursor2 = cursor
1880
- end).to be_nil
1881
- expect { cursor2.fetch }.to raise_error(/Cursor was already closed|Closed Statement/)
1882
- end
1883
-
1884
- it "should not raise error if cursor is closed inside block" do
1885
- expect do
1886
- plsql.test_cursor do |cursor|
1887
- cursor.close
1888
- end
1889
- end.not_to raise_error
1890
- end
1891
-
1892
- it "should fetch hash from returned cursor" do
1893
- plsql.test_cursor do |cursor|
1894
- expect(cursor.fetch_hash).to eq(@employees[0])
1895
- end
1896
- end
1897
-
1898
- it "should fetch all rows from returned cursor" do
1899
- plsql.test_cursor do |cursor|
1900
- expect(cursor.fetch_all).to eq(@employees.map { |e| @fields.map { |f| e[f] } })
1901
- end
1902
- end
1903
-
1904
- it "should fetch all rows as hash from returned cursor" do
1905
- plsql.test_cursor do |cursor|
1906
- expect(cursor.fetch_hash_all).to eq(@employees)
1907
- end
1908
- end
1909
-
1910
- it "should get field names from returned cursor" do
1911
- plsql.test_cursor do |cursor|
1912
- expect(cursor.fields).to eq(@fields)
1913
- end
1914
- end
1915
-
1916
- it "should return output parameter with cursor and fetch first row" do
1917
- expect(plsql.test_cursor_out do |result|
1918
- expect(result[:x_cursor].fetch).to eq(@fields.map { |f| @employees[0][f] })
1919
- end).to be_nil
1920
- end
1921
-
1922
- it "should return output parameter with cursor and fetch all rows as hash" do
1923
- expect(plsql.test_cursor_out do |result|
1924
- expect(result[:x_cursor].fetch_hash_all).to eq(@employees)
1925
- end).to be_nil
1926
- end
1927
-
1928
- it "should execute function with cursor parameter and return record" do
1929
- skip "not possible from JDBC" if defined?(JRUBY_VERSION)
1930
- plsql.test_cursor do |cursor|
1931
- expect(plsql.test_cursor_fetch(cursor)).to eq(@employees[0])
1932
- end
1933
- end
1934
-
1935
- end
1936
-
1937
- describe "Function with typed ref cursor return value" do
1938
- before(:all) do
1939
- plsql.connect! CONNECTION_PARAMS
1940
- plsql.execute "DROP TABLE typed_ref_cursor_table" rescue nil
1941
-
1942
- plsql.execute <<-SQL
1943
- CREATE TABLE typed_ref_cursor_table
1944
- ( col1 VARCHAR2(10), col2 NUMBER )
1945
- SQL
1946
-
1947
- plsql.execute <<-SQL
1948
- CREATE OR REPLACE PACKAGE typed_ref_cursor_test IS
1949
- TYPE test_rec IS RECORD ( col1 VARCHAR2(10), col2 NUMBER ) ;
1950
- TYPE test_rec_ref IS REF CURSOR RETURN test_rec ;
1951
-
1952
- function get_all RETURN test_rec_ref ;
1953
- END typed_ref_cursor_test ;
1954
- SQL
1955
-
1956
- plsql.execute <<-SQL
1957
- CREATE OR REPLACE PACKAGE BODY typed_ref_cursor_test IS
1958
- FUNCTION get_all RETURN test_rec_ref IS
1959
- rc test_rec_ref ;
1960
- BEGIN
1961
- OPEN rc FOR SELECT * FROM typed_ref_cursor_table ;
1962
- RETURN rc ;
1963
- END get_all ;
1964
- END typed_ref_cursor_test ;
1965
- SQL
1966
-
1967
- @fields = [:col1, :col2 ]
1968
- @rows = (1..3).map { |i| ["row #{i}", i] }
1969
- plsql.typed_ref_cursor_table.insert_values *@rows
1970
- plsql.commit
1971
-
1972
- end
1973
-
1974
- after(:all) do
1975
- plsql.execute "DROP PACKAGE typed_ref_cursor_test"
1976
- plsql.execute "DROP TABLE typed_ref_cursor_table"
1977
- plsql.logoff
1978
- end
1979
-
1980
- it "should return cursor and fetch first row" do
1981
- expect(plsql.typed_ref_cursor_test.get_all do |cursor|
1982
- expect(cursor.fetch).to eq(@rows[0])
1983
- end).to be_nil
1984
- end
1985
-
1986
- it "should fetch hash from returned cursor" do
1987
- plsql.typed_ref_cursor_test.get_all do |cursor|
1988
- expect(cursor.fetch_hash).to eq(Hash[*@fields.zip(@rows[0]).flatten])
1989
- end
1990
- end
1991
-
1992
- it "should fetch all rows from returned cursor" do
1993
- plsql.typed_ref_cursor_test.get_all do |cursor|
1994
- expect(cursor.fetch_all).to eq(@rows)
1995
- end
1996
- end
1997
-
1998
- end
1999
-
2000
- end
2001
-
2002
- describe "Synonyms /" do
2003
- before(:all) do
2004
- plsql.connect! CONNECTION_PARAMS
2005
- end
2006
-
2007
- after(:all) do
2008
- plsql.logoff
2009
- end
2010
-
2011
- describe "Local synonym to function" do
2012
-
2013
- before(:all) do
2014
- plsql.execute <<-SQL
2015
- CREATE OR REPLACE FUNCTION hr.test_uppercase
2016
- ( p_string VARCHAR2 )
2017
- RETURN VARCHAR2
2018
- IS
2019
- BEGIN
2020
- RETURN UPPER(p_string);
2021
- END test_uppercase;
2022
- SQL
2023
- plsql.execute "CREATE SYNONYM test_synonym FOR hr.test_uppercase"
2024
- end
2025
-
2026
- after(:all) do
2027
- plsql.execute "DROP SYNONYM test_synonym"
2028
- plsql.execute "DROP FUNCTION hr.test_uppercase"
2029
- end
2030
-
2031
- it "should find synonym to function" do
2032
- expect(PLSQL::Procedure.find(plsql, :test_synonym)).not_to be_nil
2033
- end
2034
-
2035
- it "should execute function using synonym and return correct value" do
2036
- expect(plsql.test_synonym("xxx")).to eq("XXX")
2037
- end
2038
-
2039
- end
2040
-
2041
- describe "Public synonym to function" do
2042
-
2043
- before(:all) do
2044
- plsql.execute <<-SQL
2045
- CREATE OR REPLACE FUNCTION hr.test_ora_login_user
2046
- RETURN VARCHAR2
2047
- IS
2048
- BEGIN
2049
- RETURN 'XXX';
2050
- END test_ora_login_user;
2051
- SQL
2052
- end
2053
-
2054
- after(:all) do
2055
- plsql.execute "DROP FUNCTION hr.test_ora_login_user"
2056
- end
2057
-
2058
- it "should find public synonym to function" do
2059
- expect(PLSQL::Procedure.find(plsql, :ora_login_user)).not_to be_nil
2060
- end
2061
-
2062
- it "should execute function using public synonym and return correct value" do
2063
- expect(plsql.ora_login_user).to eq("HR")
2064
- end
2065
-
2066
- it "should not find public synonym if schema prefix is used" do
2067
- expect { plsql.hr.ora_login_user }.to raise_error(ArgumentError)
2068
- end
2069
-
2070
- it "should find private synonym before public synonym" do
2071
- # should reconnect to force clearing of procedure cache
2072
- plsql.connection = get_connection
2073
- plsql.execute "DROP SYNONYM ora_login_user" rescue nil
2074
- plsql.execute "CREATE SYNONYM ora_login_user FOR hr.test_ora_login_user"
2075
- expect(plsql.ora_login_user).to eq("XXX")
2076
- plsql.execute "DROP SYNONYM ora_login_user"
2077
- plsql.connection = get_connection
2078
- expect(plsql.ora_login_user).to eq("HR")
2079
- end
2080
-
2081
- end
2082
-
2083
- describe "invalid objects" do
2084
- before(:all) do
2085
- plsql.execute <<-SQL
2086
- CREATE OR REPLACE FUNCTION test_invalid_function(p_dummy VARCHAR2) RETURN VARCHAR2 IS
2087
- l_dummy invalid_table.invalid_column%TYPE;
2088
- BEGIN
2089
- RETURN p_dummy;
2090
- END;
2091
- SQL
2092
- plsql.execute <<-SQL
2093
- CREATE OR REPLACE PACKAGE test_invalid_package IS
2094
- FUNCTION test_invalid_function(p_dummy VARCHAR2) RETURN VARCHAR2;
2095
- END;
2096
- SQL
2097
- plsql.execute <<-SQL
2098
- CREATE OR REPLACE PACKAGE BODY test_invalid_package IS
2099
- FUNCTION test_invalid_function(p_dummy VARCHAR2) RETURN VARCHAR2 IS
2100
- l_dummy1 invalid_table.invalid_column%TYPE;
2101
- l_dummy2 invalid_table.invalid_column%TYPE;
2102
- BEGIN
2103
- RETURN p_dummy;
2104
- END;
2105
- END;
2106
- SQL
2107
- end
2108
-
2109
- after(:all) do
2110
- plsql.execute "DROP FUNCTION test_invalid_function"
2111
- plsql.execute "DROP PACKAGE test_invalid_package"
2112
- end
2113
-
2114
- it "should raise error when invalid function is called" do
2115
- expect {
2116
- plsql.test_invalid_function("test")
2117
- }.to raise_error(ArgumentError, /is not in valid status/)
2118
- end
2119
-
2120
- it "should raise error when function from invalid package body is called" do
2121
- expect {
2122
- plsql.test_invalid_package.test_invalid_function("test")
2123
- }.to raise_error(oracle_error_class, /ORA-04063/)
2124
- end
2125
- end
2126
-
2127
- describe "invalid objects that can be automatically recompiled" do
2128
- before(:all) do
2129
- plsql.execute "DROP TABLE test_recompilable_table" rescue nil
2130
- plsql.execute "CREATE TABLE test_recompilable_table (dummy VARCHAR2(10))"
2131
- plsql.execute <<-SQL
2132
- CREATE OR REPLACE FUNCTION test_recompilable_function(p_dummy VARCHAR2) RETURN VARCHAR2 IS
2133
- l_dummy test_recompilable_table.dummy%TYPE;
2134
- BEGIN
2135
- RETURN p_dummy;
2136
- END;
2137
- SQL
2138
- plsql.execute <<-SQL
2139
- CREATE OR REPLACE PACKAGE test_recompilable_package IS
2140
- FUNCTION test_recompilable_function(p_dummy VARCHAR2) RETURN VARCHAR2;
2141
- END;
2142
- SQL
2143
- plsql.execute <<-SQL
2144
- CREATE OR REPLACE PACKAGE BODY test_recompilable_package IS
2145
- FUNCTION test_recompilable_function(p_dummy VARCHAR2) RETURN VARCHAR2 IS
2146
- l_dummy test_recompilable_table.dummy%TYPE;
2147
- BEGIN
2148
- RETURN p_dummy;
2149
- END;
2150
- END;
2151
- SQL
2152
- end
2153
-
2154
- before(:each) do
2155
- # Cause the dependent function and package to go into INVALID status
2156
- plsql.execute "ALTER TABLE test_recompilable_table MODIFY (dummy VARCHAR2(10))"
2157
- end
2158
-
2159
- after(:all) do
2160
- plsql.execute "DROP TABLE test_recompilable_table"
2161
- plsql.execute "DROP FUNCTION test_recompilable_function"
2162
- plsql.execute "DROP PACKAGE test_recompilable_package"
2163
- end
2164
-
2165
- it "should successfully call invalid function that can be recompiled" do
2166
- expect {
2167
- result = plsql.test_recompilable_function("test")
2168
- expect(result).to eq("test")
2169
- }.not_to raise_error
2170
- end
2171
-
2172
- it "should successfully call invalid package body that can be recompiled" do
2173
- expect {
2174
- result = plsql.test_recompilable_package.test_recompilable_function("test")
2175
- expect(result).to eq("test")
2176
- }.not_to raise_error
2177
- end
2178
- end
2179
-
2180
- end
2181
-
2182
- describe "SYS.STANDARD procedures /" do
2183
-
2184
- before(:all) do
2185
- plsql.connect! CONNECTION_PARAMS
2186
- end
2187
-
2188
- after(:all) do
2189
- plsql.logoff
2190
- end
2191
-
2192
- it "should execute function from SYS.STANDARD package" do
2193
- expect(plsql.upper("abc")).to eq("ABC")
2194
- end
2195
-
2196
- it "should find function overload based on types of sequential arguments" do
2197
- expect(plsql.nvl(1, 2)).to eq(1)
2198
- expect(plsql.nvl(nil, 2)).to eq(2)
2199
- expect(plsql.nvl(1.1, 2.2)).to eq(1.1)
2200
- expect(plsql.nvl(nil, 2.2)).to eq(2.2)
2201
- expect(plsql.nvl(BigDecimal("1.1"), BigDecimal("2.2"))).to eq(BigDecimal("1.1"))
2202
- expect(plsql.nvl(nil, BigDecimal("2.2"))).to eq(BigDecimal("2.2"))
2203
- expect(plsql.nvl("a", "b")).to eq("a")
2204
- expect(plsql.nvl(nil, "b")).to eq("b")
2205
- expect(plsql.nvl(Date.new(2010, 1, 13), Date.new(2010, 1, 19))).to eq(Time.local(2010, 1, 13))
2206
- expect(plsql.nvl(nil, Date.new(2010, 1, 19))).to eq(Time.local(2010, 1, 19))
2207
- expect(plsql.nvl(Time.local(2010, 1, 13), Time.local(2010, 1, 19))).to eq(Time.local(2010, 1, 13))
2208
- expect(plsql.nvl(nil, Time.local(2010, 1, 19))).to eq(Time.local(2010, 1, 19))
2209
- expect(plsql.nvl(true, false)).to eq(true)
2210
- expect(plsql.nvl(nil, false)).to eq(false)
2211
- end
2212
-
2213
- end
2214
-
2215
- describe "PLS_INTEGER/SIMPLE_INTEGER should be nullable" do
2216
-
2217
- before(:all) do
2218
- plsql.connect! CONNECTION_PARAMS
2219
- plsql.execute <<-SQL
2220
- CREATE OR REPLACE FUNCTION test_pls_f ( p_num PLS_INTEGER ) RETURN PLS_INTEGER IS
2221
- BEGIN
2222
- RETURN p_num;
2223
- END;
2224
- SQL
2225
- plsql.execute <<-SQL
2226
- CREATE OR REPLACE FUNCTION test_bin_f ( p_num BINARY_INTEGER ) RETURN BINARY_INTEGER IS
2227
- BEGIN
2228
- RETURN p_num;
2229
- END;
2230
- SQL
2231
- plsql.execute <<-SQL
2232
- CREATE OR REPLACE FUNCTION test_int_f ( p_num INTEGER ) RETURN INTEGER IS
2233
- BEGIN
2234
- RETURN p_num;
2235
- END;
2236
- SQL
2237
- plsql.execute <<-SQL
2238
- CREATE OR REPLACE PROCEDURE test_pls_p ( p_num IN OUT PLS_INTEGER ) IS
2239
- BEGIN
2240
- NULL;
2241
- END;
2242
- SQL
2243
- plsql.execute <<-SQL
2244
- CREATE OR REPLACE PROCEDURE test_bin_p ( p_num IN OUT BINARY_INTEGER ) IS
2245
- BEGIN
2246
- NULL;
2247
- END;
2248
- SQL
2249
- plsql.execute <<-SQL
2250
- CREATE OR REPLACE PROCEDURE test_int_p ( p_num IN OUT INTEGER ) IS
2251
- BEGIN
2252
- NULL;
2253
- END;
2254
- SQL
2255
- plsql.execute <<-SQL
2256
- CREATE OR REPLACE PROCEDURE test_flt_p ( p_num IN OUT BINARY_FLOAT ) IS
2257
- BEGIN
2258
- NULL;
2259
- END;
2260
- SQL
2261
- plsql.execute <<-SQL
2262
- CREATE OR REPLACE PROCEDURE test_dbl_p ( p_num IN OUT BINARY_DOUBLE ) IS
2263
- BEGIN
2264
- NULL;
2265
- END;
2266
- SQL
2267
- end
2268
-
2269
- after(:all) do
2270
- plsql.execute "DROP FUNCTION test_pls_f"
2271
- plsql.execute "DROP FUNCTION test_bin_f"
2272
- plsql.execute "DROP FUNCTION test_int_f"
2273
- plsql.execute "DROP PROCEDURE test_pls_p"
2274
- plsql.execute "DROP PROCEDURE test_int_p"
2275
- plsql.execute "DROP PROCEDURE test_flt_p"
2276
- plsql.execute "DROP PROCEDURE test_dbl_p"
2277
- plsql.logoff
2278
- end
2279
-
2280
- it "should return null for a function call with NULL PLS_INTEGER param" do
2281
- expect(plsql.test_pls_f(nil)).to be_nil
2282
- end
2283
-
2284
- it "should return null for a function call with NULL BINARY_INTEGER param" do
2285
- expect(plsql.test_bin_f(nil)).to be_nil
2286
- end
2287
-
2288
- it "should return null for a function call with NULL INTEGER param" do
2289
- expect(plsql.test_int_f(nil)).to be_nil
2290
- end
2291
-
2292
- it "should return null for a procedure call with NULL PLS_INTEGER param" do
2293
- expect(plsql.test_pls_p(nil)[:p_num]).to be_nil
2294
- end
2295
-
2296
- it "should return null for a procedure call with NULL BINARY_INTEGER param" do
2297
- expect(plsql.test_bin_p(nil)[:p_num]).to be_nil
2298
- end
2299
-
2300
- it "should return null for a procedure call with NULL INTEGER param" do
2301
- expect(plsql.test_int_p(nil)[:p_num]).to be_nil
2302
- end
2303
-
2304
- it "should return null for a procedure call with NULL BINARY_FLOAT param" do
2305
- expect(plsql.test_flt_p(nil)[:p_num]).to be_nil
2306
- end
2307
-
2308
- it "should return null for a procedure call with NULL BINARY_DOUBLE param" do
2309
- expect(plsql.test_dbl_p(nil)[:p_num]).to be_nil
2310
- end
2311
-
2312
- end
2313
-
2314
- describe "#get_argument_metadata" do
2315
- before(:all) do
2316
- plsql.connect! CONNECTION_PARAMS
2317
- end
2318
-
2319
- after(:all) do
2320
- plsql.logoff
2321
- end
2322
-
2323
- before(:each) do
2324
- plsql.execute <<-SQL
2325
- CREATE OR REPLACE FUNCTION magic_number(p_num INTEGER #{defaulted_clause})
2326
- RETURN INTEGER
2327
- IS
2328
- BEGIN
2329
- RETURN p_num * 2;
2330
- END magic_number;
2331
- SQL
2332
- end
2333
-
2334
- after(:each) do
2335
- plsql.execute "DROP FUNCTION magic_number"
2336
- end
2337
-
2338
- context "on procedure with defaulted field" do
2339
- let(:defaulted_clause) { "DEFAULT 21" }
2340
-
2341
- it 'field\'s metadata attribute "defaulted" is Y' do
2342
- procedure = PLSQL::Procedure.find(plsql, :magic_number)
2343
- expect(procedure.arguments[0][:p_num][:defaulted]).to eq("Y")
2344
- end
2345
- end
2346
-
2347
- context "procedure without defaulted field" do
2348
- let(:defaulted_clause) { "" }
2349
-
2350
- it 'field\'s metadata attribute "defaulted" is N' do
2351
- procedure = PLSQL::Procedure.find(plsql, :magic_number)
2352
- expect(procedure.arguments[0][:p_num][:defaulted]).to eq("N")
2353
- end
2354
- end
2355
-
2356
- context "oracle <= 10g without defaulted functionality" do
2357
- let(:defaulted_clause) { "" }
2358
-
2359
- it 'field\'s metadata attribute "defaulted" is nil' do
2360
- allow(plsql.connection).to receive(:database_version).and_return([10, 2, 0, 2])
2361
-
2362
- procedure = PLSQL::Procedure.find(plsql, :magic_number)
2363
- expect(procedure.arguments[0][:p_num][:defaulted]).to be_nil
2364
- end
2365
- end
2366
- end
2367
-
2368
- describe "case-insensitive params" do
2369
- before(:all) do
2370
- plsql.connect! CONNECTION_PARAMS
2371
- plsql.execute <<-SQL
2372
- CREATE OR REPLACE FUNCTION test_func
2373
- ( p_string VARCHAR2 )
2374
- RETURN VARCHAR2
2375
- IS
2376
- BEGIN
2377
- RETURN UPPER(p_string);
2378
- END test_func;
2379
- SQL
2380
- end
2381
-
2382
- after(:all) do
2383
- plsql.execute "DROP FUNCTION test_func"
2384
- plsql.logoff
2385
- end
2386
-
2387
- it "should call procedure/function with case-insensitive param names" do
2388
- expect { plsql.test_func(p_STRING: "xxx") }.not_to raise_error
2389
- end
2390
- end