partitioned 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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,590 @@
1
+ #!/usr/bin/env ../spec/dummy/script/rails runner
2
+ # if you use linux, please change previous line to the
3
+ # "#! ../spec/dummy/script/rails runner"
4
+
5
+ # Before running this example you should execute "bundle install" and "rake db:create".
6
+ # To run this example you should open 'example' directory and execute example with one of the following flags:
7
+ # -C cleanup data in database and exit;
8
+ # -F cleanup data in database before creating new data;
9
+ #
10
+ # For example:
11
+ # ./created_at.rb - F
12
+
13
+ # Initial data:
14
+ #
15
+ # Companies table is completed by four companies:
16
+ #
17
+ # create table companies (
18
+ # id serial not null primary key,
19
+ # created_at timestamp not null default now(),
20
+ # updated_at timestamp,
21
+ # name text null
22
+ # );
23
+ #
24
+ # insert into companies (created_at,id,name) values
25
+ # ('2012-03-13 13:26:52.184347',1,'Fluent Mobile, inc.'),
26
+ # ('2012-03-13 13:26:52.184347',2,'Fiksu, inc.'),
27
+ # ('2012-03-13 13:26:52.184347',3,'AppExchanger, inc.'),
28
+ # ('2012-03-13 13:26:52.184347',4,'FreeMyApps, inc.');
29
+ #
30
+ # id | created_at | updated_at | name
31
+ # ---+----------------------------+------------+---------------------
32
+ # 1 | 2012-03-11 13:26:52.184347 | | Fluent Mobile, inc.
33
+ # 2 | 2012-03-11 13:26:52.184347 | | Fiksu, inc.
34
+ # 3 | 2012-03-11 13:26:52.184347 | | AppExchanger, inc.
35
+ # 4 | 2012-03-11 13:26:52.184347 | | FreeMyApps, inc.
36
+ #
37
+ # Employees table is associated with companies table via key - id:
38
+ #
39
+ # create table employees (
40
+ # id serial not null primary key,
41
+ # created_at timestamp not null default now(),
42
+ # updated_at timestamp,
43
+ # name text not null,
44
+ # salary money not null,
45
+ # company_id integer not null
46
+ # );
47
+ #
48
+ # id | created_at | updated_at | name | salary | company_id
49
+ # ----+------------+------------+------+--------+------------
50
+ #
51
+ # Task:
52
+ #
53
+ # To increase the speed of requests to the database and to reduce the time
54
+ # of the request, need to split the Employees table to the partition tables.
55
+ # Break criterion is a created date(created_at).
56
+ #
57
+ # Implementation:
58
+ #
59
+ # Class Employee inherits from the abstract class ByCreatedAt,
60
+ # which supports partitioning.
61
+ #
62
+ # class Employee < Partitioned::ByCreatedAt
63
+ #
64
+ # Indicates a relationship to the companies table.
65
+ # belongs_to :company, :class_name => 'Company'
66
+ #
67
+ # Create a rules for each partition.
68
+ # Id is a unique index. Foreign key is company_id.
69
+ # This imposes a restriction on each of partition, that
70
+ # the column company_id associated with the table of companies
71
+ # and can not have values ​​that are not in the table companies.
72
+ # In this example, set up only 4 records in the table companies,
73
+ # so company_id can not be equal to 5 in any partition
74
+ # until it is an established company with id = 5.
75
+ #
76
+ # partitioned do |partition|
77
+ # partition.index :id, :unique => true
78
+ # partition.foreign_key :company_id
79
+ # end
80
+ # end
81
+ #
82
+ # Create a schema employees_partitions, within which to store all of our partitions:
83
+ #
84
+ # Employee.create_infrastructure
85
+ #
86
+ # Create a partition tables with increments of one week:
87
+ #
88
+ # dates = Employee.partition_generate_range(START_DATE, END_DATE)
89
+ # Employee.create_new_partition_tables(dates)
90
+ #
91
+ # Each of partition has the same structure as that of the employees table:
92
+ #
93
+ # id | created_at | updated_at | name | salary | company_id
94
+ # ----+------------+------------+------+--------+------------
95
+ #
96
+ # CREATE TABLE "employees_partitions"."p20101227" (CHECK (created_at >= '2010-12-27'
97
+ # AND created_at < '2011-01-03')) INHERITS (employees);
98
+ # CREATE INDEX "index_employees_partitions.p20101227_on_created_at"
99
+ # ON "employees_partitions"."p20101227" ("created_at");
100
+ # CREATE UNIQUE INDEX "index_employees_partitions.p20101227_on_id"
101
+ # ON "employees_partitions"."p20101227" ("id");
102
+ # ALTER TABLE employees_partitions.p20101227 add foreign key (company_id) references companies(id);
103
+ #
104
+ # CREATE TABLE "employees_partitions"."p20110103" (CHECK (created_at >= '2011-01-03'
105
+ # AND created_at < '2011-01-10')) INHERITS (employees);
106
+ # CREATE INDEX "index_employees_partitions.p20110103_on_created_at"
107
+ # ON "employees_partitions"."p20110103" ("created_at");
108
+ # CREATE UNIQUE INDEX "index_employees_partitions.p20110103_on_id"
109
+ # ON "employees_partitions"."p20110103" ("id");
110
+ # ALTER TABLE employees_partitions.p20110103 add foreign key (company_id) references companies(id);
111
+ #
112
+ # CREATE TABLE "employees_partitions"."p20110110" (CHECK (created_at >= '2011-01-10'
113
+ # AND created_at < '2011-01-17')) INHERITS (employees);
114
+ # CREATE INDEX "index_employees_partitions.p20110110_on_created_at"
115
+ # ON "employees_partitions"."p20110110" ("created_at");
116
+ # CREATE UNIQUE INDEX "index_employees_partitions.p20110110_on_id"
117
+ # ON "employees_partitions"."p20110110" ("id");
118
+ # ALTER TABLE employees_partitions.p20110110 add foreign key (company_id) references companies(id);
119
+ #
120
+ # ...
121
+ # CREATE TABLE "employees_partitions"."p20111212" (CHECK (created_at >= '2011-12-12'
122
+ # AND created_at < '2011-12-19')) INHERITS (employees);
123
+ # CREATE INDEX "index_employees_partitions.p20111212_on_created_at"
124
+ # ON "employees_partitions"."p20111212" ("created_at");
125
+ # CREATE UNIQUE INDEX "index_employees_partitions.p20111212_on_id"
126
+ # ON "employees_partitions"."p20111212" ("id");
127
+ # ALTER TABLE employees_partitions.p20111212 add foreign key (company_id) references companies(id);
128
+ #
129
+ # CREATE TABLE "employees_partitions"."p20111219" (CHECK (created_at >= '2011-12-19'
130
+ # AND created_at < '2011-12-26')) INHERITS (employees);
131
+ # CREATE INDEX "index_employees_partitions.p20111219_on_created_at"
132
+ # ON "employees_partitions"."p20111219" ("created_at");
133
+ # CREATE UNIQUE INDEX "index_employees_partitions.p20111219_on_id"
134
+ # ON "employees_partitions"."p20111219" ("id");
135
+ # ALTER TABLE employees_partitions.p20111219 add foreign key (company_id) references companies(id);
136
+ #
137
+ # CREATE TABLE "employees_partitions"."p20111226" (CHECK (created_at >= '2011-12-26'
138
+ # AND created_at < '2012-01-02')) INHERITS (employees);
139
+ # CREATE INDEX "index_employees_partitions.p20111226_on_created_at"
140
+ # ON "employees_partitions"."p20111226" ("created_at");
141
+ # CREATE UNIQUE INDEX "index_employees_partitions.p20111226_on_id"
142
+ # ON "employees_partitions"."p20111226" ("id");
143
+ # ALTER TABLE employees_partitions.p20111226 add foreign key (company_id) references companies(id);
144
+ #
145
+ # You should have the following tables with increments of one week:
146
+ # employees_partitions.p20101227
147
+ # employees_partitions.p20110103
148
+ # employees_partitions.p20110110
149
+ # employees_partitions.p20110117
150
+ # employees_partitions.p20110124
151
+ # employees_partitions.p20110131
152
+ # employees_partitions.p20110207
153
+ # employees_partitions.p20110214
154
+ # employees_partitions.p20110221
155
+ # employees_partitions.p20110228
156
+ # employees_partitions.p20110307
157
+ # employees_partitions.p20110314
158
+ # employees_partitions.p20110321
159
+ # employees_partitions.p20110328
160
+ # employees_partitions.p20110404
161
+ # employees_partitions.p20110411
162
+ # employees_partitions.p20110418
163
+ # employees_partitions.p20110425
164
+ # employees_partitions.p20110502
165
+ # employees_partitions.p20110509
166
+ # employees_partitions.p20110516
167
+ # employees_partitions.p20110523
168
+ # employees_partitions.p20110530
169
+ # employees_partitions.p20110606
170
+ # employees_partitions.p20110613
171
+ # employees_partitions.p20110620
172
+ # employees_partitions.p20110627
173
+ # employees_partitions.p20110704
174
+ # employees_partitions.p20110711
175
+ # employees_partitions.p20110718
176
+ # employees_partitions.p20110725
177
+ # employees_partitions.p20110801
178
+ # employees_partitions.p20110808
179
+ # employees_partitions.p20110815
180
+ # employees_partitions.p20110822
181
+ # employees_partitions.p20110829
182
+ # employees_partitions.p20110905
183
+ # employees_partitions.p20110912
184
+ # employees_partitions.p20110919
185
+ # employees_partitions.p20110926
186
+ # employees_partitions.p20111003
187
+ # employees_partitions.p20111010
188
+ # employees_partitions.p20111017
189
+ # employees_partitions.p20111024
190
+ # employees_partitions.p20111031
191
+ # employees_partitions.p20111107
192
+ # employees_partitions.p20111114
193
+ # employees_partitions.p20111121
194
+ # employees_partitions.p20111128
195
+ # employees_partitions.p20111205
196
+ # employees_partitions.p20111212
197
+ # employees_partitions.p20111219
198
+ # employees_partitions.p20111226
199
+ #
200
+ # Each of partitions inherits from employees table,
201
+ # thus a new row will automatically be added to the employees table .
202
+ #
203
+ # To add data, we use the following constructions,
204
+ # in which employees and employee_data - a random data:
205
+ #
206
+ # create_many - allows you to add multiple records
207
+ # Employee.create_many(employees)
208
+ # create - allows you to add one record
209
+ # Employee.create(employee_data)
210
+ # new/save! - allows you to add one record without using "create" method
211
+ # employee = Employee.new(employee_data)
212
+ # employee.save!
213
+ #
214
+ # For update data, we use the following constructions,
215
+ # in which updates - a random data:
216
+ #
217
+ # update_many - allows you to update multiple records.
218
+ # :set_array - additional option, you may read the description
219
+ # of the method in the file update_many bulk_methods_mixin.rb about this option.
220
+ # Employee.update_many(updates, {:set_array => '"salary = #{table_name}.salary +
221
+ # datatable.salary, updated_at = now()"'})
222
+ #
223
+ # This construction using for update one record. You also may use update method.
224
+ # employee = Employee.from_partition(employee_record[:created_at]).find(employee_record[:id])
225
+ # employee.save
226
+ #
227
+ # The data get into the employees table ONLY through partition tables.
228
+ # You can not do an insert row into a table employees directly.
229
+ # For this purpose special restrictions are imposed on the table employees.
230
+ #
231
+ # Result:
232
+ #
233
+ # We have table companies:
234
+ #
235
+ # id | created_at | updated_at | name
236
+ # ---+----------------------------+------------+---------------------
237
+ # 1 | 2012-03-11 13:26:52.184347 | | Fluent Mobile, inc.
238
+ # 2 | 2012-03-11 13:26:52.184347 | | Fiksu, inc.
239
+ # 3 | 2012-03-11 13:26:52.184347 | | AppExchanger, inc.
240
+ # 4 | 2012-03-11 13:26:52.184347 | | FreeMyApps, inc.
241
+ #
242
+ # Table employees with random data from 1 to 5000:
243
+ #
244
+ # id | created_at | updated_at | name | salary | company_id
245
+ #------+---------------------+----------------------------+-----------------------------------+-------------+------------
246
+ # 1 | 2011-03-06 21:06:59 | 2012-03-26 12:41:40.32776 | Winston J. Sillypants, I | $125,499.00 | 3
247
+ # 2 | 2011-11-19 21:03:15 | | Winston J. Sillypants, II | $84,881.00 | 2
248
+ # 3 | 2011-10-04 10:06:14 | 2012-03-26 12:41:40.478717 | Winston J. Sillypants, III | $124,067.00 | 3
249
+ # ...
250
+ # 4998 | 2011-09-23 06:10:23 | 2012-03-26 11:41:30.218432 | Picholine Pimplenad, MMMMCMXCVIII | $121,474.00 | 3
251
+ # 4999 | 2011-08-26 18:24:12 | 2012-03-26 11:41:30.222835 | Picholine Pimplenad, MMMMCMXCIX | $134,549.00 | 4
252
+ # 5000 | 2011-10-01 18:29:33 | 2012-03-26 12:41:40.544125 | Picholine Pimplenad, _V | $135,786.00 | 1
253
+ #
254
+ # Partition employees_partitions.p20101227 - partition where
255
+ # created_at >= '2010-12-27 00:00:00' AND created_at < '2011-01-03 00:00:00':
256
+ #
257
+ # id | created_at | updated_at | name | salary | company_id
258
+ #------+---------------------+----------------------------+--------------------------------+-------------+------------
259
+ # 501 | 2011-01-01 07:19:27 | | Winston J. Sillypants, DI | $114,587.00 | 2
260
+ # 1019 | 2011-01-01 15:35:56 | 2012-03-26 13:06:30.045207 | Winston J. Sillypants, MXIX | $84,563.00 | 3
261
+ # 1093 | 2011-01-02 16:59:03 | | Winston J. Sillypants, MXCIII | $81,852.00 | 1
262
+ # ...
263
+ # 4461 | 2011-01-02 09:10:12 | 2012-03-26 14:06:37.462631 | Picholine Pimplenad, MMMMCDLXI | $115,618.00 | 4
264
+ # 4544 | 2011-01-01 09:56:06 | 2012-03-26 13:06:24.708909 | Picholine Pimplenad, MMMMDXLIV | $71,629.00 | 4
265
+ # 4596 | 2011-01-02 03:10:12 | 2012-03-26 13:06:25.027589 | Picholine Pimplenad, MMMMDXCVI | $88,167.00 | 3
266
+ #
267
+ # Partition employees_partitions.p20110103 - partition where
268
+ # created_at >= '2011-01-03 00:00:00' AND created_at < '2011-01-10 00:00:00':
269
+ #
270
+ # id | created_at | updated_at | name | salary | company_id
271
+ #------+---------------------+----------------------------+------------------------------------+-------------+------------
272
+ # 41 | 2011-01-09 04:19:34 | | Winston J. Sillypants, XLI | $125,885.00 | 2
273
+ # 68 | 2011-01-05 13:27:00 | 2012-03-26 13:06:31.066556 | Winston J. Sillypants, LXVIII | $117,202.00 | 2
274
+ # 77 | 2011-01-08 11:34:15 | | Winston J. Sillypants, LXXVII | $68,907.00 | 4
275
+ # ...
276
+ # 4858 | 2011-01-03 04:13:29 | 2012-03-26 13:06:26.497023 | Picholine Pimplenad, MMMMDCCCLVIII | $85,379.00 | 4
277
+ # 4865 | 2011-01-04 05:42:59 | 2012-03-26 13:06:26.531102 | Picholine Pimplenad, MMMMDCCCLXV | $78,517.00 | 4
278
+ # 4943 | 2011-01-05 04:15:05 | 2012-03-26 13:06:26.892893 | Picholine Pimplenad, MMMMCMXLIII | $137,396.00 | 1
279
+ #
280
+ # Partition employees_partitions.p20110110 - partition where
281
+ # created_at >= '2011-01-10 00:00:00' AND created_at < '2011-01-17 00:00:00':
282
+ #
283
+ # id | created_at | updated_at | name | salary | company_id
284
+ #------+---------------------+----------------------------+---------------------------------+-------------+------------
285
+ # 7 | 2011-01-13 04:29:44 | | Winston J. Sillypants, VII | $65,096.00 | 2
286
+ # 8 | 2011-01-14 16:34:09 | 2012-03-26 13:06:30.408574 | Winston J. Sillypants, VIII | $96,136.00 | 4
287
+ # 53 | 2011-01-14 15:02:05 | 2012-03-26 13:06:30.596073 | Winston J. Sillypants, LIII | $107,568.00 | 2
288
+ # ...
289
+ # 4909 | 2011-01-16 21:35:17 | 2012-03-26 13:06:26.734996 | Picholine Pimplenad, MMMMCMIX | $117,583.00 | 3
290
+ # 4945 | 2011-01-14 13:08:14 | 2012-03-26 13:06:26.902338 | Picholine Pimplenad, MMMMCMXLV | $138,966.00 | 1
291
+ # 4946 | 2011-01-15 13:01:35 | 2012-03-26 14:06:37.290964 | Picholine Pimplenad, MMMMCMXLVI | $131,803.00 | 3
292
+ #
293
+ # ...
294
+ #
295
+ # Partition employees_partitions.p20111212 - partition where
296
+ # created_at >= '2011-12-12 00:00:00' AND created_at < '2011-12-19 00:00:00':
297
+ #
298
+ # id | created_at | updated_at | name | salary | company_id
299
+ #------+---------------------+----------------------------+------------------------------------+-------------+------------
300
+ # 10 | 2011-12-17 11:21:01 | | Winston J. Sillypants, X | $66,153.00 | 4
301
+ # 137 | 2011-12-18 06:55:52 | | Winston J. Sillypants, CXXXVII | $67,900.00 | 1
302
+ # 195 | 2011-12-17 15:39:41 | | Winston J. Sillypants, CXCV | $121,419.00 | 1
303
+ # ...
304
+ # 4958 | 2011-12-14 07:16:08 | 2012-03-26 13:06:26.965279 | Picholine Pimplenad, MMMMCMLVIII | $114,922.00 | 1
305
+ # 4987 | 2011-12-12 07:11:57 | 2012-03-26 13:06:30.022127 | Picholine Pimplenad, MMMMCMLXXXVII | $86,493.00 | 2
306
+ # 5000 | 2011-12-18 04:23:49 | 2012-03-26 14:06:37.20847 | Picholine Pimplenad, _V | $84,113.00 | 4
307
+ #
308
+ # Partition employees_partitions.p20111219 - partition where
309
+ # created_at >= '2011-12-19 00:00:00' AND created_at < '2011-12-26 00:00:00':
310
+ #
311
+ # id | created_at | updated_at | name | salary | company_id
312
+ #------+---------------------+----------------------------+-------------------------------------+-------------+------------
313
+ # 2 | 2011-12-25 15:24:20 | 2012-03-26 13:06:28.669243 | Winston J. Sillypants, II | $67,221.00 | 3
314
+ # 73 | 2011-12-20 01:04:46 | | Winston J. Sillypants, LXXIII | $108,260.00 | 4
315
+ # 88 | 2011-12-24 17:58:28 | | Winston J. Sillypants, LXXXVIII | $66,455.00 | 2
316
+ # ...
317
+ # 4898 | 2011-12-25 23:23:17 | 2012-03-26 13:06:26.685775 | Picholine Pimplenad, MMMMDCCCXCVIII | $139,737.00 | 3
318
+ # 4919 | 2011-12-24 07:30:13 | 2012-03-26 13:06:26.777466 | Picholine Pimplenad, MMMMCMXIX | $78,781.00 | 4
319
+ # 4988 | 2011-12-20 12:03:47 | 2012-03-26 13:06:27.112457 | Picholine Pimplenad, MMMMCMLXXXVIII | $101,671.00 | 1
320
+ #
321
+ # Partition employees_partitions.p20111226 - partition where
322
+ # created_at >= '2011-12-26 00:00:00' AND created_at < '2012-01-02 00:00:00':
323
+ #
324
+ # id | created_at | updated_at | name | salary | company_id
325
+ #------+---------------------+----------------------------+-------------------------------------+-------------+------------
326
+ # 91 | 2011-12-28 09:57:36 | 2012-03-26 14:06:37.434407 | Winston J. Sillypants, XCI | $63,230.00 | 2
327
+ # 118 | 2011-12-29 21:05:05 | | Winston J. Sillypants, CXVIII | $131,837.00 | 3
328
+ # 146 | 2011-12-27 04:50:46 | | Winston J. Sillypants, CXLVI | $107,580.00 | 1
329
+ # ...
330
+ # 4488 | 2011-12-26 03:03:13 | 2012-03-26 13:06:24.43532 | Picholine Pimplenad, MMMMCDLXXXVIII | $91,115.00 | 3
331
+ # 4730 | 2011-12-26 11:07:25 | 2012-03-26 13:06:25.785818 | Picholine Pimplenad, MMMMDCCXXX | $95,658.00 | 2
332
+ # 4817 | 2011-12-27 12:00:07 | 2012-03-26 13:06:34.28227 | Picholine Pimplenad, MMMMDCCCXVII | $63,418.00 | 1
333
+
334
+ require File.expand_path(File.dirname(__FILE__) + "/lib/command_line_tool_mixin")
335
+ require File.expand_path(File.dirname(__FILE__) + "/lib/get_options")
336
+
337
+ include CommandLineToolMixin
338
+
339
+ $cleanup = false
340
+ $force = false
341
+ $create_many = 3000
342
+ $create_individual = 1000
343
+ $new_individual = 1000
344
+ $update_many = 1000
345
+ $update_individual = 1000
346
+
347
+ @options = {
348
+ "--cleanup" => {
349
+ :short => "-C",
350
+ :argument => GetoptLong::NO_ARGUMENT,
351
+ :note => "cleanup data in database and exit"
352
+ },
353
+ "--force" => {
354
+ :short => "-F",
355
+ :argument => GetoptLong::NO_ARGUMENT,
356
+ :note => "cleanup data in database before creating new data"
357
+ },
358
+ "--create-many" => {
359
+ :short => "-m",
360
+ :argument => GetoptLong::REQUIRED_ARGUMENT,
361
+ :note => "how many objects to create via create_many",
362
+ :argument_note => "NUMBER"
363
+ },
364
+ "--create-individual" => {
365
+ :short => "-i",
366
+ :argument => GetoptLong::REQUIRED_ARGUMENT,
367
+ :note => "how many objects to create via create",
368
+ :argument_note => "NUMBER"
369
+ },
370
+ "--new-individual" => {
371
+ :short => "-I",
372
+ :argument => GetoptLong::REQUIRED_ARGUMENT,
373
+ :note => "how many objects to create via new/save",
374
+ :argument_note => "NUMBER"
375
+ },
376
+ "--update-individual" => {
377
+ :short => "-u",
378
+ :argument => GetoptLong::REQUIRED_ARGUMENT,
379
+ :note => "how many objects to update indivudually",
380
+ :argument_note => "NUMBER"
381
+ },
382
+ "--update-many" => {
383
+ :short => "-U",
384
+ :argument => GetoptLong::REQUIRED_ARGUMENT,
385
+ :note => "how many objects to update via update_many",
386
+ :argument_note => "NUMBER"
387
+ },
388
+ }
389
+
390
+ command_line_options(@options) do |option,argument|
391
+ if option == '--cleanup'
392
+ $cleanup = true
393
+ elsif option == '--force'
394
+ $force = true
395
+ elsif option == '--create-many'
396
+ $create_many = argument.to_i
397
+ elsif option == '--create-individual'
398
+ $create_individual = argument.to_i
399
+ elsif option == '--new-individual'
400
+ $new_individual = argument.to_i
401
+ elsif option == '--update-individual'
402
+ $update_individual = argument.to_i
403
+ elsif option == '--update-many'
404
+ $update_many = argument.to_i
405
+ end
406
+ end
407
+
408
+ if $cleanup || $force
409
+ ActiveRecord::Base.connection.drop_schema("employees_partitions", :cascade => true) rescue nil
410
+ ActiveRecord::Base.connection.drop_table("employees") rescue nil
411
+ ActiveRecord::Base.connection.drop_table("companies") rescue nil
412
+ exit(0) if $cleanup
413
+ end
414
+
415
+ $total_records = $create_many + $create_individual + $new_individual
416
+
417
+ puts "total records: #{$total_records}"
418
+
419
+ START_DATE = Date.parse('2011-01-01')
420
+ END_DATE = Date.parse('2011-12-31')
421
+
422
+ # the ActiveRecord classes
423
+
424
+ require File.expand_path(File.dirname(__FILE__) + "/lib/company")
425
+
426
+ class Employee < Partitioned::ByCreatedAt
427
+ belongs_to :company, :class_name => 'Company'
428
+ attr_accessible :name, :company_id, :salary, :created_at
429
+
430
+ partitioned do |partition|
431
+ partition.index :id, :unique => true
432
+ partition.foreign_key :company_id
433
+ end
434
+
435
+ connection.execute <<-SQL
436
+ create table employees
437
+ (
438
+ id serial not null primary key,
439
+ created_at timestamp not null default now(),
440
+ updated_at timestamp,
441
+ name text not null,
442
+ salary money not null,
443
+ company_id integer not null
444
+ );
445
+ SQL
446
+ end
447
+
448
+ # You should have the following tables:
449
+ # public.companies
450
+ # public.employees
451
+
452
+ # create the infrastructure for EMPLOYEES table which includes the schema and partition tables
453
+
454
+ Employee.create_infrastructure
455
+
456
+ # You should have the following schema:
457
+ # employees_partitions
458
+
459
+ dates = Employee.partition_generate_range(START_DATE, END_DATE)
460
+ Employee.create_new_partition_tables(dates)
461
+
462
+ # You should have the following tables with increments of one week:
463
+ # employees_partitions.p20101227
464
+ # employees_partitions.p20110103
465
+ # employees_partitions.p20110110
466
+ # employees_partitions.p20110117
467
+ # employees_partitions.p20110124
468
+ # employees_partitions.p20110131
469
+ # employees_partitions.p20110207
470
+ # employees_partitions.p20110214
471
+ # employees_partitions.p20110221
472
+ # employees_partitions.p20110228
473
+ # employees_partitions.p20110307
474
+ # employees_partitions.p20110314
475
+ # employees_partitions.p20110321
476
+ # employees_partitions.p20110328
477
+ # employees_partitions.p20110404
478
+ # employees_partitions.p20110411
479
+ # employees_partitions.p20110418
480
+ # employees_partitions.p20110425
481
+ # employees_partitions.p20110502
482
+ # employees_partitions.p20110509
483
+ # employees_partitions.p20110516
484
+ # employees_partitions.p20110523
485
+ # employees_partitions.p20110530
486
+ # employees_partitions.p20110606
487
+ # employees_partitions.p20110613
488
+ # employees_partitions.p20110620
489
+ # employees_partitions.p20110627
490
+ # employees_partitions.p20110704
491
+ # employees_partitions.p20110711
492
+ # employees_partitions.p20110718
493
+ # employees_partitions.p20110725
494
+ # employees_partitions.p20110801
495
+ # employees_partitions.p20110808
496
+ # employees_partitions.p20110815
497
+ # employees_partitions.p20110822
498
+ # employees_partitions.p20110829
499
+ # employees_partitions.p20110905
500
+ # employees_partitions.p20110912
501
+ # employees_partitions.p20110919
502
+ # employees_partitions.p20110926
503
+ # employees_partitions.p20111003
504
+ # employees_partitions.p20111010
505
+ # employees_partitions.p20111017
506
+ # employees_partitions.p20111024
507
+ # employees_partitions.p20111031
508
+ # employees_partitions.p20111107
509
+ # employees_partitions.p20111114
510
+ # employees_partitions.p20111121
511
+ # employees_partitions.p20111128
512
+ # employees_partitions.p20111205
513
+ # employees_partitions.p20111212
514
+ # employees_partitions.p20111219
515
+ # employees_partitions.p20111226
516
+
517
+ # add some companies
518
+
519
+ Company.create_many(COMPANIES)
520
+ company_ids = Company.all.map(&:id)
521
+
522
+ employees = []
523
+
524
+ require File.expand_path(File.dirname(__FILE__) + "/lib/roman")
525
+
526
+ # generates data for employees_partitions and employees tables
527
+
528
+ base = 0
529
+ (1..$create_many).each do |i|
530
+ employees << {
531
+ :name => "Winston J. Sillypants, #{to_roman(base+i)}",
532
+ :created_at => START_DATE + rand(END_DATE - START_DATE) + rand(1.day.seconds).seconds,
533
+ :salary => rand(80000) + 60000,
534
+ :company_id => company_ids[rand company_ids.length]
535
+ }
536
+ end
537
+
538
+ puts "creating many #{$create_many}"
539
+ Employee.create_many(employees)
540
+ base += $create_many
541
+
542
+ puts "creating individual #{$create_individual}"
543
+ (1..$create_individual).each do |i|
544
+ employee_data = {
545
+ :name => "Jonathan Crabapple, #{to_roman(base+i)}",
546
+ :created_at => START_DATE + rand(END_DATE - START_DATE) + rand(1.day.seconds).seconds,
547
+ :salary => rand(80000) + 60000,
548
+ :company_id => company_ids[rand company_ids.length]
549
+ }
550
+ employees << Employee.create(employee_data)
551
+ end
552
+ base += $create_individual
553
+
554
+ puts "new individual #{$new_individual}"
555
+ (1..$new_individual).each do |i|
556
+ employee_data = {
557
+ :name => "Picholine Pimplenad, #{to_roman(base+i)}",
558
+ :created_at => START_DATE + rand(END_DATE - START_DATE) + rand(1.day.seconds).seconds,
559
+ :salary => rand(80000) + 60000,
560
+ :company_id => company_ids[rand company_ids.length]
561
+ }
562
+ employee = Employee.new(employee_data)
563
+ employee.save
564
+ employees << employee
565
+ end
566
+ base += $new_individual
567
+
568
+ updates = {}
569
+ puts "update many #{$update_many}"
570
+ (1..$update_many).each do |i|
571
+ index = rand(employees.length)
572
+ employee_record = employees[index]
573
+ updates[{
574
+ :id => employee_record[:id],
575
+ :created_at => employee_record[:created_at]
576
+ }] = {
577
+ :salary => 100
578
+ }
579
+ end
580
+
581
+ Employee.update_many(updates, {:set_array => '"salary = #{table_name}.salary + datatable.salary, updated_at = now()"'})
582
+
583
+ puts "update individual #{$update_individual}"
584
+ (1..$update_individual).each do |i|
585
+ index = rand(employees.length)
586
+ employee_record = employees[index]
587
+ employee = Employee.from_partition(employee_record[:created_at]).find(employee_record[:id])
588
+ employee.salary += 1000
589
+ employee.save
590
+ end