ibm_db 0.4.0 → 0.4.6

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.
@@ -0,0 +1,2 @@
1
+ DROP TABLE courses;
2
+
@@ -0,0 +1,5 @@
1
+ CREATE TABLE courses (
2
+ id INT NOT NULL PRIMARY KEY,
3
+ name VARCHAR(255) NOT NULL
4
+ );
5
+
@@ -0,0 +1,32 @@
1
+ DROP TABLE accounts;
2
+ DROP TABLE funny_jokes;
3
+ DROP TABLE companies;
4
+ DROP TABLE topics;
5
+ DROP TABLE developers;
6
+ DROP TABLE projects;
7
+ DROP TABLE developers_projects;
8
+ DROP TABLE orders;
9
+ DROP TABLE customers;
10
+ DROP TABLE movies;
11
+ DROP TABLE subscribers;
12
+ DROP TABLE booleantests;
13
+ DROP TABLE auto_id_tests;
14
+ DROP TABLE entrants;
15
+ DROP TABLE colnametests;
16
+ DROP TABLE mixins;
17
+ DROP TABLE people;
18
+ DROP TABLE readers;
19
+ DROP TABLE binaries;
20
+ DROP TABLE computers;
21
+ DROP TABLE posts;
22
+ DROP TABLE comments;
23
+ DROP TABLE authors;
24
+ DROP TABLE tasks;
25
+ DROP TABLE categories;
26
+ DROP TABLE categories_posts;
27
+ DROP TABLE fk_test_has_pk;
28
+ DROP TABLE fk_test_has_fk;
29
+ DROP TABLE keyboards;
30
+ DROP TABLE legacy_things;
31
+ DROP TABLE numeric_data;
32
+ DROP TABLE mixed_case_monkeys;
@@ -0,0 +1,284 @@
1
+ CREATE TABLE accounts (
2
+ id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
3
+ firm_id INT DEFAULT NULL,
4
+ credit_limit INT DEFAULT NULL,
5
+ PRIMARY KEY (id)
6
+ );
7
+ CREATE UNIQUE INDEX accounts_id_idx ON
8
+ accounts (id);
9
+
10
+ CREATE TABLE funny_jokes (
11
+ id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
12
+ name VARCHAR(50) DEFAULT NULL,
13
+ PRIMARY KEY (id)
14
+ );
15
+ CREATE UNIQUE INDEX funny_jokes_id_idx ON
16
+ funny_jokes (id);
17
+
18
+ CREATE TABLE companies (
19
+ id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
20
+ type VARCHAR(50) DEFAULT NULL,
21
+ ruby_type VARCHAR(50) DEFAULT NULL,
22
+ firm_id INT DEFAULT NULL,
23
+ name VARCHAR(50) DEFAULT NULL,
24
+ client_of INT DEFAULT NULL,
25
+ rating INT DEFAULT 1,
26
+ PRIMARY KEY (id)
27
+ );
28
+ CREATE UNIQUE INDEX companies_id_idx ON
29
+ companies (id);
30
+
31
+ CREATE TABLE topics (
32
+ id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
33
+ title VARCHAR(255) DEFAULT NULL,
34
+ author_name VARCHAR(255) DEFAULT NULL,
35
+ author_email_address VARCHAR(255) DEFAULT NULL,
36
+ written_on TIMESTAMP DEFAULT NULL,
37
+ --bonus_time TIMESTAMP DEFAULT NULL,
38
+ bonus_time TIME DEFAULT NULL,
39
+ last_read DATE DEFAULT NULL,
40
+ content VARCHAR(3000),
41
+ approved SMALLINT DEFAULT 1,
42
+ replies_count INT DEFAULT 0,
43
+ parent_id INT DEFAULT NULL,
44
+ type VARCHAR(50) DEFAULT NULL,
45
+ PRIMARY KEY (id)
46
+ );
47
+ CREATE UNIQUE INDEX topics_id_idx ON
48
+ topics (id);
49
+
50
+ CREATE TABLE developers (
51
+ id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
52
+ name VARCHAR(100) DEFAULT NULL,
53
+ salary INT DEFAULT 70000,
54
+ created_at TIMESTAMP DEFAULT NULL,
55
+ updated_at TIMESTAMP DEFAULT NULL,
56
+ PRIMARY KEY (id)
57
+ );
58
+ CREATE UNIQUE INDEX developers_id_idx ON
59
+ developers (id);
60
+
61
+ CREATE TABLE projects (
62
+ id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
63
+ name VARCHAR(100) DEFAULT NULL,
64
+ type VARCHAR(255) DEFAULT NULL,
65
+ PRIMARY KEY (id)
66
+ );
67
+ CREATE UNIQUE INDEX projects_id_idx ON
68
+ projects (id);
69
+
70
+ CREATE TABLE developers_projects (
71
+ developer_id INT NOT NULL,
72
+ project_id INT NOT NULL,
73
+ joined_on DATE DEFAULT NULL,
74
+ access_level SMALLINT DEFAULT 1
75
+ );
76
+
77
+ CREATE TABLE orders (
78
+ id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
79
+ name VARCHAR(100) DEFAULT NULL,
80
+ billing_customer_id INT DEFAULT NULL,
81
+ shipping_customer_id INT DEFAULT NULL,
82
+ PRIMARY KEY (id)
83
+ );
84
+ CREATE UNIQUE INDEX orders_idx ON
85
+ orders (id);
86
+
87
+ CREATE TABLE customers (
88
+ id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
89
+ name VARCHAR(100) DEFAULT NULL,
90
+ balance INT DEFAULT 0,
91
+ address_street VARCHAR(100) DEFAULT NULL,
92
+ address_city VARCHAR(100) DEFAULT NULL,
93
+ address_country VARCHAR(100) DEFAULT NULL,
94
+ gps_location VARCHAR(100) DEFAULT NULL,
95
+ PRIMARY KEY (id)
96
+ );
97
+ CREATE UNIQUE INDEX customers_id_idx ON
98
+ customers (id);
99
+
100
+ CREATE TABLE movies (
101
+ movieid INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
102
+ name VARCHAR(100) DEFAULT NULL,
103
+ PRIMARY KEY (movieid)
104
+ );
105
+ CREATE UNIQUE INDEX movies_id_idx ON
106
+ movies (movieid);
107
+
108
+ CREATE TABLE subscribers (
109
+ nick VARCHAR(100) NOT NULL,
110
+ name VARCHAR(100) DEFAULT NULL,
111
+ PRIMARY KEY (nick)
112
+ );
113
+ CREATE UNIQUE INDEX subscribers_id_idx ON
114
+ subscribers (nick);
115
+
116
+ CREATE TABLE booleantests (
117
+ id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
118
+ value INT DEFAULT NULL,
119
+ PRIMARY KEY (id)
120
+ );
121
+ CREATE UNIQUE INDEX booleantest_id_idx ON
122
+ booleantests (id);
123
+
124
+ CREATE TABLE auto_id_tests (
125
+ auto_id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
126
+ value INT DEFAULT NULL,
127
+ PRIMARY KEY (auto_id)
128
+ );
129
+ CREATE UNIQUE INDEX auto_id_tests_idx ON
130
+ auto_id_tests (auto_id);
131
+
132
+ CREATE TABLE entrants (
133
+ id INT NOT NULL PRIMARY KEY,
134
+ name VARCHAR(255) NOT NULL,
135
+ course_id INT NOT NULL
136
+ );
137
+ CREATE UNIQUE INDEX entrants_id_idx ON
138
+ entrants (id);
139
+
140
+ CREATE TABLE colnametests (
141
+ id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
142
+ references INT NOT NULL,
143
+ PRIMARY KEY (id)
144
+ );
145
+ CREATE UNIQUE INDEX colnametest_id_idx ON
146
+ colnametests (id);
147
+
148
+ CREATE TABLE mixins (
149
+ id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
150
+ parent_id INT DEFAULT NULL,
151
+ pos INT DEFAULT NULL,
152
+ created_at TIMESTAMP DEFAULT NULL,
153
+ updated_at TIMESTAMP DEFAULT NULL,
154
+ lft INT DEFAULT NULL,
155
+ rgt INT DEFAULT NULL,
156
+ root_id INT DEFAULT NULL,
157
+ type VARCHAR(40) DEFAULT NULL,
158
+ PRIMARY KEY (id)
159
+ );
160
+ CREATE UNIQUE INDEX mixins_id_idx ON
161
+ mixins (id);
162
+
163
+ CREATE TABLE people (
164
+ id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
165
+ first_name VARCHAR(40) NOT NULL,
166
+ lock_version INT DEFAULT 0,
167
+ PRIMARY KEY (id)
168
+ );
169
+ CREATE UNIQUE INDEX people_id_idx ON
170
+ people (id);
171
+
172
+ CREATE TABLE readers (
173
+ id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
174
+ post_id INT NOT NULL,
175
+ person_id INT NOT NULL,
176
+ PRIMARY KEY (id)
177
+ );
178
+ CREATE UNIQUE INDEX readers_id_idx ON
179
+ readers (id);
180
+
181
+ CREATE TABLE binaries (
182
+ id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
183
+ data BLOB(5000000),
184
+ PRIMARY KEY (id)
185
+ );
186
+ CREATE UNIQUE INDEX binaries_id_idx ON
187
+ binaries (id);
188
+ --CREATE LOB TABLESPACE datalob;
189
+ --CREATE AUXILIARY TABLE data_aux IN datalob
190
+ --STORES binaries COLUMN data;
191
+ --CREATE UNIQUE INDEX lob_data_idx ON data_aux;
192
+
193
+ CREATE TABLE computers (
194
+ id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
195
+ developer INT NOT NULL,
196
+ extendedWarranty INT NOT NULL
197
+ );
198
+
199
+ CREATE TABLE posts (
200
+ id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
201
+ author_id INT DEFAULT NULL,
202
+ title VARCHAR(255) DEFAULT NULL,
203
+ type VARCHAR(255) DEFAULT NULL,
204
+ body VARCHAR(3000) DEFAULT NULL
205
+ );
206
+
207
+ CREATE TABLE comments (
208
+ id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
209
+ post_id INT DEFAULT NULL,
210
+ type VARCHAR(255) DEFAULT NULL,
211
+ body VARCHAR(3000) DEFAULT NULL
212
+ );
213
+
214
+ CREATE TABLE authors (
215
+ id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
216
+ name VARCHAR(255) DEFAULT NULL
217
+ );
218
+
219
+ CREATE TABLE tasks (
220
+ id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
221
+ starting TIMESTAMP DEFAULT NULL,
222
+ ending TIMESTAMP DEFAULT NULL
223
+ );
224
+
225
+ CREATE TABLE categories (
226
+ id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
227
+ name VARCHAR(255) NOT NULL,
228
+ type VARCHAR(40) DEFAULT NULL
229
+ );
230
+
231
+ CREATE TABLE categories_posts (
232
+ category_id INT NOT NULL,
233
+ post_id INT NOT NULL
234
+ );
235
+
236
+ CREATE TABLE keyboards (
237
+ key_number INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
238
+ name VARCHAR(255)
239
+ );
240
+
241
+ CREATE TABLE fk_test_has_pk (
242
+ id INT NOT NULL PRIMARY KEY
243
+ );
244
+ CREATE UNIQUE INDEX fk_test_has_id_idx ON
245
+ fk_test_has_pk (id);
246
+
247
+ CREATE TABLE fk_test_has_fk (
248
+ id INT NOT NULL PRIMARY KEY,
249
+ fk_id INT NOT NULL,
250
+
251
+ FOREIGN KEY (fk_id) REFERENCES fk_test_has_pk(id)
252
+ );
253
+ CREATE UNIQUE INDEX fk_test_has_fk_idx ON
254
+ fk_test_has_fk (id);
255
+
256
+ --This table has an altered lock_version column name
257
+ CREATE TABLE legacy_things (
258
+ id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
259
+ tps_report_number INT DEFAULT NULL,
260
+ version INT DEFAULT 0,
261
+ PRIMARY KEY (id)
262
+ );
263
+ CREATE UNIQUE INDEX legacy_thin_id_idx ON
264
+ legacy_things (id);
265
+
266
+ CREATE TABLE numeric_data (
267
+ id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
268
+ bank_balance DECIMAL(10,2),
269
+ big_bank_balance DECIMAL(15,2),
270
+ world_population DECIMAL(10),
271
+ my_house_population DECIMAL(2),
272
+ decimal_number_with_default DECIMAL(3,2) DEFAULT 2.78
273
+ );
274
+ CREATE UNIQUE INDEX numeric_data_idx ON
275
+ numeric_data (id);
276
+
277
+ CREATE TABLE mixed_case_monkeys (
278
+ monkeyID INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100),
279
+ fleaCount INT DEFAULT 0,
280
+ PRIMARY KEY (monkeyID)
281
+ );
282
+
283
+ CREATE UNIQUE INDEX mixed_monkeys_idx ON
284
+ mixed_case_monkeys (monkeyID);
@@ -0,0 +1,2 @@
1
+ DROP TABLE courses;
2
+
@@ -0,0 +1,7 @@
1
+ CREATE TABLE courses (
2
+ id INT NOT NULL PRIMARY KEY,
3
+ name VARCHAR(255) NOT NULL
4
+ );
5
+ CREATE UNIQUE INDEX courses_id_idx ON
6
+ courses (id);
7
+
@@ -0,0 +1,190 @@
1
+ require 'abstract_unit'
2
+ require 'fixtures/person'
3
+ require 'fixtures/legacy_thing'
4
+
5
+ class LockWithoutDefault < ActiveRecord::Base; end
6
+
7
+ class LockWithCustomColumnWithoutDefault < ActiveRecord::Base
8
+ set_table_name :lock_without_defaults_cust
9
+ set_locking_column :custom_lock_version
10
+ end
11
+
12
+ class OptimisticLockingTest < Test::Unit::TestCase
13
+ fixtures :people, :legacy_things
14
+
15
+ def test_lock_existing
16
+ p1 = Person.find(1)
17
+ p2 = Person.find(1)
18
+ assert_equal 0, p1.lock_version
19
+ assert_equal 0, p2.lock_version
20
+
21
+ p1.save!
22
+ assert_equal 1, p1.lock_version
23
+ assert_equal 0, p2.lock_version
24
+
25
+ assert_raises(ActiveRecord::StaleObjectError) { p2.save! }
26
+ end
27
+
28
+ def test_lock_new
29
+ p1 = Person.new(:first_name => 'anika')
30
+ assert_equal 0, p1.lock_version
31
+
32
+ p1.save!
33
+ p2 = Person.find(p1.id)
34
+ assert_equal 0, p1.lock_version
35
+ assert_equal 0, p2.lock_version
36
+
37
+ p1.save!
38
+ assert_equal 1, p1.lock_version
39
+ assert_equal 0, p2.lock_version
40
+
41
+ assert_raises(ActiveRecord::StaleObjectError) { p2.save! }
42
+ end
43
+
44
+ def test_lock_column_name_existing
45
+ t1 = LegacyThing.find(1)
46
+ t2 = LegacyThing.find(1)
47
+ assert_equal 0, t1.version
48
+ assert_equal 0, t2.version
49
+
50
+ t1.save!
51
+ assert_equal 1, t1.version
52
+ assert_equal 0, t2.version
53
+
54
+ assert_raises(ActiveRecord::StaleObjectError) { t2.save! }
55
+ end
56
+
57
+ def test_lock_column_is_mass_assignable
58
+ p1 = Person.create(:first_name => 'bianca')
59
+ assert_equal 0, p1.lock_version
60
+ assert_equal p1.lock_version, Person.new(p1.attributes).lock_version
61
+
62
+ p1.save!
63
+ assert_equal 1, p1.lock_version
64
+ assert_equal p1.lock_version, Person.new(p1.attributes).lock_version
65
+ end
66
+
67
+ def test_lock_without_default_sets_version_to_zero
68
+ t1 = LockWithoutDefault.new
69
+ assert_equal 0, t1.lock_version
70
+ end
71
+
72
+ def test_lock_with_custom_column_without_default_sets_version_to_zero
73
+ t1 = LockWithCustomColumnWithoutDefault.new
74
+ assert_equal 0, t1.custom_lock_version
75
+ end
76
+ end
77
+
78
+
79
+ # TODO: test against the generated SQL since testing locking behavior itself
80
+ # is so cumbersome. Will deadlock Ruby threads if the underlying db.execute
81
+ # blocks, so separate script called by Kernel#system is needed.
82
+ # (See exec vs. async_exec in the PostgreSQL adapter.)
83
+
84
+ # TODO: The SQL Server and Sybase adapters currently have no support for pessimistic locking
85
+
86
+ unless current_adapter?(:SQLServerAdapter, :SybaseAdapter)
87
+ class PessimisticLockingTest < Test::Unit::TestCase
88
+ self.use_transactional_fixtures = false
89
+ fixtures :people, :readers
90
+
91
+ def setup
92
+ # Avoid introspection queries during tests.
93
+ Person.columns; Reader.columns
94
+
95
+ @allow_concurrency = ActiveRecord::Base.allow_concurrency
96
+ ActiveRecord::Base.allow_concurrency = true
97
+ end
98
+
99
+ def teardown
100
+ ActiveRecord::Base.allow_concurrency = @allow_concurrency
101
+ end
102
+
103
+ # Test typical find.
104
+ def test_sane_find_with_lock
105
+ assert_nothing_raised do
106
+ Person.transaction do
107
+ Person.find 1, :lock => true
108
+ end
109
+ end
110
+ end
111
+
112
+ # Test scoped lock.
113
+ def test_sane_find_with_scoped_lock
114
+ assert_nothing_raised do
115
+ Person.transaction do
116
+ Person.with_scope(:find => { :lock => true }) do
117
+ Person.find 1
118
+ end
119
+ end
120
+ end
121
+ end
122
+
123
+ # PostgreSQL protests SELECT ... FOR UPDATE on an outer join.
124
+ unless current_adapter?(:PostgreSQLAdapter, :IBM_DBAdapter)
125
+ # Test locked eager find.
126
+ def test_eager_find_with_lock
127
+ assert_nothing_raised do
128
+ Person.transaction do
129
+ Person.find 1, :include => :readers, :lock => true
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ # Locking a record reloads it.
136
+ def test_sane_lock_method
137
+ assert_nothing_raised do
138
+ Person.transaction do
139
+ person = Person.find 1
140
+ old, person.first_name = person.first_name, 'fooman'
141
+ person.lock!
142
+ assert_equal old, person.first_name
143
+ end
144
+ end
145
+ end
146
+
147
+ if current_adapter?(:PostgreSQLAdapter, :OracleAdapter)
148
+ def test_no_locks_no_wait
149
+ first, second = duel { Person.find 1 }
150
+ assert first.end > second.end
151
+ end
152
+
153
+ def test_second_lock_waits
154
+ assert [0.2, 1, 5].any? { |zzz|
155
+ first, second = duel(zzz) { Person.find 1, :lock => true }
156
+ second.end > first.end
157
+ }
158
+ end
159
+
160
+ protected
161
+ def duel(zzz = 5)
162
+ t0, t1, t2, t3 = nil, nil, nil, nil
163
+
164
+ a = Thread.new do
165
+ t0 = Time.now
166
+ Person.transaction do
167
+ yield
168
+ sleep zzz # block thread 2 for zzz seconds
169
+ end
170
+ t1 = Time.now
171
+ end
172
+
173
+ b = Thread.new do
174
+ sleep zzz / 2.0 # ensure thread 1 tx starts first
175
+ t2 = Time.now
176
+ Person.transaction { yield }
177
+ t3 = Time.now
178
+ end
179
+
180
+ a.join
181
+ b.join
182
+
183
+ assert t1 > t0 + zzz
184
+ assert t2 > t0
185
+ assert t3 > t2
186
+ [t0.to_f..t1.to_f, t2.to_f..t3.to_f]
187
+ end
188
+ end
189
+ end
190
+ end