ruby-plsql 0.4.0 → 0.4.1

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.
@@ -116,7 +116,7 @@ describe "ActiveRecord connection" do
116
116
  plsql.schema_name.should == 'HR'
117
117
  end
118
118
 
119
- it "should user ActiveRecord::Base.default_timezone as default" do
119
+ it "should use ActiveRecord::Base.default_timezone as default" do
120
120
  ActiveRecord::Base.default_timezone = :utc
121
121
  plsql.default_timezone.should == :utc
122
122
  end
@@ -125,3 +125,111 @@ describe "ActiveRecord connection" do
125
125
  plsql.hr.connection.should == plsql.connection
126
126
  end
127
127
  end
128
+
129
+ describe "DBMS_OUTPUT logging" do
130
+
131
+ before(:all) do
132
+ plsql.connection = get_connection
133
+ plsql.execute <<-SQL
134
+ CREATE OR REPLACE PROCEDURE test_dbms_output(p_string VARCHAR2)
135
+ IS
136
+ BEGIN
137
+ DBMS_OUTPUT.PUT_LINE(p_string);
138
+ END;
139
+ SQL
140
+ plsql.execute <<-SQL
141
+ CREATE OR REPLACE PROCEDURE test_dbms_output_large(p_string VARCHAR2, p_times INTEGER)
142
+ IS
143
+ i INTEGER;
144
+ BEGIN
145
+ FOR i IN 1..p_times LOOP
146
+ DBMS_OUTPUT.PUT_LINE(p_string);
147
+ END LOOP;
148
+ END;
149
+ SQL
150
+ @buffer = StringIO.new
151
+ end
152
+
153
+ before(:each) do
154
+ @buffer.rewind
155
+ @buffer.reopen
156
+ end
157
+
158
+ after(:all) do
159
+ plsql.dbms_output_stream = nil
160
+ plsql.execute "DROP PROCEDURE test_dbms_output"
161
+ plsql.logoff
162
+ end
163
+
164
+ describe "with standard connection" do
165
+ before(:all) do
166
+ plsql.dbms_output_stream = @buffer
167
+ end
168
+
169
+ before(:each) do
170
+ plsql.dbms_output_buffer_size = nil
171
+ end
172
+
173
+ it "should log output to specified stream" do
174
+ plsql.test_dbms_output("test_dbms_output")
175
+ @buffer.string.should == "DBMS_OUTPUT: test_dbms_output\n"
176
+ end
177
+
178
+ it "should not log output to stream when output is disabled" do
179
+ plsql.test_dbms_output("enabled")
180
+ plsql.dbms_output_stream = nil
181
+ plsql.test_dbms_output("disabled")
182
+ plsql.dbms_output_stream = @buffer
183
+ plsql.test_dbms_output("enabled again")
184
+ @buffer.string.should == "DBMS_OUTPUT: enabled\nDBMS_OUTPUT: enabled again\n"
185
+ end
186
+
187
+ it "should log 20_000 character output with default buffer size" do
188
+ times = 2_000
189
+ plsql.test_dbms_output_large("1234567890", times)
190
+ @buffer.string.should == "DBMS_OUTPUT: 1234567890\n" * times
191
+ end
192
+
193
+ it "should log 100_000 character output with specified buffer size" do
194
+ times = 10_000
195
+ plsql.dbms_output_buffer_size = 10 * times
196
+ plsql.test_dbms_output_large("1234567890", times)
197
+ @buffer.string.should == "DBMS_OUTPUT: 1234567890\n" * times
198
+ end
199
+
200
+ it "should log output when database version is less than 10.2" do
201
+ plsql.connection.stub!(:database_version).and_return([9, 2])
202
+ times = 2_000
203
+ plsql.test_dbms_output_large("1234567890", times)
204
+ @buffer.string.should == "DBMS_OUTPUT: 1234567890\n" * times
205
+ end
206
+
207
+ it "should log output when calling procedure with schema prefix" do
208
+ plsql.hr.test_dbms_output("test_dbms_output")
209
+ @buffer.string.should == "DBMS_OUTPUT: test_dbms_output\n"
210
+ end
211
+
212
+ end
213
+
214
+ describe "with Activerecord connection" do
215
+
216
+ before(:all) do
217
+ ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
218
+ plsql(:ar).activerecord_class = ActiveRecord::Base
219
+ plsql(:ar).dbms_output_stream = @buffer
220
+ end
221
+
222
+ it "should log output to specified stream" do
223
+ plsql(:ar).test_dbms_output("test_dbms_output")
224
+ @buffer.string.should == "DBMS_OUTPUT: test_dbms_output\n"
225
+ end
226
+
227
+ it "should log output after reconnection" do
228
+ ActiveRecord::Base.connection.reconnect!
229
+ plsql(:ar).test_dbms_output("after reconnection")
230
+ @buffer.string.should == "DBMS_OUTPUT: after reconnection\n"
231
+ end
232
+
233
+ end
234
+
235
+ end
@@ -41,6 +41,7 @@ describe "SQL statements /" do
41
41
  :hire_date => Time.local(2000,01,i)
