partitioned 0.8.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.
Files changed (95) hide show
  1. data/Gemfile +17 -0
  2. data/LICENSE +30 -0
  3. data/PARTITIONING_EXPLAINED.txt +351 -0
  4. data/README +111 -0
  5. data/Rakefile +27 -0
  6. data/examples/README +23 -0
  7. data/examples/company_id.rb +417 -0
  8. data/examples/company_id_and_created_at.rb +689 -0
  9. data/examples/created_at.rb +590 -0
  10. data/examples/created_at_referencing_awards.rb +1000 -0
  11. data/examples/id.rb +475 -0
  12. data/examples/lib/by_company_id.rb +11 -0
  13. data/examples/lib/command_line_tool_mixin.rb +71 -0
  14. data/examples/lib/company.rb +29 -0
  15. data/examples/lib/get_options.rb +44 -0
  16. data/examples/lib/roman.rb +41 -0
  17. data/examples/start_date.rb +621 -0
  18. data/init.rb +1 -0
  19. data/lib/monkey_patch_activerecord.rb +92 -0
  20. data/lib/monkey_patch_postgres.rb +73 -0
  21. data/lib/partitioned.rb +26 -0
  22. data/lib/partitioned/active_record_overrides.rb +34 -0
  23. data/lib/partitioned/bulk_methods_mixin.rb +288 -0
  24. data/lib/partitioned/by_created_at.rb +13 -0
  25. data/lib/partitioned/by_foreign_key.rb +21 -0
  26. data/lib/partitioned/by_id.rb +35 -0
  27. data/lib/partitioned/by_integer_field.rb +32 -0
  28. data/lib/partitioned/by_monthly_time_field.rb +23 -0
  29. data/lib/partitioned/by_time_field.rb +65 -0
  30. data/lib/partitioned/by_weekly_time_field.rb +30 -0
  31. data/lib/partitioned/multi_level.rb +20 -0
  32. data/lib/partitioned/multi_level/configurator/data.rb +14 -0
  33. data/lib/partitioned/multi_level/configurator/dsl.rb +32 -0
  34. data/lib/partitioned/multi_level/configurator/reader.rb +162 -0
  35. data/lib/partitioned/multi_level/partition_manager.rb +47 -0
  36. data/lib/partitioned/partitioned_base.rb +354 -0
  37. data/lib/partitioned/partitioned_base/configurator.rb +6 -0
  38. data/lib/partitioned/partitioned_base/configurator/data.rb +62 -0
  39. data/lib/partitioned/partitioned_base/configurator/dsl.rb +628 -0
  40. data/lib/partitioned/partitioned_base/configurator/reader.rb +209 -0
  41. data/lib/partitioned/partitioned_base/partition_manager.rb +138 -0
  42. data/lib/partitioned/partitioned_base/sql_adapter.rb +286 -0
  43. data/lib/partitioned/version.rb +3 -0
  44. data/lib/tasks/desirable_tasks.rake +4 -0
  45. data/partitioned.gemspec +21 -0
  46. data/spec/dummy/.rspec +1 -0
  47. data/spec/dummy/README.rdoc +261 -0
  48. data/spec/dummy/Rakefile +7 -0
  49. data/spec/dummy/app/assets/javascripts/application.js +9 -0
  50. data/spec/dummy/app/assets/stylesheets/application.css +7 -0
  51. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  52. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  53. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  54. data/spec/dummy/config.ru +4 -0
  55. data/spec/dummy/config/application.rb +51 -0
  56. data/spec/dummy/config/boot.rb +10 -0
  57. data/spec/dummy/config/database.yml +32 -0
  58. data/spec/dummy/config/environment.rb +5 -0
  59. data/spec/dummy/config/environments/development.rb +30 -0
  60. data/spec/dummy/config/environments/production.rb +60 -0
  61. data/spec/dummy/config/environments/test.rb +39 -0
  62. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  63. data/spec/dummy/config/initializers/inflections.rb +10 -0
  64. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  65. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  66. data/spec/dummy/config/initializers/session_store.rb +8 -0
  67. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  68. data/spec/dummy/config/locales/en.yml +5 -0
  69. data/spec/dummy/config/routes.rb +58 -0
  70. data/spec/dummy/public/404.html +26 -0
  71. data/spec/dummy/public/422.html +26 -0
  72. data/spec/dummy/public/500.html +26 -0
  73. data/spec/dummy/public/favicon.ico +0 -0
  74. data/spec/dummy/script/rails +6 -0
  75. data/spec/dummy/spec/spec_helper.rb +27 -0
  76. data/spec/monkey_patch_posgres_spec.rb +176 -0
  77. data/spec/partitioned/bulk_methods_mixin_spec.rb +512 -0
  78. data/spec/partitioned/by_created_at_spec.rb +62 -0
  79. data/spec/partitioned/by_foreign_key_spec.rb +95 -0
  80. data/spec/partitioned/by_id_spec.rb +97 -0
  81. data/spec/partitioned/by_integer_field_spec.rb +143 -0
  82. data/spec/partitioned/by_monthly_time_field_spec.rb +100 -0
  83. data/spec/partitioned/by_time_field_spec.rb +182 -0
  84. data/spec/partitioned/by_weekly_time_field_spec.rb +100 -0
  85. data/spec/partitioned/multi_level/configurator/dsl_spec.rb +88 -0
  86. data/spec/partitioned/multi_level/configurator/reader_spec.rb +147 -0
  87. data/spec/partitioned/partitioned_base/configurator/dsl_spec.rb +459 -0
  88. data/spec/partitioned/partitioned_base/configurator/reader_spec.rb +513 -0
  89. data/spec/partitioned/partitioned_base/sql_adapter_spec.rb +204 -0
  90. data/spec/partitioned/partitioned_base_spec.rb +173 -0
  91. data/spec/spec_helper.rb +32 -0
  92. data/spec/support/shared_example_spec_helper_for_integer_key.rb +137 -0
  93. data/spec/support/shared_example_spec_helper_for_time_key.rb +147 -0
  94. data/spec/support/tables_spec_helper.rb +47 -0
  95. metadata +250 -0
