flash-gordons-ruby-plsql 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|