42
42
  }
43
43
  end
44
+ plsql.connection.prefetch_rows = 100
44
45
  end
45
46
 
46
47
  before(:each) do
@@ -52,6 +53,7 @@ describe "SQL statements /" do
52
53
  after(:all) do
53
54
  plsql.execute "DROP PROCEDURE test_insert_employee"
54
55
  plsql.execute "DROP TABLE test_employees"
56
+ plsql.connection.prefetch_rows = 1
55
57
  end
56
58
 
57
59
  it "should select first result" do
@@ -59,6 +61,12 @@ describe "SQL statements /" do
59
61
  @employees.first[:employee_id]).should == @employees.first
60
62
  end
61
63
 
64
+ it "should prefetch only one row when selecting first result" do
65
+ lambda {
66
+ plsql.select(:first, "SELECT 1 FROM dual UNION ALL SELECT 1/0 FROM dual")
67
+ }.should_not raise_error
68
+ end
69
+
62
70
  it "should select one value" do
63
71
  plsql.select_one("SELECT count(*) FROM test_employees").should == @employees.size
64
72
  end
@@ -67,6 +75,12 @@ describe "SQL statements /" do
67
75
  plsql.select_one("SELECT employee_id FROM test_employees WHERE 1=2").should be_nil
68
76
  end
69
77
 
78
+ it "should prefetch only one row when selecting one value" do
79
+ lambda {
80
+ plsql.select_one("SELECT 1 FROM dual UNION ALL SELECT 1/0 FROM dual")
81
+ }.should_not raise_error
82
+ end
83
+
70
84
  it "should select all results" do
71
85
  plsql.select(:all, "SELECT * FROM test_employees ORDER BY employee_id").should == @employees
72
86
  plsql.select("SELECT * FROM test_employees ORDER BY employee_id").should == @employees
@@ -74,36 +88,4 @@ describe "SQL statements /" do
74
88
 
75
89
  end
76
90
 
77
- # describe "INSERT" do
78
- # before(:all) do
79
- # plsql.execute "DROP TABLE test_employees" rescue nil
80
- # plsql.execute <<-SQL
81
- # CREATE TABLE test_employees (
82
- # employee_id NUMBER(15),
83
- # first_name VARCHAR2(50),
84
- # last_name VARCHAR2(50),
85
- # hire_date DATE
86
- # )
87
- # SQL
88
- # @employees = (1..10).map do |i|
89
- # {
90
- # :employee_id => i,
91
- # :first_name => "First #{i}",
92
- # :last_name => "Last #{i}",
93
- # :hire_date => Time.local(2000,01,i)
94
- # }
95
- # end
96
- # end
97
- #
98
- # after(:all) do
99
- # plsql.execute "DROP TABLE test_employees"
100
- # end
101
- #
102
- # # it "should insert a record in table" do
103
- # # plsql.test_employees.insert @employees.first
104
- # # plsql.test_employees.select(:all).should == [@employees.first]
105
- # # end
106
- #
107
- # end
108
-
109
91
  end
@@ -9,27 +9,28 @@ describe "Table" do
9
9
  employee_id NUMBER(15),
10
10
  first_name VARCHAR2(50),
11
11
  last_name VARCHAR2(50),
12
- hire_date DATE
12
+ hire_date DATE,
13
+ status VARCHAR2(1) DEFAULT 'N'
13
14
  )
