ibm_db 0.9.5 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/CHANGES +5 -0
  2. data/README +63 -97
  3. data/ext/ibm_db.c +20 -4
  4. data/ext/ruby_ibm_db.h +10 -0
  5. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +2 -4
  6. data/test/{adapter_test.rb → cases/adapter_test.rb} +39 -14
  7. data/test/cases/associations/cascaded_eager_loading_test.rb +113 -0
  8. data/test/{associations → cases/associations}/eager_test.rb +231 -65
  9. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +686 -0
  10. data/test/cases/associations/join_model_test.rb +797 -0
  11. data/test/{base_test.rb → cases/base_test.rb} +605 -385
  12. data/test/cases/calculations_test.rb +275 -0
  13. data/test/cases/finder_test.rb +885 -0
  14. data/test/cases/fixtures_test.rb +630 -0
  15. data/test/{migration_test.rb → cases/migration_test.rb} +530 -146
  16. data/test/cases/query_cache_test.rb +127 -0
  17. data/test/cases/validations_test.rb +1509 -0
  18. data/test/connections/native_ibm_db/connection.rb +1 -1
  19. data/test/models/warehouse_thing.rb +5 -0
  20. data/test/schema/i5/ibm_db_specific_schema.rb +133 -0
  21. data/test/schema/ids/ibm_db_specific_schema.rb +136 -0
  22. data/test/schema/luw/ibm_db_specific_schema.rb +133 -0
  23. data/test/schema/schema.rb +432 -0
  24. data/test/schema/zOS/ibm_db_specific_schema.rb +204 -0
  25. metadata +29 -33
  26. data/test/associations_test.rb +0 -2151
  27. data/test/fixtures/db_definitions/i5/ibm_db.drop.sql +0 -33
  28. data/test/fixtures/db_definitions/i5/ibm_db.sql +0 -236
  29. data/test/fixtures/db_definitions/i5/ibm_db2.drop.sql +0 -2
  30. data/test/fixtures/db_definitions/i5/ibm_db2.sql +0 -5
  31. data/test/fixtures/db_definitions/ids/ibm_db.drop.sql +0 -33
  32. data/test/fixtures/db_definitions/ids/ibm_db.sql +0 -237
  33. data/test/fixtures/db_definitions/ids/ibm_db2.drop.sql +0 -2
  34. data/test/fixtures/db_definitions/ids/ibm_db2.sql +0 -5
  35. data/test/fixtures/db_definitions/luw/ibm_db.drop.sql +0 -33
  36. data/test/fixtures/db_definitions/luw/ibm_db.sql +0 -236
  37. data/test/fixtures/db_definitions/luw/ibm_db2.drop.sql +0 -2
  38. data/test/fixtures/db_definitions/luw/ibm_db2.sql +0 -5
  39. data/test/fixtures/db_definitions/schema.rb +0 -361
  40. data/test/fixtures/db_definitions/zOS/ibm_db.drop.sql +0 -33
  41. data/test/fixtures/db_definitions/zOS/ibm_db.sql +0 -288
  42. data/test/fixtures/db_definitions/zOS/ibm_db2.drop.sql +0 -2
  43. data/test/fixtures/db_definitions/zOS/ibm_db2.sql +0 -7
  44. data/test/locking_test.rb +0 -282
