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
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