14
15
  SQL
15
16
 
16
- plsql.connection.exec <<-SQL
17
+ plsql.execute <<-SQL
17
18
  CREATE OR REPLACE TYPE t_address AS OBJECT (
18
19
  street VARCHAR2(50),
19
20
  city VARCHAR2(50),
20
21
  country VARCHAR2(50)
21
22
  )
22
23
  SQL
23
- plsql.connection.exec <<-SQL
24
+ plsql.execute <<-SQL
24
25
  CREATE OR REPLACE TYPE t_phone AS OBJECT (
25
26
  type VARCHAR2(10),
26
27
  phone_number VARCHAR2(50)
27
28
  )
28
29
  SQL
29
- plsql.connection.exec <<-SQL
30
+ plsql.execute <<-SQL
30
31
  CREATE OR REPLACE TYPE t_phones AS VARRAY(10) OF T_PHONE
31
32
  SQL
32
- plsql.connection.exec <<-SQL
33
+ plsql.execute <<-SQL
33
34
  CREATE TABLE test_employees2 (
34
35
  employee_id NUMBER(15),
35
36
  first_name VARCHAR2(50),
@@ -44,9 +45,16 @@ describe "Table" do
44
45
  :employee_id => i,
45
46
  :first_name => "First #{i}",
46
47
  :last_name => "Last #{i}",
47
- :hire_date => Time.local(2000,01,i)
48
+ :hire_date => Time.local(2000,01,i),
49
+ :status => 'A'
48
50
  }
49
51
  end
52
+ @employees_all_fields = [:employee_id, :first_name, :last_name, :hire_date, :status]
53
+ @employees_all_values = @employees.map{|e| @employees_all_fields.map{|f| e[f]}}
54
+ @employees_some_fields = [:employee_id, :first_name, :last_name]
55
+ @employees_some_values = @employees.map{|e| @employees_some_fields.map{|f| e[f]}}
56
+ @employee_default_values = {:hire_date => nil, :status => 'N'}
57
+
50
58
  @employees2 = (1..10).map do |i|
