flash-gordons-ruby-plsql 0.5.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.
- checksums.yaml +15 -0
- data/Gemfile +14 -0
- data/History.txt +172 -0
- data/License.txt +20 -0
- data/README.md +182 -0
- data/Rakefile +47 -0
- data/VERSION +1 -0
- data/lib/plsql/connection.rb +233 -0
- data/lib/plsql/helpers.rb +9 -0
- data/lib/plsql/jdbc_connection.rb +542 -0
- data/lib/plsql/oci8_patches.rb +25 -0
- data/lib/plsql/oci_connection.rb +339 -0
- data/lib/plsql/package.rb +80 -0
- data/lib/plsql/procedure.rb +269 -0
- data/lib/plsql/procedure_call.rb +124 -0
- data/lib/plsql/schema.rb +309 -0
- data/lib/plsql/sequence.rb +49 -0
- data/lib/plsql/sql_statements.rb +87 -0
- data/lib/plsql/table.rb +348 -0
- data/lib/plsql/type.rb +275 -0
- data/lib/plsql/variable.rb +146 -0
- data/lib/plsql/version.rb +3 -0
- data/lib/plsql/view.rb +41 -0
- data/lib/ruby-plsql.rb +1 -0
- data/lib/ruby_plsql.rb +18 -0
- data/ruby-plsql.gemspec +87 -0
- data/spec/plsql/connection_spec.rb +495 -0
- data/spec/plsql/package_spec.rb +149 -0
- data/spec/plsql/procedure_spec.rb +2048 -0
- data/spec/plsql/schema_spec.rb +331 -0
- data/spec/plsql/sequence_spec.rb +67 -0
- data/spec/plsql/sql_statements_spec.rb +91 -0
- data/spec/plsql/table_spec.rb +371 -0
- data/spec/plsql/type_spec.rb +304 -0
- data/spec/plsql/variable_spec.rb +505 -0
- data/spec/plsql/version_spec.rb +8 -0
- data/spec/plsql/view_spec.rb +264 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +79 -0
- metadata +159 -0
@@ -0,0 +1,371 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Table" do
|
4
|
+
before(:all) do
|
5
|
+
plsql.connect! CONNECTION_PARAMS
|
6
|
+
plsql.connection.autocommit = false
|
7
|
+
plsql.execute <<-SQL
|
8
|
+
CREATE TABLE test_employees (
|
9
|
+
employee_id NUMBER(15) NOT NULL,
|
10
|
+
first_name VARCHAR2(50),
|
11
|
+
last_name VARCHAR2(50),
|
12
|
+
hire_date DATE,
|
13
|
+
created_at TIMESTAMP,
|
14
|
+
status VARCHAR2(1) DEFAULT 'N'
|
15
|
+
)
|
16
|
+
SQL
|
17
|
+
|
18
|
+
plsql.execute <<-SQL
|
19
|
+
CREATE OR REPLACE TYPE t_address AS OBJECT (
|
20
|
+
street VARCHAR2(50),
|
21
|
+
city VARCHAR2(50),
|
22
|
+
country VARCHAR2(50)
|
23
|
+
)
|
24
|
+
SQL
|
25
|
+
plsql.execute <<-SQL
|
26
|
+
CREATE OR REPLACE TYPE t_phone AS OBJECT (
|
27
|
+
type VARCHAR2(10),
|
28
|
+
phone_number VARCHAR2(50)
|
29
|
+
)
|
30
|
+
SQL
|
31
|
+
plsql.execute <<-SQL
|
32
|
+
CREATE OR REPLACE TYPE t_phones AS VARRAY(10) OF T_PHONE
|
33
|
+
SQL
|
34
|
+
plsql.execute <<-SQL
|
35
|
+
CREATE TABLE test_employees2 (
|
36
|
+
employee_id NUMBER(15) NOT NULL,
|
37
|
+
first_name VARCHAR2(50),
|
38
|
+
last_name VARCHAR2(50),
|
39
|
+
hire_date DATE DEFAULT SYSDATE,
|
40
|
+
address t_address,
|
41
|
+
phones t_phones
|
42
|
+
)
|
43
|
+
SQL
|
44
|
+
@employees = (1..10).map do |i|
|
45
|
+
{
|
46
|
+
:employee_id => i,
|
47
|
+
:first_name => "First #{i}",
|
48
|
+
:last_name => "Last #{i}",
|
49
|
+
:hire_date => Time.local(2000,01,i),
|
50
|
+
:created_at => Time.local(2000,01,i,9,15,30,i),
|
51
|
+
:status => 'A'
|
52
|
+
}
|
53
|
+
end
|
54
|
+
@employees_all_fields = [:employee_id, :first_name, :last_name, :hire_date, :created_at, :status]
|
55
|
+
@employees_all_values = @employees.map{|e| @employees_all_fields.map{|f| e[f]}}
|
56
|
+
@employees_some_fields = [:employee_id, :first_name, :last_name]
|
57
|
+
@employees_some_values = @employees.map{|e| @employees_some_fields.map{|f| e[f]}}
|
58
|
+
@employee_default_values = {:hire_date => nil, :created_at => nil, :status => 'N'}
|
59
|
+
|
60
|
+
@employees2 = (1..10).map do |i|
|
61
|
+
{
|
62
|
+
:employee_id => i,
|
63
|
+
:first_name => "First #{i}",
|
64
|
+
:last_name => "Last #{i}",
|
65
|
+
:hire_date => Time.local(2000,01,i),
|
66
|
+
:address => {:street => "Street #{i}", :city => "City #{i}", :country => "County #{i}"},
|
67
|
+
:phones => [{:type => "mobile", :phone_number => "Mobile#{i}"}, {:type => "fixed", :phone_number => "Fixed#{i}"}]
|
68
|
+
}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
after(:all) do
|
73
|
+
plsql.execute "DROP TABLE test_employees"
|
74
|
+
plsql.execute "DROP TABLE test_employees2"
|
75
|
+
plsql.execute "DROP TYPE t_phones"
|
76
|
+
plsql.execute "DROP TYPE t_phone"
|
77
|
+
plsql.execute "DROP TYPE t_address"
|
78
|
+
plsql.logoff
|
79
|
+
end
|
80
|
+
|
81
|
+
after(:each) do
|
82
|
+
plsql.rollback
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "find" do
|
86
|
+
|
87
|
+
it "should find existing table" do
|
88
|
+
PLSQL::Table.find(plsql, :test_employees).should_not be_nil
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should not find nonexisting table" do
|
92
|
+
PLSQL::Table.find(plsql, :qwerty123456).should be_nil
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should find existing table in schema" do
|
96
|
+
plsql.test_employees.should be_a(PLSQL::Table)
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "synonym" do
|
102
|
+
|
103
|
+
before(:all) do
|
104
|
+
plsql.execute "CREATE SYNONYM test_employees_synonym FOR hr.test_employees"
|
105
|
+
end
|
106
|
+
|
107
|
+
after(:all) do
|
108
|
+
plsql.execute "DROP SYNONYM test_employees_synonym" rescue nil
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should find synonym to table" do
|
112
|
+
PLSQL::Table.find(plsql, :test_employees_synonym).should_not be_nil
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should find table using synonym in schema" do
|
116
|
+
plsql.test_employees_synonym.should be_a(PLSQL::Table)
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
describe "public synonym" do
|
122
|
+
|
123
|
+
it "should find public synonym to table" do
|
124
|
+
PLSQL::Table.find(plsql, :dual).should_not be_nil
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should find table using public synonym in schema" do
|
128
|
+
plsql.dual.should be_a(PLSQL::Table)
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
describe "columns" do
|
134
|
+
|
135
|
+
it "should get column names for table" do
|
136
|
+
plsql.test_employees.column_names.should == @employees_all_fields
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should get columns metadata for table" do
|
140
|
+
plsql.test_employees.columns.should == {
|
141
|
+
:employee_id => {
|
142
|
+
:position=>1, :data_type=>"NUMBER", :data_length=>22, :data_precision=>15, :data_scale=>0, :char_used=>nil,
|
143
|
+
:type_owner=>nil, :type_name=>nil, :sql_type_name=>nil, :nullable => false, :data_default => nil},
|
144
|
+
:first_name => {
|
145
|
+
:position=>2, :data_type=>"VARCHAR2", :data_length=>50, :data_precision=>nil, :data_scale=>nil, :char_used=>"B",
|
146
|
+
:type_owner=>nil, :type_name=>nil, :sql_type_name=>nil, :nullable => true, :data_default => nil},
|
147
|
+
:last_name => {
|
148
|
+
:position=>3, :data_type=>"VARCHAR2", :data_length=>50, :data_precision=>nil, :data_scale=>nil, :char_used=>"B",
|
149
|
+
:type_owner=>nil, :type_name=>nil, :sql_type_name=>nil, :nullable => true, :data_default => nil},
|
150
|
+
:hire_date => {
|
151
|
+
:position=>4, :data_type=>"DATE", :data_length=>7, :data_precision=>nil, :data_scale=>nil, :char_used=>nil,
|
152
|
+
:type_owner=>nil, :type_name=>nil, :sql_type_name=>nil, :nullable => true, :data_default => nil},
|
153
|
+
:created_at => {
|
154
|
+
:position=>5, :data_type=>"TIMESTAMP", :data_length=>11, :data_precision=>nil, :data_scale=>6, :char_used=>nil,
|
155
|
+
:type_owner=>nil, :type_name=>nil, :sql_type_name=>nil, :nullable => true, :data_default => nil},
|
156
|
+
:status => {
|
157
|
+
:position=>6, :data_type=>"VARCHAR2", :data_length=>1, :data_precision=>nil, :data_scale=>nil, :char_used=>"B",
|
158
|
+
:type_owner=>nil, :type_name=>nil, :sql_type_name=>nil, :nullable => true, :data_default => "'N'"}
|
159
|
+
}
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should get columns metadata for table with object columns" do
|
163
|
+
plsql.test_employees2.columns.should == {
|
164
|
+
:employee_id => {
|
165
|
+
:position=>1, :data_type=>"NUMBER", :data_length=>22, :data_precision=>15, :data_scale=>0, :char_used=>nil,
|
166
|
+
:type_owner=>nil, :type_name=>nil, :sql_type_name=>nil, :nullable => false, :data_default => nil},
|
167
|
+
:first_name => {
|
168
|
+
:position=>2, :data_type=>"VARCHAR2", :data_length=>50, :data_precision=>nil, :data_scale=>nil, :char_used=>"B",
|
169
|
+
:type_owner=>nil, :type_name=>nil, :sql_type_name=>nil, :nullable => true, :data_default => nil},
|
170
|
+
:last_name => {
|
171
|
+
:position=>3, :data_type=>"VARCHAR2", :data_length=>50, :data_precision=>nil, :data_scale=>nil, :char_used=>"B",
|
172
|
+
:type_owner=>nil, :type_name=>nil, :sql_type_name=>nil, :nullable => true, :data_default => nil},
|
173
|
+
:hire_date => {
|
174
|
+
:position=>4, :data_type=>"DATE", :data_length=>7, :data_precision=>nil, :data_scale=>nil, :char_used=>nil,
|
175
|
+
:type_owner=>nil, :type_name=>nil, :sql_type_name=>nil, :nullable => true, :data_default => "SYSDATE"},
|
176
|
+
:address => {
|
177
|
+
:position=>5, :data_type=>"OBJECT", :data_length=>nil, :data_precision=>nil, :data_scale=>nil,
|
178
|
+
:char_used=>nil, :type_owner=>"HR", :type_name=>"T_ADDRESS", :sql_type_name=>"HR.T_ADDRESS", :nullable => true, :data_default => nil},
|
179
|
+
:phones => {
|
180
|
+
:position=>6, :data_type=>"TABLE", :data_length=>nil, :data_precision=>nil, :data_scale=>nil, :char_used=>nil,
|
181
|
+
:type_owner=>"HR", :type_name=>"T_PHONES", :sql_type_name=>"HR.T_PHONES", :nullable => true, :data_default => nil}
|
182
|
+
}
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
|
187
|
+
describe "insert" do
|
188
|
+
it "should insert a record in table" do
|
189
|
+
plsql.test_employees.insert @employees.first
|
190
|
+
plsql.test_employees.all.should == [@employees.first]
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should insert a record in table using partial list of columns" do
|
194
|
+
plsql.test_employees.insert @employees.first.except(:hire_date)
|
195
|
+
plsql.test_employees.all.should == [@employees.first.merge(:hire_date => nil)]
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should insert default value from table definition if value not provided" do
|
199
|
+
plsql.test_employees.insert @employees.first.except(:status)
|
200
|
+
plsql.test_employees.all.should == [@employees.first.merge(:status => 'N')]
|
201
|
+
end
|
202
|
+
|
203
|
+
it "should insert array of records in table" do
|
204
|
+
plsql.test_employees.insert @employees
|
205
|
+
plsql.test_employees.all("ORDER BY employee_id").should == @employees
|
206
|
+
end
|
207
|
+
|
208
|
+
it "should insert a record in table with object types" do
|
209
|
+
plsql.test_employees2.insert @employees2.first
|
210
|
+
plsql.test_employees2.all.should == [@employees2.first]
|
211
|
+
end
|
212
|
+
|
213
|
+
it "should insert array of records in table with object types" do
|
214
|
+
plsql.test_employees2.insert @employees2
|
215
|
+
plsql.test_employees2.all("ORDER BY employee_id").should == @employees2
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
describe "insert values" do
|
221
|
+
it "should insert a record with array of values" do
|
222
|
+
plsql.test_employees.insert_values @employees_all_values.first
|
223
|
+
plsql.test_employees.all.should == [@employees.first]
|
224
|
+
end
|
225
|
+
|
226
|
+
it "should insert a record with list of all fields and array of values" do
|
227
|
+
plsql.test_employees.insert_values @employees_all_fields, @employees_all_values.first
|
228
|
+
plsql.test_employees.all.should == [@employees.first]
|
229
|
+
end
|
230
|
+
|
231
|
+
it "should insert a record with list of some fields and array of values" do
|
232
|
+
plsql.test_employees.insert_values @employees_some_fields, @employees_some_values.first
|
233
|
+
plsql.test_employees.all.should == [@employees.first.merge(@employee_default_values)]
|
234
|
+
end
|
235
|
+
|
236
|
+
it "should insert many records with array of values" do
|
237
|
+
plsql.test_employees.insert_values *@employees_all_values
|
238
|
+
plsql.test_employees.all.should == @employees
|
239
|
+
end
|
240
|
+
|
241
|
+
it "should insert many records with list of all fields and array of values" do
|
242
|
+
plsql.test_employees.insert_values @employees_all_fields, *@employees_all_values
|
243
|
+
plsql.test_employees.all.should == @employees
|
244
|
+
end
|
245
|
+
|
246
|
+
it "should insert many records with list of some fields and array of values" do
|
247
|
+
plsql.test_employees.insert_values @employees_some_fields, *@employees_some_values
|
248
|
+
plsql.test_employees.all.should == @employees.map{|e| e.merge(@employee_default_values)}
|
249
|
+
end
|
250
|
+
|
251
|
+
end
|
252
|
+
|
253
|
+
describe "select" do
|
254
|
+
before(:each) do
|
255
|
+
plsql.test_employees.insert @employees
|
256
|
+
end
|
257
|
+
|
258
|
+
it "should select first record in table" do
|
259
|
+
plsql.test_employees.select(:first, "ORDER BY employee_id").should == @employees.first
|
260
|
+
plsql.test_employees.first("ORDER BY employee_id").should == @employees.first
|
261
|
+
end
|
262
|
+
|
263
|
+
it "should select all records in table" do
|
264
|
+
plsql.test_employees.select(:all, "ORDER BY employee_id").should == @employees
|
265
|
+
plsql.test_employees.all("ORDER BY employee_id").should == @employees
|
266
|
+
plsql.test_employees.all(:order_by => :employee_id).should == @employees
|
267
|
+
end
|
268
|
+
|
269
|
+
it "should select record in table using WHERE condition" do
|
270
|
+
plsql.test_employees.select(:first, "WHERE employee_id = :1", @employees.first[:employee_id]).should == @employees.first
|
271
|
+
plsql.test_employees.first("WHERE employee_id = :1", @employees.first[:employee_id]).should == @employees.first
|
272
|
+
plsql.test_employees.first(:employee_id => @employees.first[:employee_id]).should == @employees.first
|
273
|
+
end
|
274
|
+
|
275
|
+
it "should select records in table using WHERE condition and ORDER BY sorting" do
|
276
|
+
plsql.test_employees.all(:employee_id => @employees.first[:employee_id], :order_by => :employee_id).should == [@employees.first]
|
277
|
+
end
|
278
|
+
|
279
|
+
it "should select record in table using :column => nil condition" do
|
280
|
+
employee = @employees.last.dup
|
281
|
+
employee[:employee_id] = employee[:employee_id] + 1
|
282
|
+
employee[:hire_date] = nil
|
283
|
+
plsql.test_employees.insert employee
|
284
|
+
plsql.test_employees.first("WHERE hire_date IS NULL").should == employee
|
285
|
+
plsql.test_employees.first(:hire_date => nil).should == employee
|
286
|
+
end
|
287
|
+
|
288
|
+
it "should select record in table using :column => :is_null condition" do
|
289
|
+
employee = @employees.last.dup
|
290
|
+
employee[:employee_id] = employee[:employee_id] + 1
|
291
|
+
employee[:hire_date] = nil
|
292
|
+
plsql.test_employees.insert employee
|
293
|
+
plsql.test_employees.first(:hire_date => :is_null).should == employee
|
294
|
+
end
|
295
|
+
|
296
|
+
it "should select record in table using :column => :is_not_null condition" do
|
297
|
+
employee = @employees.last.dup
|
298
|
+
employee[:employee_id] = employee[:employee_id] + 1
|
299
|
+
employee[:hire_date] = nil
|
300
|
+
plsql.test_employees.insert employee
|
301
|
+
plsql.test_employees.all(:hire_date => :is_not_null, :order_by => :employee_id).should == @employees
|
302
|
+
end
|
303
|
+
|
304
|
+
it "should count records in table" do
|
305
|
+
plsql.test_employees.select(:count).should == @employees.size
|
306
|
+
plsql.test_employees.count.should == @employees.size
|
307
|
+
end
|
308
|
+
|
309
|
+
it "should count records in table using condition" do
|
310
|
+
plsql.test_employees.select(:count, "WHERE employee_id <= :1", @employees[2][:employee_id]).should == 3
|
311
|
+
plsql.test_employees.count("WHERE employee_id <= :1", @employees[2][:employee_id]).should == 3
|
312
|
+
end
|
313
|
+
|
314
|
+
end
|
315
|
+
|
316
|
+
describe "update" do
|
317
|
+
it "should update a record in table" do
|
318
|
+
employee_id = @employees.first[:employee_id]
|
319
|
+
plsql.test_employees.insert @employees.first
|
320
|
+
plsql.test_employees.update :first_name => 'Test', :where => {:employee_id => employee_id}
|
321
|
+
plsql.test_employees.first(:employee_id => employee_id)[:first_name].should == 'Test'
|
322
|
+
end
|
323
|
+
|
324
|
+
it "should update a record in table using String WHERE condition" do
|
325
|
+
employee_id = @employees.first[:employee_id]
|
326
|
+
plsql.test_employees.insert @employees
|
327
|
+
plsql.test_employees.update :first_name => 'Test', :where => "employee_id = #{employee_id}"
|
328
|
+
plsql.test_employees.first(:employee_id => employee_id)[:first_name].should == 'Test'
|
329
|
+
# all other records should not be changed
|
330
|
+
plsql.test_employees.all("WHERE employee_id > :1", employee_id) do |employee|
|
331
|
+
employee[:first_name].should_not == 'Test'
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
it "should update all records in table" do
|
336
|
+
plsql.test_employees.insert @employees
|
337
|
+
plsql.test_employees.update :first_name => 'Test'
|
338
|
+
plsql.test_employees.all do |employee|
|
339
|
+
employee[:first_name].should == 'Test'
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
it "should update a record in table with object type" do
|
344
|
+
employee = @employees2[0]
|
345
|
+
employee2 = @employees2[1]
|
346
|
+
plsql.test_employees2.insert employee
|
347
|
+
plsql.test_employees2.update :address => employee2[:address], :phones => employee2[:phones], :where => {:employee_id => employee[:employee_id]}
|
348
|
+
updated_employee = plsql.test_employees2.first(:employee_id => employee[:employee_id])
|
349
|
+
updated_employee[:address].should == employee2[:address]
|
350
|
+
updated_employee[:phones].should == employee2[:phones]
|
351
|
+
end
|
352
|
+
|
353
|
+
end
|
354
|
+
|
355
|
+
describe "delete" do
|
356
|
+
it "should delete record from table" do
|
357
|
+
employee_id = @employees.first[:employee_id]
|
358
|
+
plsql.test_employees.insert @employees
|
359
|
+
plsql.test_employees.delete :employee_id => employee_id
|
360
|
+
plsql.test_employees.first(:employee_id => employee_id).should be_nil
|
361
|
+
plsql.test_employees.all(:order_by => :employee_id).should == @employees[1, @employees.size-1]
|
362
|
+
end
|
363
|
+
|
364
|
+
it "should delete all records from table" do
|
365
|
+
plsql.test_employees.insert @employees
|
366
|
+
plsql.test_employees.delete
|
367
|
+
plsql.test_employees.all.should be_empty
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
end
|
@@ -0,0 +1,304 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Type" do
|
4
|
+
before(:all) do
|
5
|
+
plsql.connection = get_connection
|
6
|
+
plsql.execute "DROP TYPE t_employee" rescue nil
|
7
|
+
plsql.execute "DROP TYPE t_phones" rescue nil
|
8
|
+
plsql.execute "DROP TYPE t_phone" rescue nil
|
9
|
+
plsql.execute <<-SQL
|
10
|
+
CREATE OR REPLACE TYPE t_address AS OBJECT (
|
11
|
+
street VARCHAR2(50),
|
12
|
+
city VARCHAR2(50),
|
13
|
+
country VARCHAR2(50),
|
14
|
+
CONSTRUCTOR FUNCTION t_address(p_full_address VARCHAR2)
|
15
|
+
RETURN SELF AS RESULT,
|
16
|
+
MEMBER FUNCTION display_address(p_separator VARCHAR2 DEFAULT ',') RETURN VARCHAR2,
|
17
|
+
MEMBER FUNCTION display_address(p_uppercase BOOLEAN, p_separator VARCHAR2 DEFAULT ',') RETURN VARCHAR2,
|
18
|
+
MEMBER PROCEDURE set_country(p_country VARCHAR2),
|
19
|
+
MEMBER PROCEDURE set_country2(p_country VARCHAR2, x_display_address OUT VARCHAR2),
|
20
|
+
STATIC FUNCTION create_address(p_full_address VARCHAR2) RETURN t_address
|
21
|
+
);
|
22
|
+
SQL
|
23
|
+
plsql.execute <<-SQL
|
24
|
+
CREATE OR REPLACE TYPE BODY t_address AS
|
25
|
+
CONSTRUCTOR FUNCTION t_address(p_full_address VARCHAR2)
|
26
|
+
RETURN SELF AS RESULT
|
27
|
+
AS
|
28
|
+
l_comma1_pos INTEGER;
|
29
|
+
l_comma2_pos INTEGER;
|
30
|
+
BEGIN
|
31
|
+
l_comma1_pos := INSTR(p_full_address, ',', 1, 1);
|
32
|
+
l_comma2_pos := INSTR(p_full_address, ',', 1, 2);
|
33
|
+
SELF.street := TRIM(SUBSTR(p_full_address, 1, l_comma1_pos - 1));
|
34
|
+
SELF.city := TRIM(SUBSTR(p_full_address, l_comma1_pos+1, l_comma2_pos - l_comma1_pos - 1));
|
35
|
+
SELF.country := TRIM(SUBSTR(p_full_address, l_comma2_pos+1));
|
36
|
+
RETURN;
|
37
|
+
END;
|
38
|
+
MEMBER FUNCTION display_address(p_separator VARCHAR2) RETURN VARCHAR2 IS
|
39
|
+
l_separator VARCHAR2(10) := p_separator;
|
40
|
+
BEGIN
|
41
|
+
IF SUBSTR(l_separator,-1) != ' ' THEN
|
42
|
+
l_separator := l_separator || ' ';
|
43
|
+
END IF;
|
44
|
+
RETURN SELF.street || l_separator || SELF.city || l_separator || SELF.country;
|
45
|
+
END;
|
46
|
+
MEMBER FUNCTION display_address(p_uppercase BOOLEAN, p_separator VARCHAR2) RETURN VARCHAR2 IS
|
47
|
+
l_separator VARCHAR2(10) := p_separator;
|
48
|
+
BEGIN
|
49
|
+
IF p_uppercase THEN
|
50
|
+
RETURN UPPER(SELF.display_address(p_separator));
|
51
|
+
ELSE
|
52
|
+
RETURN SELF.display_address(p_separator);
|
53
|
+
END IF;
|
54
|
+
END;
|
55
|
+
MEMBER PROCEDURE set_country(p_country VARCHAR2) IS
|
56
|
+
BEGIN
|
57
|
+
SELF.country := p_country;
|
58
|
+
END;
|
59
|
+
MEMBER PROCEDURE set_country2(p_country VARCHAR2, x_display_address OUT VARCHAR2) IS
|
60
|
+
BEGIN
|
61
|
+
SELF.country := p_country;
|
62
|
+
x_display_address := SELF.display_address();
|
63
|
+
END;
|
64
|
+
STATIC FUNCTION create_address(p_full_address VARCHAR2) RETURN t_address IS
|
65
|
+
BEGIN
|
66
|
+
RETURN t_address(p_full_address);
|
67
|
+
END;
|
68
|
+
END;
|
69
|
+
SQL
|
70
|
+
plsql.execute <<-SQL
|
71
|
+
CREATE OR REPLACE TYPE t_phone AS OBJECT (
|
72
|
+
type VARCHAR2(10),
|
73
|
+
phone_number VARCHAR2(50)
|
74
|
+
)
|
75
|
+
SQL
|
76
|
+
plsql.execute <<-SQL
|
77
|
+
CREATE OR REPLACE TYPE t_phones AS VARRAY(10) OF T_PHONE
|
78
|
+
SQL
|
79
|
+
plsql.execute <<-SQL
|
80
|
+
CREATE OR REPLACE TYPE t_employee AS OBJECT (
|
81
|
+
employee_id NUMBER(15),
|
82
|
+
first_name VARCHAR2(50),
|
83
|
+
last_name VARCHAR2(50),
|
84
|
+
hire_date DATE,
|
85
|
+
address t_address,
|
86
|
+
phones t_phones
|
87
|
+
)
|
88
|
+
SQL
|
89
|
+
end
|
90
|
+
|
91
|
+
after(:all) do
|
92
|
+
plsql.execute "DROP TYPE t_employee"
|
93
|
+
plsql.execute "DROP TYPE t_address"
|
94
|
+
plsql.execute "DROP TYPE t_phones"
|
95
|
+
plsql.execute "DROP TYPE t_phone"
|
96
|
+
plsql.logoff
|
97
|
+
end
|
98
|
+
|
99
|
+
after(:each) do
|
100
|
+
plsql.rollback
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "find" do
|
104
|
+
|
105
|
+
it "should find existing type" do
|
106
|
+
PLSQL::Type.find(plsql, :t_employee).should_not be_nil
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should not find nonexisting type" do
|
110
|
+
PLSQL::Type.find(plsql, :qwerty123456).should be_nil
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should find existing type in schema" do
|
114
|
+
plsql.t_employee.should be_a(PLSQL::Type)
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "synonym" do
|
120
|
+
|
121
|
+
before(:all) do
|
122
|
+
plsql.execute "CREATE SYNONYM t_employee_synonym FOR hr.t_employee"
|
123
|
+
end
|
124
|
+
|
125
|
+
after(:all) do
|
126
|
+
plsql.execute "DROP SYNONYM t_employee_synonym" rescue nil
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should find synonym to type" do
|
130
|
+
PLSQL::Type.find(plsql, :t_employee_synonym).should_not be_nil
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should find type using synonym in schema" do
|
134
|
+
plsql.t_employee_synonym.should be_a(PLSQL::Type)
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "public synonym" do
|
140
|
+
|
141
|
+
it "should find public synonym to type" do
|
142
|
+
PLSQL::Type.find(plsql, :xmltype).should_not be_nil
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should find type using public synonym in schema" do
|
146
|
+
plsql.xmltype.should be_a(PLSQL::Type)
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
describe "typecode" do
|
152
|
+
|
153
|
+
it "should get typecode of object type" do
|
154
|
+
plsql.t_employee.typecode.should == "OBJECT"
|
155
|
+
end
|
156
|
+
|
157
|
+
it "should get typecode of collection type" do
|
158
|
+
plsql.t_phones.typecode.should == "COLLECTION"
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
describe "attributes" do
|
164
|
+
|
165
|
+
it "should get attribute names" do
|
166
|
+
plsql.t_employee.attribute_names.should == [:employee_id, :first_name, :last_name, :hire_date, :address, :phones]
|
167
|
+
end
|
168
|
+
|
169
|
+
it "should get attributes metadata" do
|
170
|
+
plsql.t_employee.attributes.should == {
|
171
|
+
:employee_id =>
|
172
|
+
{:position=>1, :data_type=>"NUMBER", :data_length=>nil, :data_precision=>15, :data_scale=>0, :type_owner=>nil, :type_name=>nil, :sql_type_name=>nil},
|
173
|
+
:first_name =>
|
174
|
+
{:position=>2, :data_type=>"VARCHAR2", :data_length=>50, :data_precision=>nil, :data_scale=>nil, :type_owner=>nil, :type_name=>nil, :sql_type_name=>nil},
|
175
|
+
:last_name =>
|
176
|
+
{:position=>3, :data_type=>"VARCHAR2", :data_length=>50, :data_precision=>nil, :data_scale=>nil, :type_owner=>nil, :type_name=>nil, :sql_type_name=>nil},
|
177
|
+
:hire_date =>
|
178
|
+
{:position=>4, :data_type=>"DATE", :data_length=>nil, :data_precision=>nil, :data_scale=>nil, :type_owner=>nil, :type_name=>nil, :sql_type_name=>nil},
|
179
|
+
:address =>
|
180
|
+
{:position=>5, :data_type=>"OBJECT", :data_length=>nil, :data_precision=>nil, :data_scale=>nil, :type_owner=>"HR", :type_name=>"T_ADDRESS", :sql_type_name=>"HR.T_ADDRESS"},
|
181
|
+
:phones =>
|
182
|
+
{:position=>6, :data_type=>"TABLE", :data_length=>nil, :data_precision=>nil, :data_scale=>nil, :type_owner=>"HR", :type_name=>"T_PHONES", :sql_type_name=>"HR.T_PHONES"}
|
183
|
+
}
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
describe "object instance" do
|
189
|
+
before(:all) do
|
190
|
+
@phone_attributes = {:type => 'mobile', :phone_number => '123456'}
|
191
|
+
@address_attributes = {:street => 'Street', :city => 'City', :country => 'Country'}
|
192
|
+
@full_address = "#{@address_attributes[:street]}, #{@address_attributes[:city]}, #{@address_attributes[:country]}"
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should get new object instance using named parameters" do
|
196
|
+
plsql.t_phone(@phone_attributes).should == @phone_attributes
|
197
|
+
end
|
198
|
+
|
199
|
+
it "should be an ObjectInstance" do
|
200
|
+
plsql.t_phone(@phone_attributes).should be_a(PLSQL::ObjectInstance)
|
201
|
+
end
|
202
|
+
|
203
|
+
it "should get new object instance using sequential parameters" do
|
204
|
+
plsql.t_phone(@phone_attributes[:type], @phone_attributes[:phone_number]).should == @phone_attributes
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should get new object instance using custom constructor" do
|
208
|
+
plsql.t_address(@full_address).should == @address_attributes
|
209
|
+
plsql.t_address(:p_full_address => @full_address).should == @address_attributes
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should get new object instance using default constructor when custom constructor exists" do
|
213
|
+
plsql.t_address(@address_attributes).should == @address_attributes
|
214
|
+
plsql.t_address(@address_attributes[:street], @address_attributes[:city], @address_attributes[:country]).should == @address_attributes
|
215
|
+
end
|
216
|
+
|
217
|
+
it "should get new empty collection of objects instance" do
|
218
|
+
plsql.t_phones.new.should == []
|
219
|
+
plsql.t_phones([]).should == []
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should get new collection of objects instances" do
|
223
|
+
phone = plsql.t_phone(@phone_attributes)
|
224
|
+
plsql.t_phones([phone, phone]).should == [phone, phone]
|
225
|
+
plsql.t_phones(phone, phone).should == [phone, phone]
|
226
|
+
plsql.t_phones(@phone_attributes, @phone_attributes).should == [phone, phone]
|
227
|
+
end
|
228
|
+
|
229
|
+
end
|
230
|
+
|
231
|
+
describe "member procedures" do
|
232
|
+
before(:all) do
|
233
|
+
@address_attributes = {:street => 'Street', :city => 'City', :country => 'Country'}
|
234
|
+
@full_address = "#{@address_attributes[:street]}, #{@address_attributes[:city]}, #{@address_attributes[:country]}"
|
235
|
+
end
|
236
|
+
|
237
|
+
it "should call object instance member function without parameters" do
|
238
|
+
plsql.t_address(@address_attributes).display_address.should == @full_address
|
239
|
+
end
|
240
|
+
|
241
|
+
it "should call object instance member function with parameters" do
|
242
|
+
plsql.t_address(@address_attributes).display_address(',').should == @full_address
|
243
|
+
end
|
244
|
+
|
245
|
+
it "should call object instance member function with named parameters" do
|
246
|
+
plsql.t_address(@address_attributes).display_address(:p_separator => ',').should == @full_address
|
247
|
+
end
|
248
|
+
|
249
|
+
it "should call object overloaded instance member function" do
|
250
|
+
plsql.t_address(@address_attributes).display_address(true).should == @full_address.upcase
|
251
|
+
plsql.t_address(@address_attributes).display_address(true, ',').should == @full_address.upcase
|
252
|
+
end
|
253
|
+
|
254
|
+
it "should call object instance member function with explicit first SELF parameter" do
|
255
|
+
plsql.t_address.display_address(@address_attributes, ',').should == @full_address
|
256
|
+
end
|
257
|
+
|
258
|
+
it "should call object instance member function with explicit named SELF parameter" do
|
259
|
+
plsql.t_address.display_address(:self => @address_attributes, :p_separator => ',').should == @full_address
|
260
|
+
end
|
261
|
+
|
262
|
+
it "should call object instance member procedure" do
|
263
|
+
other_country = "Other"
|
264
|
+
plsql.t_address(@address_attributes).set_country(other_country).should == @address_attributes.merge(:country => other_country)
|
265
|
+
end
|
266
|
+
|
267
|
+
it "should call object instance member procedure with output parameters" do
|
268
|
+
other_country = "Other"
|
269
|
+
plsql.t_address(@address_attributes).set_country2(other_country).should ==
|
270
|
+
[@address_attributes.merge(:country => other_country),
|
271
|
+
{:x_display_address => "#{@address_attributes[:street]}, #{@address_attributes[:city]}, #{other_country}"}]
|
272
|
+
end
|
273
|
+
|
274
|
+
it "should raise error if invalid member procedure is called" do
|
275
|
+
lambda do
|
276
|
+
plsql.t_address(@address_attributes).invalid_procedure
|
277
|
+
end.should raise_error(ArgumentError)
|
278
|
+
end
|
279
|
+
|
280
|
+
end
|
281
|
+
|
282
|
+
describe "static procedures" do
|
283
|
+
before(:all) do
|
284
|
+
@address_attributes = {:street => 'Street', :city => 'City', :country => 'Country'}
|
285
|
+
@full_address = "#{@address_attributes[:street]}, #{@address_attributes[:city]}, #{@address_attributes[:country]}"
|
286
|
+
end
|
287
|
+
|
288
|
+
it "should call object type static function" do
|
289
|
+
plsql.t_address.create_address(@full_address).should == @address_attributes
|
290
|
+
end
|
291
|
+
|
292
|
+
it "should call object type static function with named parameters" do
|
293
|
+
plsql.t_address.create_address(:p_full_address => @full_address).should == @address_attributes
|
294
|
+
end
|
295
|
+
|
296
|
+
it "should raise error if invalid static procedure is called" do
|
297
|
+
lambda do
|
298
|
+
plsql.t_address.invalid_procedure
|
299
|
+
end.should raise_error(ArgumentError)
|
300
|
+
end
|
301
|
+
|
302
|
+
end
|
303
|
+
|
304
|
+
end
|