@@ -1,33 +0,0 @@
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;
33
- DROP TABLE minimalistics;
@@ -1,288 +0,0 @@
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 TIME 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);
285
-
286
- CREATE TABLE minimalistics (
287
- id INT GENERATED BY DEFAULT AS IDENTITY (START WITH 100)
288
- );
@@ -1,2 +0,0 @@
1
- DROP TABLE courses;
2
-
@@ -1,7 +0,0 @@
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
-
data/test/locking_test.rb DELETED
@@ -1,282 +0,0 @@
1
- require 'abstract_unit'
2
- require 'fixtures/person'
3
- require 'fixtures/reader'
4
- require 'fixtures/legacy_thing'
5
-
6
- class LockWithoutDefault < ActiveRecord::Base; end
7
-
8
- class LockWithCustomColumnWithoutDefault < ActiveRecord::Base
9
- set_table_name :lock_without_defaults_cust
10
- set_locking_column :custom_lock_version
11
- end
12
-
13
- class ReadonlyFirstNamePerson < Person
14
- attr_readonly :first_name
15
- end
16
-
17
- class IBMDBOptimisticLockingTest < Test::Unit::TestCase
18
- fixtures :people, :legacy_things
19
-
20
- # need to disable transactional fixtures, because otherwise the sqlite3
21
- # adapter (at least) chokes when we try and change the schema in the middle
22
- # of a test (see test_increment_counter_*).
23
- self.use_transactional_fixtures = false
24
-
25
- def test_lock_existing
26
- p1 = Person.find(1)
27
- p2 = Person.find(1)
28
- assert_equal 0, p1.lock_version
29
- assert_equal 0, p2.lock_version
30
-
31
- p1.save!
32
- assert_equal 1, p1.lock_version
33
- assert_equal 0, p2.lock_version
34
-
35
- assert_raises(ActiveRecord::StaleObjectError) { p2.save! }
36
- end
37
-
38
- def test_lock_repeating
39
- p1 = Person.find(1)
40
- p2 = Person.find(1)
41
- assert_equal 0, p1.lock_version
42
- assert_equal 0, p2.lock_version
43
-
44
- p1.save!
45
- assert_equal 1, p1.lock_version
46
- assert_equal 0, p2.lock_version
47
-
48
- assert_raises(ActiveRecord::StaleObjectError) { p2.save! }
49
- assert_raises(ActiveRecord::StaleObjectError) { p2.save! }
50
- end
51
-
52
- def test_lock_new
53
- p1 = Person.new(:first_name => 'anika')
54
- assert_equal 0, p1.lock_version
55
-
56
- p1.save!
57
- p2 = Person.find(p1.id)
58
- assert_equal 0, p1.lock_version
59
- assert_equal 0, p2.lock_version
60
-
61
- p1.save!
62
- assert_equal 1, p1.lock_version
63
- assert_equal 0, p2.lock_version
64
-
65
- assert_raises(ActiveRecord::StaleObjectError) { p2.save! }
66
- end
67
-
68
- def test_lock_new_with_nil
69
- p1 = Person.new(:first_name => 'anika')
70
- p1.save!
71
- p1.lock_version = nil # simulate bad fixture or column with no default
72
- p1.save!
73
- assert_equal 1, p1.lock_version
74
- end
75
-
76
-
77
- def test_lock_column_name_existing
78
- t1 = LegacyThing.find(1)
79
- t2 = LegacyThing.find(1)
80
- assert_equal 0, t1.version
81
- assert_equal 0, t2.version
82
-
83
- t1.save!
84
- assert_equal 1, t1.version
85
- assert_equal 0, t2.version
86
-
87
- assert_raises(ActiveRecord::StaleObjectError) { t2.save! }
88
- end
89
-
90
- def test_lock_column_is_mass_assignable
91
- p1 = Person.create(:first_name => 'bianca')
92
- assert_equal 0, p1.lock_version
93
- assert_equal p1.lock_version, Person.new(p1.attributes).lock_version
94
-
95
- p1.save!
96
- assert_equal 1, p1.lock_version
97
- assert_equal p1.lock_version, Person.new(p1.attributes).lock_version
98
- end
99
-
100
- def test_lock_without_default_sets_version_to_zero
101
- t1 = LockWithoutDefault.new
102
- assert_equal 0, t1.lock_version
103
- end
104
-
105
- def test_lock_with_custom_column_without_default_sets_version_to_zero
106
- t1 = LockWithCustomColumnWithoutDefault.new
107
- assert_equal 0, t1.custom_lock_version
108
- end
109
-
110
- def test_readonly_attributes
111
- assert_equal Set.new([ 'first_name' ]), ReadonlyFirstNamePerson.readonly_attributes
112
-
113
- p = ReadonlyFirstNamePerson.create(:first_name => "unchangeable name")
114
- p.reload
115
- assert_equal "unchangeable name", p.first_name
116
-
117
- p.update_attributes(:first_name => "changed name")
118
- p.reload
119
- assert_equal "unchangeable name", p.first_name
120
- end
121
-
122
- { :lock_version => Person, :custom_lock_version => LegacyThing }.each do |name, model|
123
- define_method("test_increment_counter_updates_#{name}") do
124
- counter_test model, 1 do |id|
125
- model.increment_counter :test_count, id
126
- end
127
- end
128
-
129
- define_method("test_decrement_counter_updates_#{name}") do
130
- counter_test model, -1 do |id|
131
- model.decrement_counter :test_count, id
132
- end
133
- end
134
-
135
- define_method("test_update_counters_updates_#{name}") do
136
- counter_test model, 1 do |id|
137
- model.update_counters id, :test_count => 1
138
- end
139
- end
140
- end
141
-
142
- private
143
-
144
- def add_counter_column_to(model)
145
- model.connection.add_column model.table_name, :test_count, :integer, :null => false, :default => 0
146
- model.reset_column_information
147
- # OpenBase does not set a value to existing rows when adding a not null default column
148
- model.update_all(:test_count => 0) if current_adapter?(:OpenBaseAdapter)
149
- end
150
-
151
- def remove_counter_column_from(model)
152
- model.connection.remove_column model.table_name, :test_count
153
- model.reset_column_information
154
- end
155
-
156
- def counter_test(model, expected_count)
157
- add_counter_column_to(model)
158
- object = model.find(:first)
159
- assert_equal 0, object.test_count
160
- assert_equal 0, object.send(model.locking_column)
161
- yield object.id
162
- object.reload
163
- assert_equal expected_count, object.test_count
164
- assert_equal 1, object.send(model.locking_column)
165
- ensure
166
- remove_counter_column_from(model)
167
- end
168
- end
169
-
170
-
171
- # TODO: test against the generated SQL since testing locking behavior itself
172
- # is so cumbersome. Will deadlock Ruby threads if the underlying db.execute
173
- # blocks, so separate script called by Kernel#system is needed.
174
- # (See exec vs. async_exec in the PostgreSQL adapter.)
175
-
176
- # TODO: The SQL Server, Sybase, and OpenBase adapters currently have no support for pessimistic locking
177
-
178
- unless current_adapter?(:SQLServerAdapter, :SybaseAdapter, :OpenBaseAdapter)
179
- class PessimisticLockingTest < Test::Unit::TestCase
180
- self.use_transactional_fixtures = false
181
- fixtures :people, :readers
182
-
183
- def setup
184
- # Avoid introspection queries during tests.
185
- Person.columns; Reader.columns
186
-
187
- @allow_concurrency = ActiveRecord::Base.allow_concurrency
188
- ActiveRecord::Base.allow_concurrency = true
189
- end
190
-
191
- def teardown
192
- ActiveRecord::Base.allow_concurrency = @allow_concurrency
193
- end
194
-
195
- # Test typical find.
196
- def test_sane_find_with_lock
197
- assert_nothing_raised do
198
- Person.transaction do
199
- Person.find 1, :lock => true
200
- end
201
- end
202
- end
203
-
204
- # Test scoped lock.
205
- def test_sane_find_with_scoped_lock
206
- assert_nothing_raised do
207
- Person.transaction do
208
- Person.with_scope(:find => { :lock => true }) do
209
- Person.find 1
210
- end
211
- end
212
- end
213
- end
214
-
215
- # PostgreSQL protests SELECT ... FOR UPDATE on an outer join.
216
- unless current_adapter?(:PostgreSQLAdapter, :IBM_DBAdapter)
217
- # Test locked eager find.
218
- def test_eager_find_with_lock
219
- assert_nothing_raised do
220
- Person.transaction do
221
- Person.find 1, :include => :readers, :lock => true
222
- end
223
- end
224
- end
225
- end
226
-
227
- # Locking a record reloads it.
228
- def test_sane_lock_method
229
- assert_nothing_raised do
230
- Person.transaction do
231
- person = Person.find 1
232
- old, person.first_name = person.first_name, 'fooman'
233
- person.lock!
234
- assert_equal old, person.first_name
235
- end
236
- end
237
- end
238
-
239
- if current_adapter?(:PostgreSQLAdapter, :OracleAdapter)
240
- def test_no_locks_no_wait
241
- first, second = duel { Person.find 1 }
242
- assert first.end > second.end
243
- end
244
-
245
- def test_second_lock_waits
246
- assert [0.2, 1, 5].any? { |zzz|
247
- first, second = duel(zzz) { Person.find 1, :lock => true }
248
- second.end > first.end
249
- }
250
- end
251
-
252
- protected
253
- def duel(zzz = 5)
254
- t0, t1, t2, t3 = nil, nil, nil, nil
255
-
256
- a = Thread.new do
257
- t0 = Time.now
258
- Person.transaction do
259
- yield
260
- sleep zzz # block thread 2 for zzz seconds
261
- end
262
- t1 = Time.now
263
- end
264
-
265
- b = Thread.new do
266
- sleep zzz / 2.0 # ensure thread 1 tx starts first
267
- t2 = Time.now
268
- Person.transaction { yield }
269
- t3 = Time.now
270
- end
271
-
272
- a.join
273
- b.join
274
-
275
- assert t1 > t0 + zzz
276
- assert t2 > t0
277
- assert t3 > t2
278
- [t0.to_f..t1.to_f, t2.to_f..t3.to_f]
279
- end
280
- end
281
- end
282
- end