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,331 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Schema" do
|
4
|
+
|
5
|
+
it "should create Schema object" do
|
6
|
+
plsql.class.should == PLSQL::Schema
|
7
|
+
end
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "Schema connection" do
|
12
|
+
|
13
|
+
before(:each) do
|
14
|
+
@conn = get_connection
|
15
|
+
end
|
16
|
+
|
17
|
+
after(:each) do
|
18
|
+
unless defined? JRUBY_VERSION
|
19
|
+
@conn.logoff
|
20
|
+
else
|
21
|
+
@conn.close
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should connect to test database" do
|
26
|
+
plsql.connection = @conn
|
27
|
+
plsql.connection.raw_connection.should == @conn
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should connect to test database using connection alias" do
|
31
|
+
plsql(:hr).connection = @conn
|
32
|
+
plsql(:hr).connection.raw_connection.should == @conn
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should return schema name" do
|
36
|
+
plsql.connection = @conn
|
37
|
+
plsql.schema_name.should == DATABASE_USERS_AND_PASSWORDS[0][0].upcase
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should return new schema name after reconnection" do
|
41
|
+
plsql.connection = @conn
|
42
|
+
plsql.schema_name.should == DATABASE_USERS_AND_PASSWORDS[0][0].upcase
|
43
|
+
plsql.connection = get_connection(1)
|
44
|
+
plsql.schema_name.should == DATABASE_USERS_AND_PASSWORDS[1][0].upcase
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should return nil schema name if not connected" do
|
48
|
+
plsql(:xxx).schema_name.should == nil
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "Connection with connect!" do
|
54
|
+
|
55
|
+
before(:all) do
|
56
|
+
@username, @password = DATABASE_USERS_AND_PASSWORDS[0]
|
57
|
+
@database = DATABASE_NAME
|
58
|
+
@host = DATABASE_HOST
|
59
|
+
@port = DATABASE_PORT
|
60
|
+
end
|
61
|
+
|
62
|
+
after(:each) do
|
63
|
+
plsql.logoff if plsql.connection
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should connect with username, password and database alias" do
|
67
|
+
plsql.connect! @username, @password, @database
|
68
|
+
plsql.connection.should_not be_nil
|
69
|
+
plsql.schema_name.should == @username.upcase
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should connect with username, password, host, port and database name" do
|
73
|
+
plsql.connect! @username, @password, :host => @host, :port => @port, :database => @database
|
74
|
+
plsql.connection.should_not be_nil
|
75
|
+
plsql.schema_name.should == @username.upcase
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should connect with username, password, host, database name and default port" do
|
79
|
+
pending "Non-default port used for test database" unless @port == 1521
|
80
|
+
plsql.connect! @username, @password, :host => @host, :database => @database
|
81
|
+
plsql.connection.should_not be_nil
|
82
|
+
plsql.schema_name.should == @username.upcase
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should not connect with wrong port number" do
|
86
|
+
lambda {
|
87
|
+
plsql.connect! @username, @password, :host => @host, :port => 9999, :database => @database
|
88
|
+
}.should raise_error(/no listener|could not establish the connection/)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should connect with one Hash parameter" do
|
92
|
+
plsql.connect! :username => @username, :password => @password, :database => @database
|
93
|
+
plsql.connection.should_not be_nil
|
94
|
+
plsql.schema_name.should == @username.upcase
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should set session time zone from TZ environment variable" do
|
98
|
+
plsql.connect! @username, @password, @database
|
99
|
+
plsql.connection.time_zone.should == ENV['TZ']
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should set session time zone from :time_zone parameter" do
|
103
|
+
plsql.connect! :username => @username, :password => @password, :database => @database, :time_zone => 'EET'
|
104
|
+
plsql.connection.time_zone.should == 'EET'
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "Named Schema" do
|
110
|
+
before(:all) do
|
111
|
+
plsql.connection = @conn = get_connection
|
112
|
+
end
|
113
|
+
|
114
|
+
after(:all) do
|
115
|
+
plsql.connection.logoff
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should find existing schema" do
|
119
|
+
plsql.hr.class.should == PLSQL::Schema
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should have the same connection as default schema" do
|
123
|
+
plsql.hr.connection.raw_connection.should == @conn
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should return schema name" do
|
127
|
+
plsql.hr.schema_name.should == 'HR'
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should not find named schema if specified twice" do
|
131
|
+
lambda { plsql.hr.hr }.should raise_error(ArgumentError)
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
describe "Schema commit and rollback" do
|
137
|
+
before(:all) do
|
138
|
+
plsql.connection = @conn = get_connection
|
139
|
+
plsql.connection.autocommit = false
|
140
|
+
plsql.execute "CREATE TABLE test_commit (dummy VARCHAR2(100))"
|
141
|
+
@data = {:dummy => 'test'}
|
142
|
+
@data2 = {:dummy => 'test2'}
|
143
|
+
end
|
144
|
+
|
145
|
+
after(:all) do
|
146
|
+
plsql.execute "DROP TABLE test_commit"
|
147
|
+
plsql.logoff
|
148
|
+
end
|
149
|
+
|
150
|
+
after(:each) do
|
151
|
+
plsql.test_commit.delete
|
152
|
+
plsql.commit
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should do commit" do
|
156
|
+
plsql.test_commit.insert @data
|
157
|
+
plsql.commit
|
158
|
+
plsql.test_commit.first.should == @data
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should do rollback" do
|
162
|
+
plsql.test_commit.insert @data
|
163
|
+
plsql.rollback
|
164
|
+
plsql.test_commit.first.should be_nil
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should create savepoint and rollback to savepoint" do
|
168
|
+
plsql.test_commit.insert @data
|
169
|
+
plsql.savepoint 'test'
|
170
|
+
plsql.test_commit.insert @data2
|
171
|
+
plsql.test_commit.all.should == [@data, @data2]
|
172
|
+
plsql.rollback_to 'test'
|
173
|
+
plsql.test_commit.all.should == [@data]
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
177
|
+
|
178
|
+
describe "ActiveRecord connection" do
|
179
|
+
before(:all) do
|
180
|
+
ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
|
181
|
+
class TestBaseModel < ActiveRecord::Base
|
182
|
+
self.abstract_class = true
|
183
|
+
end
|
184
|
+
class TestModel < TestBaseModel
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
before(:each) do
|
189
|
+
plsql.activerecord_class = ActiveRecord::Base
|
190
|
+
end
|
191
|
+
|
192
|
+
it "should connect to test database" do
|
193
|
+
unless defined?(JRUBY_VERSION)
|
194
|
+
plsql.connection.is_a?(PLSQL::OCIConnection).should be_true
|
195
|
+
else
|
196
|
+
plsql.connection.is_a?(PLSQL::JDBCConnection).should be_true
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should return schema name" do
|
201
|
+
plsql.schema_name.should == 'HR'
|
202
|
+
end
|
203
|
+
|
204
|
+
it "should use ActiveRecord::Base.default_timezone as default" do
|
205
|
+
ActiveRecord::Base.default_timezone = :utc
|
206
|
+
plsql.default_timezone.should == :utc
|
207
|
+
end
|
208
|
+
|
209
|
+
it "should have the same connection as default schema" do
|
210
|
+
plsql.hr.connection.should == plsql.connection
|
211
|
+
end
|
212
|
+
|
213
|
+
it "should accept inherited ActiveRecord class" do
|
214
|
+
plsql.activerecord_class = TestBaseModel
|
215
|
+
plsql.schema_name.should == 'HR'
|
216
|
+
end
|
217
|
+
|
218
|
+
it "should accept subclass of inherited ActiveRecord class" do
|
219
|
+
plsql.activerecord_class = TestModel
|
220
|
+
plsql.schema_name.should == 'HR'
|
221
|
+
end
|
222
|
+
end if defined?(ActiveRecord)
|
223
|
+
|
224
|
+
describe "DBMS_OUTPUT logging" do
|
225
|
+
|
226
|
+
before(:all) do
|
227
|
+
plsql.connection = get_connection
|
228
|
+
plsql.execute <<-SQL
|
229
|
+
CREATE OR REPLACE PROCEDURE test_dbms_output(p_string VARCHAR2)
|
230
|
+
IS
|
231
|
+
BEGIN
|
232
|
+
DBMS_OUTPUT.PUT_LINE(p_string);
|
233
|
+
END;
|
234
|
+
SQL
|
235
|
+
plsql.execute <<-SQL
|
236
|
+
CREATE OR REPLACE PROCEDURE test_dbms_output_large(p_string VARCHAR2, p_times INTEGER)
|
237
|
+
IS
|
238
|
+
i INTEGER;
|
239
|
+
BEGIN
|
240
|
+
FOR i IN 1..p_times LOOP
|
241
|
+
DBMS_OUTPUT.PUT_LINE(p_string);
|
242
|
+
END LOOP;
|
243
|
+
END;
|
244
|
+
SQL
|
245
|
+
@buffer = StringIO.new
|
246
|
+
end
|
247
|
+
|
248
|
+
before(:each) do
|
249
|
+
@buffer.rewind
|
250
|
+
@buffer.reopen
|
251
|
+
end
|
252
|
+
|
253
|
+
after(:all) do
|
254
|
+
plsql.dbms_output_stream = nil
|
255
|
+
plsql.execute "DROP PROCEDURE test_dbms_output"
|
256
|
+
plsql.execute "DROP PROCEDURE test_dbms_output_large"
|
257
|
+
plsql.logoff
|
258
|
+
end
|
259
|
+
|
260
|
+
describe "with standard connection" do
|
261
|
+
before(:all) do
|
262
|
+
plsql.dbms_output_stream = @buffer
|
263
|
+
end
|
264
|
+
|
265
|
+
before(:each) do
|
266
|
+
plsql.dbms_output_buffer_size = nil
|
267
|
+
end
|
268
|
+
|
269
|
+
it "should log output to specified stream" do
|
270
|
+
plsql.test_dbms_output("test_dbms_output")
|
271
|
+
@buffer.string.should == "DBMS_OUTPUT: test_dbms_output\n"
|
272
|
+
end
|
273
|
+
|
274
|
+
it "should not log output to stream when output is disabled" do
|
275
|
+
plsql.test_dbms_output("enabled")
|
276
|
+
plsql.dbms_output_stream = nil
|
277
|
+
plsql.test_dbms_output("disabled")
|
278
|
+
plsql.dbms_output_stream = @buffer
|
279
|
+
plsql.test_dbms_output("enabled again")
|
280
|
+
@buffer.string.should == "DBMS_OUTPUT: enabled\nDBMS_OUTPUT: enabled again\n"
|
281
|
+
end
|
282
|
+
|
283
|
+
it "should log 20_000 character output with default buffer size" do
|
284
|
+
times = 2_000
|
285
|
+
plsql.test_dbms_output_large("1234567890", times)
|
286
|
+
@buffer.string.should == "DBMS_OUTPUT: 1234567890\n" * times
|
287
|
+
end
|
288
|
+
|
289
|
+
it "should log 100_000 character output with specified buffer size" do
|
290
|
+
times = 10_000
|
291
|
+
plsql.dbms_output_buffer_size = 10 * times
|
292
|
+
plsql.test_dbms_output_large("1234567890", times)
|
293
|
+
@buffer.string.should == "DBMS_OUTPUT: 1234567890\n" * times
|
294
|
+
end
|
295
|
+
|
296
|
+
it "should log output when database version is less than 10.2" do
|
297
|
+
plsql.connection.stub!(:database_version).and_return([9, 2, 0, 0])
|
298
|
+
times = 2_000
|
299
|
+
plsql.test_dbms_output_large("1234567890", times)
|
300
|
+
@buffer.string.should == "DBMS_OUTPUT: 1234567890\n" * times
|
301
|
+
end
|
302
|
+
|
303
|
+
it "should log output when calling procedure with schema prefix" do
|
304
|
+
plsql.hr.test_dbms_output("test_dbms_output")
|
305
|
+
@buffer.string.should == "DBMS_OUTPUT: test_dbms_output\n"
|
306
|
+
end
|
307
|
+
|
308
|
+
end
|
309
|
+
|
310
|
+
describe "with Activerecord connection" do
|
311
|
+
|
312
|
+
before(:all) do
|
313
|
+
ActiveRecord::Base.establish_connection(CONNECTION_PARAMS)
|
314
|
+
plsql(:ar).activerecord_class = ActiveRecord::Base
|
315
|
+
plsql(:ar).dbms_output_stream = @buffer
|
316
|
+
end
|
317
|
+
|
318
|
+
it "should log output to specified stream" do
|
319
|
+
plsql(:ar).test_dbms_output("test_dbms_output")
|
320
|
+
@buffer.string.should == "DBMS_OUTPUT: test_dbms_output\n"
|
321
|
+
end
|
322
|
+
|
323
|
+
it "should log output after reconnection" do
|
324
|
+
ActiveRecord::Base.connection.reconnect!
|
325
|
+
plsql(:ar).test_dbms_output("after reconnection")
|
326
|
+
@buffer.string.should == "DBMS_OUTPUT: after reconnection\n"
|
327
|
+
end
|
328
|
+
|
329
|
+
end if defined?(ActiveRecord)
|
330
|
+
|
331
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Table" do
|
4
|
+
before(:all) do
|
5
|
+
plsql.connection = get_connection
|
6
|
+
plsql.connection.autocommit = false
|
7
|
+
plsql.execute "CREATE SEQUENCE test_employees_seq"
|
8
|
+
end
|
9
|
+
|
10
|
+
after(:all) do
|
11
|
+
plsql.execute "DROP SEQUENCE test_employees_seq"
|
12
|
+
plsql.logoff
|
13
|
+
end
|
14
|
+
|
15
|
+
after(:each) do
|
16
|
+
plsql.rollback
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "find" do
|
20
|
+
|
21
|
+
it "should find existing sequence" do
|
22
|
+
PLSQL::Sequence.find(plsql, :test_employees_seq).should_not be_nil
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should not find nonexisting table" do
|
26
|
+
PLSQL::Sequence.find(plsql, :qwerty123456).should be_nil
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should find existing sequence in schema" do
|
30
|
+
plsql.test_employees_seq.should be_a(PLSQL::Sequence)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "synonym" do
|
36
|
+
|
37
|
+
before(:all) do
|
38
|
+
plsql.connection.exec "CREATE SYNONYM test_employees_seq_synonym FOR hr.test_employees_seq"
|
39
|
+
end
|
40
|
+
|
41
|
+
after(:all) do
|
42
|
+
plsql.connection.exec "DROP SYNONYM test_employees_seq_synonym" rescue nil
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should find synonym to sequence" do
|
46
|
+
PLSQL::Sequence.find(plsql, :test_employees_seq_synonym).should_not be_nil
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should find sequence using synonym in schema" do
|
50
|
+
plsql.test_employees_seq_synonym.should be_a(PLSQL::Sequence)
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "values" do
|
56
|
+
it "should get next value from sequence" do
|
57
|
+
next_value = plsql.select_one "SELECT test_employees_seq.NEXTVAL FROM dual"
|
58
|
+
plsql.test_employees_seq.nextval.should == next_value + 1
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should get current value from sequence" do
|
62
|
+
next_value = plsql.test_employees_seq.nextval
|
63
|
+
plsql.test_employees_seq.currval.should == next_value
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "SQL statements /" do
|
4
|
+
before(:all) do
|
5
|
+
plsql.connect! CONNECTION_PARAMS
|
6
|
+
plsql.connection.autocommit = false
|
7
|
+
end
|
8
|
+
|
9
|
+
after(:all) do
|
10
|
+
plsql.logoff
|
11
|
+
end
|
12
|
+
|
13
|
+
after(:each) do
|
14
|
+
plsql.rollback
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "SELECT" do
|
18
|
+
before(:all) do
|
19
|
+
plsql.execute "DROP TABLE test_employees" rescue nil
|
20
|
+
plsql.execute <<-SQL
|
21
|
+
CREATE TABLE test_employees (
|
22
|
+
employee_id NUMBER(15),
|
23
|
+
first_name VARCHAR2(50),
|
24
|
+
last_name VARCHAR2(50),
|
25
|
+
hire_date DATE
|
26
|
+
)
|
27
|
+
SQL
|
28
|
+
plsql.execute <<-SQL
|
29
|
+
CREATE OR REPLACE PROCEDURE test_insert_employee(p_employee test_employees%ROWTYPE)
|
30
|
+
IS
|
31
|
+
BEGIN
|
32
|
+
INSERT INTO test_employees
|
33
|
+
VALUES p_employee;
|
34
|
+
END;
|
35
|
+
SQL
|
36
|
+
@employees = (1..10).map do |i|
|
37
|
+
{
|
38
|
+
:employee_id => i,
|
39
|
+
:first_name => "First #{i}",
|
40
|
+
:last_name => "Last #{i}",
|
41
|
+
:hire_date => Time.local(2000,01,i)
|
42
|
+
}
|
43
|
+
end
|
44
|
+
plsql.connection.prefetch_rows = 100
|
45
|
+
end
|
46
|
+
|
47
|
+
before(:each) do
|
48
|
+
@employees.each do |e|
|
49
|
+
plsql.test_insert_employee(e)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
after(:all) do
|
54
|
+
plsql.execute "DROP PROCEDURE test_insert_employee"
|
55
|
+
plsql.execute "DROP TABLE test_employees"
|
56
|
+
plsql.connection.prefetch_rows = 1
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should select first result" do
|
60
|
+
plsql.select(:first, "SELECT * FROM test_employees WHERE employee_id = :employee_id",
|
61
|
+
@employees.first[:employee_id]).should == @employees.first
|
62
|
+
end
|
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
|
+
|
70
|
+
it "should select one value" do
|
71
|
+
plsql.select_one("SELECT count(*) FROM test_employees").should == @employees.size
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should return nil when selecting non-existing one value" do
|
75
|
+
plsql.select_one("SELECT employee_id FROM test_employees WHERE 1=2").should be_nil
|
76
|
+
end
|
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
|
+
|
84
|
+
it "should select all results" do
|
85
|
+
plsql.select(:all, "SELECT * FROM test_employees ORDER BY employee_id").should == @employees
|
86
|
+
plsql.select("SELECT * FROM test_employees ORDER BY employee_id").should == @employees
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|