@@ -0,0 +1,512 @@
1
+ require 'spec_helper'
2
+ require "#{File.dirname(__FILE__)}/../support/tables_spec_helper"
3
+
4
+ module Partitioned
5
+ module BulkMethodsMixin
6
+ describe "BulkMethodsMixin" do
7
+ include TablesSpecHelper
8
+
9
+ before do
10
+ class Employee < ActiveRecord::Base
11
+ include ActiveRecordOverrides
12
+ extend Partitioned::BulkMethodsMixin
13
+ end
14
+ create_tables
15
+ end
16
+
17
+ describe "create_many" do
18
+
19
+ context "when call method with empty rows" do
20
+ it "returns empty array" do
21
+ Employee.create_many("").should == []
22
+ end
23
+ end # when call method with empty rows
24
+
25
+ context "when try to create records with the given id" do
26
+ it "records created" do
27
+ Employee.create_many([{ :id => Employee.connection.next_sequence_value(Employee.sequence_name),
28
+ :name => 'Keith',
29
+ :company_id => 2
30
+ },
31
+ { :id => Employee.connection.next_sequence_value(Employee.sequence_name),
32
+ :name => 'Mike',
33
+ :company_id => 3
34
+ },
35
+ { :id => Employee.connection.next_sequence_value(Employee.sequence_name),
36
+ :name => 'Alex',
37
+ :company_id => 1
38
+ }])
39
+ Employee.all.map{ |r| r.name }.should == ["Keith", "Mike", "Alex"]
40
+ end
41
+ end # when try to create records with the given id
42
+
43
+ context "when try to create records without the given id" do
44
+ it "records created" do
45
+ Employee.create_many([{ :name => 'Keith', :company_id => 2 },
46
+ { :name => 'Mike', :company_id => 3 },
47
+ { :name => 'Alex', :company_id => 1 }])
48
+ Employee.all.map{ |r| r.name }.should == ["Keith", "Mike", "Alex"]
49
+ end
50
+ end # when try to create records without the given id
51
+
52
+ context "when try to create records with a mixture of given ids and non-given ids" do
53
+ it "records created" do
54
+ Employee.create_many([{ :name => 'Keith', :company_id => 2 },
55
+ { :id => Employee.connection.next_sequence_value(Employee.sequence_name),
56
+ :name => 'Mike',
57
+ :company_id => 3
58
+ },
59
+ { :name => 'Mark', :company_id => 1 },
60
+ { :id => Employee.connection.next_sequence_value(Employee.sequence_name),
61
+ :name => 'Alex',
62
+ :company_id => 1
63
+ }])
64
+ Employee.all.map{ |r| r.name }.should == ["Keith", "Mike", "Mark", "Alex"]
65
+ end
66
+ end # when try to create records with a mixture of given ids and non-given ids
67
+
68
+ context "when try to create records with the given created_at" do
69
+ it "records created" do
70
+ Employee.create_many([{ :name => 'Keith',
71
+ :company_id => 2,
72
+ :created_at => Time.zone.parse('2012-01-02')
73
+ },
74
+ { :name => 'Mike',
75
+ :company_id => 3,
76
+ :created_at => Time.zone.parse('2012-01-03')
77
+ },
78
+ { :name => 'Alex',
79
+ :company_id => 1,
80
+ :created_at => Time.zone.parse('2012-01-04')
81
+ }])
82
+ Employee.all.map{ |r| r.created_at }.should == [
83
+ Time.zone.parse('2012-01-02'),
84
+ Time.zone.parse('2012-01-03'),
85
+ Time.zone.parse('2012-01-04')
86
+ ]
87
+ end
88
+ end # when try to create records with the given created_at
89
+
90
+ context "when try to create records without the given created_at" do
91
+ it "records created" do
92
+ Employee.create_many([{ :name => 'Keith', :company_id => 2 },
93
+ { :name => 'Mike', :company_id => 3 },
94
+ { :name => 'Alex', :company_id => 1 }])
95
+ Employee.all.each{ |r| r.created_at.between?(Time.now - 3.minute, Time.now + 3.minute) }.
96
+ should be_true
97
+ end
98
+ end # when try to create records without the given created_at
99
+
100
+ context "when try to create records without options" do
101
+ it "generates one insert queries" do
102
+ Employee.should_receive(:find_by_sql).once.and_return([])
103
+ Employee.create_many([{ :name => 'Keith', :company_id => 2 },
104
+ { :name => 'Alex', :company_id => 1 },
105
+ { :name => 'Mark', :company_id => 2 },
106
+ { :name => 'Phil', :company_id => 3 }])
107
+ end
108
+ end # when try to create records without options
109
+
110
+ context "when call method with option 'slice_size' equal 2" do
111
+ it "generates two insert queries" do
112
+ Employee.should_receive(:find_by_sql).twice.and_return([])
113
+ Employee.create_many([{ :name => 'Keith', :company_id => 2 },
114
+ { :name => 'Alex', :company_id => 1 },
115
+ { :name => 'Mark', :company_id => 2 },
116
+ { :name => 'Phil', :company_id => 3 }],
117
+ { :slice_size => 2})
118
+ end
119
+ end # when call method with option 'slice_size' equal 2
120
+
121
+ context "when create two records with options 'returning' equal id" do
122
+ it "returns last records id" do
123
+ Employee.create_many([{ :name => 'Keith', :company_id => 2 },
124
+ { :name => 'Alex', :company_id => 3 }],
125
+ { :returning => [:id] }).
126
+ last.id.should == 2
127
+ end
128
+ end # when create two records with options 'returning' equal id
129
+
130
+ context "when try to create two records and doesn't
131
+ the same number of keys and options check_consistency equal false" do
132
+ it "records created, last salary is nil" do
133
+ Employee.create_many([{ :company_id => 2, :name => 'Keith', :salary => 1002 },
134
+ { :name => 'Alex', :company_id => 3 }],
135
+ { :check_consistency => false })
136
+ Employee.find(2).salary.should == nil
137
+ end
138
+ end # when try to create two records and doesn't
139
+ # the same number of keys and options check_consistency equal false
140
+
141
+ context "when try to create two records and doesn't the same number of keys" do
142
+ it "raises BulkUploadDataInconsistent" do
143
+ lambda { Employee.create_many([{ :company_id => 2, :name => 'Keith', :salary => 1002 },
144
+ { :name => 'Alex', :company_id => 3}])
145
+ }.should raise_error(BulkUploadDataInconsistent)
146
+ end
147
+ end # when try to create two records and doesn't the same number of keys
148
+
149
+ context "when try to create records using partitioning" do
150
+
151
+ before do
152
+ Partitioned::BulkMethodsMixin.send(:remove_const, :Employee)
153
+ class Employee < ByForeignKey
154
+ belongs_to :company, :class_name => 'Company'
155
+
156
+ def self.partition_foreign_key
157
+ return :company_id
158
+ end
159
+
160
+ partitioned do |partition|
161
+ partition.index :id, :unique => true
162
+ partition.foreign_key :company_id
163
+ end
164
+ end # Employee
165
+ Employee.create_new_partition_tables(Employee.partition_generate_range(0, 4, 1))
166
+ end
167
+
168
+ after do
169
+ Partitioned::BulkMethodsMixin.send(:remove_const, :Employee)
170
+ end
171
+
172
+ it "returns records" do
173
+ Employee.create_many([{ :name => 'Keith', :company_id => 2 },
174
+ { :name => 'Alex', :company_id => 1 },
175
+ { :name => 'Phil', :company_id => 3 }])
176
+ Employee.from_partition(1).where(:id => 2).first.name.should == "Alex"
177
+ Employee.where(:id => 1, :company_id => 2).first.name.should == "Keith"
178
+ Employee.all.map{ |r| r.name }.should == ["Alex", "Keith", "Phil"]
179
+ end
180
+ end # when try to create records using partitioning
181
+
182
+ context "when try to create records in the table that has all the different sql types" do
183
+
184
+ before do
185
+ ActiveRecord::Base.connection.execute <<-SQL
186
+ ALTER TABLE employees ADD COLUMN test_string character varying;
187
+ ALTER TABLE employees ADD COLUMN test_float float;
188
+ ALTER TABLE employees ADD COLUMN test_decimal decimal;
189
+ ALTER TABLE employees ADD COLUMN test_time time;
190
+ ALTER TABLE employees ADD COLUMN test_time_string time;
191
+ ALTER TABLE employees ADD COLUMN test_date date;
192
+ ALTER TABLE employees ADD COLUMN test_date_string date;
193
+ ALTER TABLE employees ADD COLUMN test_bytea bytea;
194
+ ALTER TABLE employees ADD COLUMN test_boolean boolean;
195
+ ALTER TABLE employees ADD COLUMN test_xml xml;
196
+ ALTER TABLE employees ADD COLUMN test_tsvector tsvector;
197
+ SQL
198
+ Employee.reset_column_information
199
+ end
200
+
201
+ after do
202
+ ActiveRecord::Base.connection.reset!
203
+ end
204
+
205
+ context "non-null values" do
206
+ it "returns record with all sql types" do
207
+ lambda { Employee.create_many([{ :name => 'Keith',
208
+ :company_id => 2,
209
+ :created_at => Time.zone.parse('2012-12-21'),
210
+ :updated_at => '2012-12-21 00:00:00',
211
+ :test_string => "string",
212
+ :test_float => 12.34,
213
+ :test_decimal => 123456789101112,
214
+ :test_time => Time.now,
215
+ :test_time_string => '00:00:00',
216
+ :test_date => Date.parse('2012-12-21'),
217
+ :test_date_string => '2012-12-21',
218
+ :test_bytea => "text".bytes.to_a,
219
+ :test_boolean => false,
220
+ :test_xml => ["text"].to_xml,
221
+ :test_tsvector => "test string",
222
+ }]) }.should_not raise_error
223
+ Employee.all.size.should == 1
224
+ end
225
+ end # non-null values
226
+
227
+ context "null values" do
228
+ it "returns record with all sql types" do
229
+ lambda { Employee.create_many([{ :name => 'Keith',
230
+ :company_id => 2,
231
+ :created_at => nil,
232
+ :updated_at => nil,
233
+ :salary => nil,
234
+ :test_string => nil,
235
+ :test_float => nil,
236
+ :test_decimal => nil,
237
+ :test_time => nil,
238
+ :test_time_string => nil,
239
+ :test_date => nil,
240
+ :test_date_string => nil,
241
+ :test_bytea => nil,
242
+ :test_boolean => nil,
243
+ :test_xml => nil,
244
+ :test_tsvector => nil,
245
+ }]) }.should_not raise_error
246
+ Employee.all.size.should == 1
247
+ end
248
+ end # null values
249
+
250
+ end # when try to create records in the table that has all the different sql types
251
+
252
+ end # create_many
253
+
254
+ describe "update_many" do
255
+
256
+ before do
257
+ Employee.create_many([{ :name => 'Keith', :company_id => 2 },
258
+ { :name => 'Alex', :company_id => 1 },
259
+ { :name => 'Mark', :company_id => 2 },
260
+ { :name => 'Phil', :company_id => 3 }])
261
+ end
262
+
263
+ context "when call method with empty rows" do
264
+ it "returns empty array" do
265
+ Employee.update_many("").should == []
266
+ end
267
+ end # when call method with empty rows
268
+
269
+ context "when try to update records without options" do
270
+
271
+ context "input parameters is hash" do
272
+ it "records updated" do
273
+ Employee.update_many({ { :id => 1 } => {
274
+ :name => 'Elvis'
275
+ },
276
+ { :id => 2 } => {
277
+ :name => 'Freddi'
278
+ } })
279
+ Employee.find(1).name.should == "Elvis"
280
+ Employee.find(2).name.should == "Freddi"
281
+ end
282
+ end # input parameters is hash
283
+
284
+ context "input parameters is array" do
285
+ it "records updated" do
286
+ Employee.update_many([{ :id => 1,
287
+ :name => 'Elvis'
288
+ },
289
+ { :id => 2,
290
+ :name => 'Freddi'
291
+ }])
292
+ Employee.find(1).name.should == "Elvis"
293
+ Employee.find(2).name.should == "Freddi"
294
+ end
295
+ end # input parameters is array
296
+
297
+ context "when try to update two records and doesn't the same number of keys" do
298
+ it "raises BulkUploadDataInconsistent" do
299
+ lambda { Employee.update_many([{ :id => 1, :name => 'Elvis', :salary => 1002 },
300
+ { :name => 'Freddi', :id => 2}])
301
+ }.should raise_error(BulkUploadDataInconsistent)
302
+ end
303
+ end # when try to update two records and doesn't the same number of keys
304
+
305
+ context "when try to update records with the given updated_at" do
306
+ it "records created" do
307
+ Employee.update_many([{ :id => 1,
308
+ :updated_at => Time.zone.parse('2012-01-02')
309
+ },
310
+ { :id => 2,
311
+ :updated_at => Time.zone.parse('2012-01-03')
312
+ },
313
+ { :id => 3,
314
+ :updated_at => Time.zone.parse('2012-01-04')
315
+ },
316
+ { :id => 4,
317
+ :updated_at => Time.zone.parse('2012-01-05')
318
+ }])
319
+ Employee.all.map{ |r| r.updated_at }.should == [
320
+ Time.zone.parse('2012-01-02'),
321
+ Time.zone.parse('2012-01-03'),
322
+ Time.zone.parse('2012-01-04'),
323
+ Time.zone.parse('2012-01-05')
324
+ ]
325
+ end
326
+ end # when try to update records with the given updated_at
327
+
328
+ end # when try to update records without options
329
+
330
+ context "when call method with option :slice_size set is default" do
331
+ it "generates one insert queries" do
332
+ Employee.should_receive(:find_by_sql).once.and_return([])
333
+ Employee.update_many([{ :id => 1, :name => 'Elvis' },
334
+ { :id => 2, :name => 'Freddi'},
335
+ { :id => 3, :name => 'Patric'},
336
+ { :id => 4, :name => 'Jane'}])
337
+ end
338
+ end # when call method with option :slice_size set is default
339
+
340
+
341
+ context "when call method with option :slice_size = 2" do
342
+ it "generates two insert queries" do
343
+ Employee.should_receive(:find_by_sql).twice.and_return([])
344
+ Employee.update_many([{ :id => 1, :name => 'Elvis' },
345
+ { :id => 2, :name => 'Freddi'},
346
+ { :id => 3, :name => 'Patric'},
347
+ { :id => 4, :name => 'Jane'}],
348
+ { :slice_size => 2})
349
+ end
350
+ end # when call method with option :slice_size = 2
351
+
352
+ context "when try to update two records and doesn't
353
+ the same number of keys and options check_consistency equal false" do
354
+ it "raises ActiveRecord::StatementInvalid" do
355
+ lambda {
356
+ Employee.update_many([{ :id => 1, :name => 'Elvis', :salary => 1002 },
357
+ { :name => 'Freddi', :id => 2}],
358
+ { :check_consistency => false })
359
+ }.should raise_error(ActiveRecord::StatementInvalid)
360
+ end
361
+ end # when try to update two records and doesn't
362
+ # the same number of keys and options check_consistency equal false
363
+
364
+ context "when update two records with options 'returning' equal :name" do
365
+ it "returns last records name" do
366
+ Employee.update_many([{ :id => 1, :name => 'Elvis' },
367
+ { :id => 2, :name => 'Freddi'}],
368
+ { :returning => [:name] }).
369
+ last.name.should == 'Freddi'
370
+ end
371
+ end # when update two records with options 'returning' equal :name
372
+
373
+ context "when update method with options :set_array equal 'salary = datatable.salary'" do
374
+ it "updates only salary column" do
375
+ Employee.update_many([{ :id => 1, :name => 'Elvis', :salary => 12 },
376
+ { :id => 2, :name => 'Freddi',:salary => 22}],
377
+ { :set_array => '"salary = datatable.salary"' })
378
+ Employee.find(1).name.should_not == "Elvis"
379
+ Employee.find(1).salary.should == 12
380
+ Employee.find(2).name.should_not == "Freddi"
381
+ Employee.find(2).salary.should == 22
382
+ end
383
+ end # when update method with options :set_array equal 'salary = datatable.salary'
384
+
385
+ context "when update method with options :where" do
386
+ it "updates only name column, where salary equal input values" do
387
+ Employee.update_many([{ :id => 1, :name => 'Elvis', :salary => 12 },
388
+ { :id => 2, :name => 'Freddi',:salary => 22}],
389
+ { :where => '"#{table_name}.salary = datatable.salary"' })
390
+ Employee.find(1).name.should_not == "Elvis"
391
+ Employee.find(1).salary.should == 3
392
+ Employee.find(2).name.should_not == "Freddi"
393
+ Employee.find(2).salary.should == 3
394
+ end
395
+ end # when update method with options :where
396
+
397
+ context "when try to update records using partitioning" do
398
+
399
+ before do
400
+ drop_tables
401
+ create_tables
402
+ Partitioned::BulkMethodsMixin.send(:remove_const, :Employee)
403
+ class Employee < ByForeignKey
404
+ belongs_to :company, :class_name => 'Company'
405
+
406
+ def self.partition_foreign_key
407
+ return :company_id
408
+ end
409
+
410
+ partitioned do |partition|
411
+ partition.index :id, :unique => true
412
+ partition.foreign_key :company_id
413
+ end
414
+ end # Employee
415
+ Employee.create_new_partition_tables(Employee.partition_generate_range(0, 4, 1))
416
+ Employee.create_many([{ :name => 'Keith', :company_id => 2 },
417
+ { :name => 'Alex', :company_id => 1 },
418
+ { :name => 'Mark', :company_id => 3 }])
419
+ end
420
+
421
+ after do
422
+ Partitioned::BulkMethodsMixin.send(:remove_const, :Employee)
423
+ end
424
+
425
+ it "returns records" do
426
+ Employee.update_many({ { :company_id => 2, :id => 1 } => { :name => 'Indy' },
427
+ { :company_id => 1, :id => 2 } => { :name => 'Larry' },
428
+ { :company_id => 3, :id => 3 } => { :name => 'Filip' } })
429
+ Employee.from_partition(1).where(:id => 2).first.name.should == "Larry"
430
+ Employee.where(:id => 1, :company_id => 2).first.name.should == "Indy"
431
+ Employee.all.map{ |r| r.name }.should == ["Larry", "Indy", "Filip"]
432
+ end
433
+ end # when try to update records using partitioning
434
+
435
+ context "when try to update records in the table that has all the different sql types" do
436
+
437
+ before do
438
+ ActiveRecord::Base.connection.execute <<-SQL
439
+ ALTER TABLE employees ADD COLUMN test_string character varying;
440
+ ALTER TABLE employees ADD COLUMN test_float float;
441
+ ALTER TABLE employees ADD COLUMN test_decimal decimal;
442
+ ALTER TABLE employees ADD COLUMN test_time time;
443
+ ALTER TABLE employees ADD COLUMN test_time_string time;
444
+ ALTER TABLE employees ADD COLUMN test_date date;
445
+ ALTER TABLE employees ADD COLUMN test_date_string date;
446
+ ALTER TABLE employees ADD COLUMN test_bytea bytea;
447
+ ALTER TABLE employees ADD COLUMN test_boolean boolean;
448
+ ALTER TABLE employees ADD COLUMN test_xml xml;
449
+ ALTER TABLE employees ADD COLUMN test_tsvector tsvector;
450
+ SQL
451
+ Employee.reset_column_information
452
+ end
453
+
454
+ after do
455
+ ActiveRecord::Base.connection.reset!
456
+ end
457
+
458
+ context "non-null values" do
459
+ it "returns record with all sql types" do
460
+ lambda { Employee.update_many([{ :id => 1,
461
+ :name => 'Keith',
462
+ :company_id => 2,
463
+ :created_at => Time.zone.parse('2012-12-21'),
464
+ :updated_at => '2012-12-21 00:00:00',
465
+ :test_string => "string",
466
+ :test_float => 12.34,
467
+ :test_decimal => 123456789101112,
468
+ :test_time => Time.now,
469
+ :test_time_string => '00:00:00',
470
+ :test_date => Date.parse('2012-12-21'),
471
+ :test_date_string => '2012-12-21',
472
+ :test_bytea => "text".bytes.to_a,
473
+ :test_boolean => false,
474
+ :test_xml => ["text"].to_xml,
475
+ :test_tsvector => "test string",
476
+ }]) }.should_not raise_error
477
+ Employee.find(1).test_boolean.should == false
478
+ Employee.find(1).test_tsvector.should == "'string' 'test'"
479
+ end
480
+ end # non-null values
481
+
482
+ context "null values" do
483
+ it "returns record with all sql types" do
484
+ lambda { Employee.update_many([{ :id => 1,
485
+ :name => 'Keith',
486
+ :company_id => 2,
487
+ :updated_at => nil,
488
+ :salary => nil,
489
+ :test_string => nil,
490
+ :test_float => nil,
491
+ :test_decimal => nil,
492
+ :test_time => nil,
493
+ :test_time_string => nil,
494
+ :test_date => nil,
495
+ :test_date_string => nil,
496
+ :test_bytea => nil,
497
+ :test_boolean => nil,
498
+ :test_xml => nil,
499
+ :test_tsvector => nil,
500
+ }]) }.should_not raise_error
501
+ Employee.find(1).test_boolean.should == nil
502
+ Employee.find(1).test_tsvector.should == nil
503
+ end
504
+ end # null values
505
+
506
+ end # when try to update records in the table that has all the different sql types
507
+
508
+ end # update_many
509
+
510
+ end # BulkMethodsMixin
511
+ end # BulkMethodsMixin
512
+ end # Partitioned