51
59
  {
52
60
  :employee_id => i,
@@ -91,11 +99,11 @@ describe "Table" do
91
99
  describe "synonym" do
92
100
 
93
101
  before(:all) do
94
- plsql.connection.exec "CREATE SYNONYM test_employees_synonym FOR hr.test_employees"
102
+ plsql.execute "CREATE SYNONYM test_employees_synonym FOR hr.test_employees"
95
103
  end
96
104
 
97
105
  after(:all) do
98
- plsql.connection.exec "DROP SYNONYM test_employees_synonym" rescue nil
106
+ plsql.execute "DROP SYNONYM test_employees_synonym" rescue nil
99
107
  end
100
108
 
101
109
  it "should find synonym to table" do
@@ -122,6 +130,10 @@ describe "Table" do
122
130
 
123
131
  describe "columns" do
124
132
 
133
+ it "should get column names for table" do
134
+ plsql.test_employees.column_names.should == [:employee_id, :first_name, :last_name, :hire_date, :status]
135
+ end
136
+
125
137
  it "should get columns metadata for table" do
126
138
  plsql.test_employees.columns.should == {
127
139
  :employee_id =>
@@ -131,7 +143,9 @@ describe "Table" do
131
143
  :last_name =>
132
144
  {:position=>3, :data_type=>"VARCHAR2", :data_length=>50, :data_precision=>nil, :data_scale=>nil, :char_used=>"B", :type_owner=>nil, :type_name=>nil, :sql_type_name=>nil},
133
145
  :hire_date =>
134
- {:position=>4, :data_type=>"DATE", :data_length=>7, :data_precision=>nil, :data_scale=>nil, :char_used=>nil, :type_owner=>nil, :type_name=>nil, :sql_type_name=>nil}
146
+ {:position=>4, :data_type=>"DATE", :data_length=>7, :data_precision=>nil, :data_scale=>nil, :char_used=>nil, :type_owner=>nil, :type_name=>nil, :sql_type_name=>nil},
147
+ :status =>
148
+ {:position=>5, :data_type=>"VARCHAR2", :data_length=>1, :data_precision=>nil, :data_scale=>nil, :char_used=>"B", :type_owner=>nil, :type_name=>nil, :sql_type_name=>nil}
135
149
  }
136
150
  end
137
151
 
@@ -160,6 +174,16 @@ describe "Table" do
160
174
  plsql.test_employees.all.should == [@employees.first]
161
175
  end
162
176
 
177
+ it "should insert a record in table using partial list of columns" do
178
+ plsql.test_employees.insert @employees.first.except(:hire_date)
179
+ plsql.test_employees.all.should == [@employees.first.merge(:hire_date => nil)]
180
+ end
181
+
182
+ it "should insert default value from table definition if value not provided" do
183
+ plsql.test_employees.insert @employees.first.except(:status)
184
+ plsql.test_employees.all.should == [@employees.first.merge(:status => 'N')]
185
+ end
186
+
163
187
  it "should insert array of records in table" do
164
188
  plsql.test_employees.insert @employees
165
189
  plsql.test_employees.all("ORDER BY employee_id").should == @employees
@@ -177,6 +201,39 @@ describe "Table" do
177
201
 
178
202
  end
179
203
 
204
+ describe "insert values" do
205
+ it "should insert a record with array of values" do
206
+ plsql.test_employees.insert_values @employees_all_values.first
207
+ plsql.test_employees.all.should == [@employees.first]
208
+ end
209
+
210
+ it "should insert a record with list of all fields and array of values" do
211
+ plsql.test_employees.insert_values @employees_all_fields, @employees_all_values.first
212
+ plsql.test_employees.all.should == [@employees.first]
213
+ end
214
+
215
+ it "should insert a record with list of some fields and array of values" do
216
+ plsql.test_employees.insert_values @employees_some_fields, @employees_some_values.first
217
+ plsql.test_employees.all.should == [@employees.first.merge(@employee_default_values)]
218
+ end
219
+
220
+ it "should insert many records with array of values" do
221
+ plsql.test_employees.insert_values *@employees_all_values
222
+ plsql.test_employees.all.should == @employees
223
+ end
224
+
225
+ it "should insert many records with list of all fields and array of values" do
226
+ plsql.test_employees.insert_values @employees_all_fields, *@employees_all_values
227
+ plsql.test_employees.all.should == @employees
228
+ end
229
+
230
+ it "should insert many records with list of some fields and array of values" do
231
+ plsql.test_employees.insert_values @employees_some_fields, *@employees_some_values
232
+ plsql.test_employees.all.should == @employees.map{|e| e.merge(@employee_default_values)}
233
+ end
234
+
235
+ end
236
+
180
237
  describe "select" do
181
238
  before(:each) do
182
239
  plsql.test_employees.insert @employees
@@ -199,6 +256,15 @@ describe "Table" do
199
256
  plsql.test_employees.first(:employee_id => @employees.first[:employee_id]).should == @employees.first
200
257
  end
201
258
 
259
+ it "should select record in table using :column => nil condition" do
260
+ employee = @employees.last
261
+ employee[:employee_id] = employee[:employee_id] + 1
262
+ employee[:hire_date] = nil
263
+ plsql.test_employees.insert employee
264
+ plsql.test_employees.first("WHERE hire_date IS NULL").should == employee
265
+ plsql.test_employees.first(:hire_date => nil).should == employee
266
+ end
267
+
202
268
  it "should count records in table" do
203
269
  plsql.test_employees.select(:count).should == @employees.size
204
270
  plsql.test_employees.count.should == @employees.size
@@ -0,0 +1,133 @@
1
+ require File.dirname(__FILE__) + '/../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 <<-SQL
9
+ CREATE OR REPLACE TYPE t_address AS OBJECT (
10
+ street VARCHAR2(50),
11
+ city VARCHAR2(50),
12
+ country VARCHAR2(50)
13
+ )
14
+ SQL
15
+ plsql.execute <<-SQL
16
+ CREATE OR REPLACE TYPE t_phone AS OBJECT (
17
+ type VARCHAR2(10),
18
+ phone_number VARCHAR2(50)
19
+ )
20
+ SQL
21
+ plsql.execute <<-SQL
22
+ CREATE OR REPLACE TYPE t_phones AS VARRAY(10) OF T_PHONE
23
+ SQL
24
+ plsql.execute <<-SQL
25
+ CREATE OR REPLACE TYPE t_employee AS OBJECT (
26
+ employee_id NUMBER(15),
27
+ first_name VARCHAR2(50),
28
+ last_name VARCHAR2(50),
29
+ hire_date DATE,
30
+ address t_address,
31
+ phones t_phones
32
+ )
33
+ SQL
34
+ end
35
+
36
+ after(:all) do
37
+ plsql.execute "DROP TYPE t_employee"
38
+ plsql.execute "DROP TYPE t_address"
39
+ plsql.execute "DROP TYPE t_phones"
40
+ plsql.execute "DROP TYPE t_phone"
41
+ plsql.logoff
42
+ end
43
+
44
+ after(:each) do
45
+ plsql.rollback
46
+ end
47
+
48
+ describe "find" do
49
+
50
+ it "should find existing type" do
51
+ PLSQL::Type.find(plsql, :t_employee).should_not be_nil
52
+ end
53
+
54
+ it "should not find nonexisting type" do
55
+ PLSQL::Type.find(plsql, :qwerty123456).should be_nil
56
+ end
57
+
58
+ it "should find existing type in schema" do
59
+ plsql.t_employee.should be_a(PLSQL::Type)
60
+ end
61
+
62
+ end
63
+
64
+ describe "synonym" do
65
+
66
+ before(:all) do
67
+ plsql.execute "CREATE SYNONYM t_employee_synonym FOR hr.t_employee"
68
+ end
69
+
70
+ after(:all) do
71
+ plsql.execute "DROP SYNONYM t_employee_synonym" rescue nil
72
+ end
73
+
74
+ it "should find synonym to type" do
75
+ PLSQL::Type.find(plsql, :t_employee_synonym).should_not be_nil
76
+ end
77
+
78
+ it "should find type using synonym in schema" do
79
+ plsql.t_employee_synonym.should be_a(PLSQL::Type)
80
+ end
81
+
82
+ end
83
+
84
+ describe "public synonym" do
85
+
86
+ it "should find public synonym to type" do
87
+ PLSQL::Type.find(plsql, :xmltype).should_not be_nil
88
+ end
89
+
90
+ it "should find type using public synonym in schema" do
91
+ plsql.xmltype.should be_a(PLSQL::Type)
92
+ end
93
+
94
+ end
95
+
96
+ describe "typecode" do
97
+
98
+ it "should get typecode of object type" do
99
+ plsql.t_employee.typecode.should == "OBJECT"
100
+ end
101
+
102
+ it "should get typecode of collection type" do
103
+ plsql.t_phones.typecode.should == "COLLECTION"
104
+ end
105
+
106
+ end
107
+
108
+ describe "attributes" do
109
+
110
+ it "should get attribute names" do
111
+ plsql.t_employee.attribute_names.should == [:employee_id, :first_name, :last_name, :hire_date, :address, :phones]
112
+ end
113
+
114
+ it "should get attributes metadata" do
115
+ plsql.t_employee.attributes.should == {
116
+ :employee_id =>
117
+ {:position=>1, :data_type=>"NUMBER", :data_length=>nil, :data_precision=>15, :data_scale=>0, :type_owner=>nil, :type_name=>nil, :sql_type_name=>nil},
118
+ :first_name =>
119
+ {:position=>2, :data_type=>"VARCHAR2", :data_length=>50, :data_precision=>nil, :data_scale=>nil, :type_owner=>nil, :type_name=>nil, :sql_type_name=>nil},
120
+ :last_name =>
121
+ {:position=>3, :data_type=>"VARCHAR2", :data_length=>50, :data_precision=>nil, :data_scale=>nil, :type_owner=>nil, :type_name=>nil, :sql_type_name=>nil},
122
+ :hire_date =>
123
+ {:position=>4, :data_type=>"DATE", :data_length=>nil, :data_precision=>nil, :data_scale=>nil, :type_owner=>nil, :type_name=>nil, :sql_type_name=>nil},
124
+ :address =>
125
+ {: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"},
126
+ :phones =>
127
+ {: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"}
128
+ }
129
+ end
130
+
131
+ end
132
+
133
+ end