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
data/examples/id.rb ADDED
@@ -0,0 +1,475 @@
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
+ # ./id.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 an id.
56
+ #
57
+ # Implementation:
58
+ #
59
+ # Class Employee inherits from the abstract class ById,
60
+ # which supports partitioning.
61
+ #
62
+ # class Employee < Partitioned::ById
63
+ #
64
+ # Indicates a relationship to the companies table.
65
+ # belongs_to :company, :class_name => 'Company'
66
+ #
67
+ # Partition table size defines a count of records in one partition table.
68
+ # def self.partition_table_size
69
+ # return 10
70
+ # end
71
+ #
72
+ # Create a rules for each partition.
73
+ # Id is a unique index. Foreign key is company_id.
74
+ # This imposes a restriction on each of partition, that
75
+ # the column company_id associated with the table of companies
76
+ # and can not have values ​​that are not in the table companies.
77
+ # In this example, set up only 4 records in the table companies,
78
+ # so company_id can not be equal to 5 in any partition
79
+ # until it is an established company with id = 5.
80
+ #
81
+ # partitioned do |partition|
82
+ # partition.foreign_key :company_id
83
+ # end
84
+ # end
85
+ #
86
+ # Create a schema employees_partitions, within which to store all of our partitions:
87
+ #
88
+ # Employee.create_infrastructure
89
+ #
90
+ # Create a partition tables with increments of 10 records:
91
+ #
92
+ # ids = Employee.partition_generate_range(0, NUM_EMPLOYEES, Employee.partition_table_size)
93
+ # Employee.create_new_partition_tables(ids)
94
+ #
95
+ # Each of partition has the same structure as that of the employees table:
96
+ #
97
+ # id | created_at | updated_at | name | salary | company_id
98
+ # ----+------------+------------+------+--------+------------
99
+ #
100
+ # CREATE TABLE "employees_partitions"."p0" (CHECK (( id >= 0 and id < 10 ))) INHERITS (employees);
101
+ # CREATE UNIQUE INDEX "p0_id_udx" ON "employees_partitions"."p0" ("id");
102
+ # ALTER TABLE employees_partitions.p0 add foreign key (company_id) references companies(id);
103
+ #
104
+ # CREATE TABLE "employees_partitions"."p10" (CHECK (( id >= 10 and id < 20 ))) INHERITS (employees);
105
+ # CREATE UNIQUE INDEX "p10_id_udx" ON "employees_partitions"."p10" ("id");
106
+ # ALTER TABLE employees_partitions.p10 add foreign key (company_id) references companies(id);
107
+ #
108
+ # CREATE TABLE "employees_partitions"."p20" (CHECK (( id >= 20 and id < 30 ))) INHERITS (employees);
109
+ # CREATE UNIQUE INDEX "p20_id_udx" ON "employees_partitions"."p20" ("id");
110
+ # ALTER TABLE employees_partitions.p20 add foreign key (company_id) references companies(id);
111
+ #
112
+ # ...
113
+ # CREATE TABLE "employees_partitions"."p4980" (CHECK (( id >= 4980 and id < 4990 ))) INHERITS (employees);
114
+ # CREATE UNIQUE INDEX "p4980_id_udx" ON "employees_partitions"."p4980" ("id");
115
+ # ALTER TABLE employees_partitions.p4980 add foreign key (company_id) references companies(id);
116
+ #
117
+ # CREATE TABLE "employees_partitions"."p4990" (CHECK (( id >= 4990 and id < 5000 ))) INHERITS (employees);
118
+ # CREATE UNIQUE INDEX "p4990_id_udx" ON "employees_partitions"."p4990" ("id");
119
+ # ALTER TABLE employees_partitions.p4990 add foreign key (company_id) references companies(id);
120
+ #
121
+ # CREATE TABLE "employees_partitions"."p5000" (CHECK (( id >= 5000 and id < 5010 ))) INHERITS (employees);
122
+ # CREATE UNIQUE INDEX "p5000_id_udx" ON "employees_partitions"."p5000" ("id");
123
+ # ALTER TABLE employees_partitions.p5000 add foreign key (company_id) references companies(id);
124
+ #
125
+ # You should have the following tables with increments of 10 ids:
126
+ # employees_partitions.p0
127
+ # employees_partitions.p10
128
+ # employees_partitions.p20
129
+ # ...
130
+ # employees_partitions.p4980
131
+ # employees_partitions.p4990
132
+ # employees_partitions.p5000
133
+ #
134
+ # Each of partitions inherits from employees table,
135
+ # thus a new row will automatically be added to the employees table .
136
+ #
137
+ # To add data, we use the following constructions,
138
+ # in which employees and employee_data - a random data:
139
+ #
140
+ # create_many - allows you to add multiple records
141
+ # Employee.create_many(employees)
142
+ # create - allows you to add one record
143
+ # Employee.create(employee_data)
144
+ # new/save! - allows you to add one record without using "create" method
145
+ # employee = Employee.new(employee_data)
146
+ # employee.save!
147
+ #
148
+ # For update data, we use the following constructions,
149
+ # in which updates - a random data:
150
+ #
151
+ # update_many - allows you to update multiple records.
152
+ # :set_array - additional option, you may read the description
153
+ # of the method in the file update_many bulk_methods_mixin.rb about this option.
154
+ # Employee.update_many(updates, {:set_array => '"salary = #{table_name}.salary +
155
+ # datatable.salary, updated_at = now()"'})
156
+ #
157
+ # This construction using for update one record. You also may use update method.
158
+ # employee = Employee.from_partition(employee_record[:id]).find(employee_record[:id])
159
+ # employee.save
160
+ #
161
+ # The data get into the employees table ONLY through partition tables.
162
+ # You can not do an insert row into a table employees directly.
163
+ # For this purpose special restrictions are imposed on the table employees.
164
+ #
165
+ # Result:
166
+ #
167
+ # We have table companies:
168
+ #
169
+ # id | created_at | updated_at | name
170
+ # ---+----------------------------+------------+---------------------
171
+ # 1 | 2012-03-11 13:26:52.184347 | | Fluent Mobile, inc.
172
+ # 2 | 2012-03-11 13:26:52.184347 | | Fiksu, inc.
173
+ # 3 | 2012-03-11 13:26:52.184347 | | AppExchanger, inc.
174
+ # 4 | 2012-03-11 13:26:52.184347 | | FreeMyApps, inc.
175
+ #
176
+ # Table employees with random data from 1 to 5000:
177
+ #
178
+ # id | created_at | updated_at | name | salary | company_id
179
+ #------+----------------------------+----------------------------+-----------------------------------+-------------+------------
180
+ # 1 | 2012-03-26 13:24:42.368938 | | Winston J. Sillypants, I | $128,739.00 | 2
181
+ # 2 | 2012-03-26 13:24:42.368938 | | Winston J. Sillypants, II | $128,107.00 | 3
182
+ # 3 | 2012-03-26 13:24:42.368938 | 2012-03-26 14:25:05.36247 | Winston J. Sillypants, III | $64,773.00 | 3
183
+ # ...
184
+ # 4998 | 2012-03-26 13:24:54.852909 | 2012-03-26 14:25:04.65906 | Picholine Pimplenad, MMMMCMXCVIII | $77,423.00 | 2
185
+ # 4999 | 2012-03-26 13:24:54.857871 | 2012-03-26 13:24:54.857871 | Picholine Pimplenad, MMMMCMXCIX | $134,121.00 | 4
186
+ # 5000 | 2012-03-26 13:24:54.862685 | 2012-03-26 13:24:54.862685 | Picholine Pimplenad, _V | $114,432.00 | 1
187
+ #
188
+ # Partition employees_partitions.p0 - partition where (id >= 0 AND id < 10):
189
+ #
190
+ # id | created_at | updated_at | name | salary | company_id
191
+ # ----+----------------------------+---------------------------+-----------------------------+-------------+------------
192
+ # 1 | 2012-03-26 13:24:42.368938 | | Winston J. Sillypants, I | $128,739.00 | 2
193
+ # 2 | 2012-03-26 13:24:42.368938 | | Winston J. Sillypants, II | $128,107.00 | 3
194
+ # 3 | 2012-03-26 13:24:42.368938 | 2012-03-26 14:25:05.36247 | Winston J. Sillypants, III | $64,773.00 | 3
195
+ # 4 | 2012-03-26 13:24:42.368938 | | Winston J. Sillypants, IV | $138,131.00 | 4
196
+ # 5 | 2012-03-26 13:24:42.368938 | | Winston J. Sillypants, V | $81,823.00 | 3
197
+ # 6 | 2012-03-26 13:24:42.368938 | | Winston J. Sillypants, VI | $66,892.00 | 1
198
+ # 7 | 2012-03-26 13:24:42.368938 | | Winston J. Sillypants, VII | $68,906.00 | 2
199
+ # 8 | 2012-03-26 13:24:42.368938 | | Winston J. Sillypants, VIII | $116,640.00 | 1
200
+ # 9 | 2012-03-26 13:24:42.368938 | 2012-03-26 14:25:05.36247 | Winston J. Sillypants, IX | $99,194.00 | 2
201
+ #
202
+ # Partition employees_partitions.p10 - partition where (id >= 10 AND id < 20):
203
+ #
204
+ # id | created_at | updated_at | name | salary | company_id
205
+ # ----+----------------------------+----------------------------+------------------------------+-------------+------------
206
+ # 10 | 2012-03-26 13:24:42.368938 | 2012-03-26 13:25:00.75383 | Winston J. Sillypants, X | $120,320.00 | 4
207
+ # 11 | 2012-03-26 13:24:42.368938 | | Winston J. Sillypants, XI | $90,422.00 | 4
208
+ # 12 | 2012-03-26 13:24:42.368938 | | Winston J. Sillypants, XII | $75,570.00 | 4
209
+ # 13 | 2012-03-26 13:24:42.368938 | | Winston J. Sillypants, XIII | $109,886.00 | 1
210
+ # 14 | 2012-03-26 13:24:42.368938 | 2012-03-26 13:25:01.58278 | Winston J. Sillypants, XIV | $89,954.00 | 3
211
+ # 15 | 2012-03-26 13:24:42.368938 | | Winston J. Sillypants, XV | $86,063.00 | 2
212
+ # 16 | 2012-03-26 13:24:42.368938 | | Winston J. Sillypants, XVI | $66,072.00 | 1
213
+ # 17 | 2012-03-26 13:24:42.368938 | | Winston J. Sillypants, XVII | $84,231.00 | 1
214
+ # 18 | 2012-03-26 13:24:42.368938 | | Winston J. Sillypants, XVIII | $105,545.00 | 1
215
+ # 19 | 2012-03-26 13:24:42.368938 | 2012-03-26 13:24:59.727553 | Winston J. Sillypants, XIX | $125,657.00 | 4
216
+ #
217
+ # Partition employees_partitions.p20 - partition where (id >= 20 AND id < 30):
218
+ #
219
+ # id | created_at | updated_at | name | salary | company_id
220
+ # ----+----------------------------+----------------------------+-------------------------------+-------------+------------
221
+ # 20 | 2012-03-26 13:24:42.368938 | | Winston J. Sillypants, XX | $89,345.00 | 2
222
+ # 21 | 2012-03-26 13:24:42.368938 | | Winston J. Sillypants, XXI | $92,289.00 | 4
223
+ # 22 | 2012-03-26 13:24:42.368938 | 2012-03-26 13:24:58.306639 | Winston J. Sillypants, XXII | $97,416.00 | 4
224
+ # 23 | 2012-03-26 13:24:42.368938 | 2012-03-26 14:25:05.152222 | Winston J. Sillypants, XXIII | $74,307.00 | 1
225
+ # 24 | 2012-03-26 13:24:42.368938 | 2012-03-26 14:25:05.152222 | Winston J. Sillypants, XXIV | $136,770.00 | 4
226
+ # 25 | 2012-03-26 13:24:42.368938 | | Winston J. Sillypants, XXV | $108,876.00 | 1
227
+ # 26 | 2012-03-26 13:24:42.368938 | | Winston J. Sillypants, XXVI | $84,157.00 | 1
228
+ # 27 | 2012-03-26 13:24:42.368938 | | Winston J. Sillypants, XXVII | $108,896.00 | 3
229
+ # 28 | 2012-03-26 13:24:42.368938 | 2012-03-26 13:24:56.590543 | Winston J. Sillypants, XXVIII | $93,987.00 | 2
230
+ # 29 | 2012-03-26 13:24:42.368938 | 2012-03-26 14:25:05.152222 | Winston J. Sillypants, XXIX | $88,377.00 | 4
231
+ #
232
+ # ...
233
+ # Partition employees_partitions.p4980 - partition where (id >= 4980 AND id < 4990):
234
+ #
235
+ # id | created_at | updated_at | name | salary | company_id
236
+ #------+----------------------------+----------------------------+-------------------------------------+-------------+------------
237
+ # 4980 | 2012-03-26 13:24:54.761377 | 2012-03-26 14:25:04.733069 | Picholine Pimplenad, MMMMCMLXXX | $104,522.00 | 3
238
+ # 4981 | 2012-03-26 13:24:54.769005 | 2012-03-26 13:25:02.598973 | Picholine Pimplenad, MMMMCMLXXXI | $112,196.00 | 2
239
+ # 4982 | 2012-03-26 13:24:54.773971 | 2012-03-26 13:24:54.773971 | Picholine Pimplenad, MMMMCMLXXXII | $93,853.00 | 4
240
+ # 4983 | 2012-03-26 13:24:54.779096 | 2012-03-26 13:24:54.779096 | Picholine Pimplenad, MMMMCMLXXXIII | $126,166.00 | 1
241
+ # 4984 | 2012-03-26 13:24:54.783103 | 2012-03-26 14:25:04.733069 | Picholine Pimplenad, MMMMCMLXXXIV | $103,503.00 | 4
242
+ # 4985 | 2012-03-26 13:24:54.787865 | 2012-03-26 13:24:54.787865 | Picholine Pimplenad, MMMMCMLXXXV | $115,251.00 | 4
243
+ # 4986 | 2012-03-26 13:24:54.792864 | 2012-03-26 13:24:57.905747 | Picholine Pimplenad, MMMMCMLXXXVI | $72,873.00 | 4
244
+ # 4987 | 2012-03-26 13:24:54.798004 | 2012-03-26 13:24:54.798004 | Picholine Pimplenad, MMMMCMLXXXVII | $117,931.00 | 4
245
+ # 4988 | 2012-03-26 13:24:54.802963 | 2012-03-26 13:24:54.802963 | Picholine Pimplenad, MMMMCMLXXXVIII | $87,801.00 | 2
246
+ # 4989 | 2012-03-26 13:24:54.8078 | 2012-03-26 13:24:54.8078 | Picholine Pimplenad, MMMMCMLXXXIX | $99,801.00 | 3
247
+ #
248
+ # Partition employees_partitions.p4990 - partition where (id >= 4990 AND id < 5000):
249
+ #
250
+ # id | created_at | updated_at | name | salary | company_id
251
+ #------+----------------------------+----------------------------+-----------------------------------+-------------+------------
252
+ # 4990 | 2012-03-26 13:24:54.812753 | 2012-03-26 13:24:54.812753 | Picholine Pimplenad, MMMMCMXC | $69,725.00 | 3
253
+ # 4991 | 2012-03-26 13:24:54.820171 | 2012-03-26 13:24:57.663318 | Picholine Pimplenad, MMMMCMXCI | $128,414.00 | 1
254
+ # 4992 | 2012-03-26 13:24:54.825059 | 2012-03-26 13:24:54.825059 | Picholine Pimplenad, MMMMCMXCII | $113,357.00 | 2
255
+ # 4993 | 2012-03-26 13:24:54.829422 | 2012-03-26 13:24:54.829422 | Picholine Pimplenad, MMMMCMXCIII | $96,098.00 | 2
256
+ # 4994 | 2012-03-26 13:24:54.833662 | 2012-03-26 13:24:54.833662 | Picholine Pimplenad, MMMMCMXCIV | $89,013.00 | 2
257
+ # 4995 | 2012-03-26 13:24:54.838481 | 2012-03-26 14:25:04.65906 | Picholine Pimplenad, MMMMCMXCV | $95,160.00 | 4
258
+ # 4996 | 2012-03-26 13:24:54.843238 | 2012-03-26 13:24:54.843238 | Picholine Pimplenad, MMMMCMXCVI | $95,245.00 | 3
259
+ # 4997 | 2012-03-26 13:24:54.84813 | 2012-03-26 13:24:54.84813 | Picholine Pimplenad, MMMMCMXCVII | $136,887.00 | 3
260
+ # 4998 | 2012-03-26 13:24:54.852909 | 2012-03-26 14:25:04.65906 | Picholine Pimplenad, MMMMCMXCVIII | $77,423.00 | 2
261
+ # 4999 | 2012-03-26 13:24:54.857871 | 2012-03-26 13:24:54.857871 | Picholine Pimplenad, MMMMCMXCIX | $134,121.00 | 4
262
+ #
263
+ # Partition employees_partitions.p5000 - partition where (id >= 5000 AND id < 5010):
264
+ #
265
+ # id | created_at | updated_at | name | salary | company_id
266
+ #------+----------------------------+----------------------------+-----------------------------------+-------------+------------
267
+ # 5000 | 2012-03-26 13:24:54.862685 | 2012-03-26 13:24:54.862685 | Picholine Pimplenad, _V | $114,432.00 | 1
268
+ #
269
+
270
+ require File.expand_path(File.dirname(__FILE__) + "/lib/command_line_tool_mixin")
271
+ require File.expand_path(File.dirname(__FILE__) + "/lib/get_options")
272
+
273
+ include CommandLineToolMixin
274
+
275
+ $cleanup = false
276
+ $force = false
277
+ $create_many = 3000
278
+ $create_individual = 1000
279
+ $new_individual = 1000
280
+ $update_many = 1000
281
+ $update_individual = 1000
282
+ $partition_table_size = 10
283
+
284
+ @options = {
285
+ "--cleanup" => {
286
+ :short => "-C",
287
+ :argument => GetoptLong::NO_ARGUMENT,
288
+ :note => "cleanup data in database and exit"
289
+ },
290
+ "--force" => {
291
+ :short => "-F",
292
+ :argument => GetoptLong::NO_ARGUMENT,
293
+ :note => "cleanup data in database before creating new data"
294
+ },
295
+ "--create-many" => {
296
+ :short => "-m",
297
+ :argument => GetoptLong::REQUIRED_ARGUMENT,
298
+ :note => "how many objects to create via create_many",
299
+ :argument_note => "NUMBER"
300
+ },
301
+ "--create-individual" => {
302
+ :short => "-i",
303
+ :argument => GetoptLong::REQUIRED_ARGUMENT,
304
+ :note => "how many objects to create via create",
305
+ :argument_note => "NUMBER"
306
+ },
307
+ "--new-individual" => {
308
+ :short => "-I",
309
+ :argument => GetoptLong::REQUIRED_ARGUMENT,
310
+ :note => "how many objects to create via new/save",
311
+ :argument_note => "NUMBER"
312
+ },
313
+ "--update-individual" => {
314
+ :short => "-u",
315
+ :argument => GetoptLong::REQUIRED_ARGUMENT,
316
+ :note => "how many objects to update individually",
317
+ :argument_note => "NUMBER"
318
+ },
319
+ "--update-many" => {
320
+ :short => "-U",
321
+ :argument => GetoptLong::REQUIRED_ARGUMENT,
322
+ :note => "how many objects to update via update_many",
323
+ :argument_note => "NUMBER"
324
+ },
325
+ }
326
+
327
+ command_line_options(@options) do |option,argument|
328
+ if option == '--cleanup'
329
+ $cleanup = true
330
+ elsif option == '--force'
331
+ $force = true
332
+ elsif option == '--create-many'
333
+ $create_many = argument.to_i
334
+ elsif option == '--create-individual'
335
+ $create_individual = argument.to_i
336
+ elsif option == '--new-individual'
337
+ $new_individual = argument.to_i
338
+ elsif option == '--update-individual'
339
+ $update_individual = argument.to_i
340
+ elsif option == '--update-many'
341
+ $update_many = argument.to_i
342
+ end
343
+ end
344
+
345
+ if $cleanup || $force
346
+ ActiveRecord::Base.connection.drop_schema("employees_partitions", :cascade => true) rescue nil
347
+ ActiveRecord::Base.connection.drop_table("employees") rescue nil
348
+ ActiveRecord::Base.connection.drop_table("companies") rescue nil
349
+ exit(0) if $cleanup
350
+ end
351
+
352
+ $total_records = $create_many + $create_individual + $new_individual
353
+
354
+ puts "total records: #{$total_records}"
355
+
356
+ # the ActiveRecord classes
357
+
358
+ require File.expand_path(File.dirname(__FILE__) + "/lib/company")
359
+
360
+ class Employee < Partitioned::ById
361
+ belongs_to :company, :class_name => 'Company'
362
+ attr_accessible :company_id, :salary, :name
363
+
364
+ def self.partition_table_size
365
+ return $partition_table_size
366
+ end
367
+
368
+ partitioned do |partition|
369
+ partition.foreign_key :company_id
370
+ end
371
+
372
+ connection.execute <<-SQL
373
+ create table employees
374
+ (
375
+ id serial not null primary key,
376
+ created_at timestamp not null default now(),
377
+ updated_at timestamp,
378
+ name text not null,
379
+ salary money not null,
380
+ company_id integer not null
381
+ );
382
+ SQL
383
+ end
384
+
385
+ # You should have the following tables:
386
+ # public.companies
387
+ # public.employees
388
+
389
+ # add some companies
390
+
391
+ Company.create_many(COMPANIES)
392
+ company_ids = Company.all.map(&:id)
393
+
394
+ # create the infrastructure for EMPLOYEES table which includes the schema and partition tables
395
+
396
+ Employee.create_infrastructure
397
+
398
+ # You should have the following schema:
399
+ # employees_partitions
400
+
401
+ # Create a partition tables with increments of 10 records, because
402
+ # Employee.partition_table_size returns 10
403
+ ids = Employee.partition_generate_range(0, $total_records, $partition_table_size)
404
+ Employee.create_new_partition_tables(ids)
405
+
406
+ # You should have the following tables:
407
+ # employees_partitions.p0
408
+ # employees_partitions.p10
409
+ # employees_partitions.p20
410
+ # ...
411
+ # employees_partitions.p4980
412
+ # employees_partitions.p4990
413
+ # employees_partitions.p5000
414
+
415
+ # now add some employees across the year.
416
+
417
+ employees = []
418
+
419
+ require File.expand_path(File.dirname(__FILE__) + "/lib/roman")
420
+
421
+ # generates data for employees_partitions and employees tables
422
+
423
+ base = 0
424
+ (1..$create_many).each do |i|
425
+ employees << {
426
+ :name => "Winston J. Sillypants, #{to_roman(base+i)}",
427
+ :salary => rand(80000) + 60000,
428
+ :company_id => company_ids[rand company_ids.length]
429
+ }
430
+ end
431
+
432
+ puts "creating many #{$create_many}"
433
+ Employee.create_many(employees)
434
+ base += $create_many
435
+
436
+ puts "creating individual #{$create_individual}"
437
+ (1..$create_individual).each do |i|
438
+ employee_data = {
439
+ :name => "Jonathan Crabapple, #{to_roman(base+i)}",
440
+ :salary => rand(80000) + 60000,
441
+ :company_id => company_ids[rand company_ids.length]
442
+ }
443
+ employees << Employee.create(employee_data)
444
+ end
445
+ base += $create_individual
446
+
447
+ puts "new individual #{$new_individual}"
448
+ (1..$new_individual).each do |i|
449
+ employee_data = {
450
+ :name => "Picholine Pimplenad, #{to_roman(base+i)}",
451
+ :salary => rand(80000) + 60000,
452
+ :company_id => company_ids[rand company_ids.length]
453
+ }
454
+ employee = Employee.new(employee_data)
455
+ employee.save!
456
+ employees << employee
457
+ end
458
+ base += $new_individual
459
+
460
+ updates = {}
461
+ puts "update many #{$update_many}"
462
+ (1..$update_many).each do |i|
463
+ employee_record = employees[rand(employees.length)]
464
+ updates[{ :id => employee_record[:id]}] = { :salary => 100 }
465
+ end
466
+
467
+ Employee.update_many(updates, {:set_array => '"salary = #{table_name}.salary + datatable.salary, updated_at = now()"'})
468
+
469
+ puts "update individual #{$update_individual}"
470
+ (1..$update_individual).each do |i|
471
+ employee_record = employees[rand(employees.length)]
472
+ employee = Employee.from_partition(employee_record[:id]).find(employee_record[:id])
473
+ employee.salary += 1000
474
+ employee.save
475
+ end