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/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'Partitioned'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+
24
+
25
+
26
+ Bundler::GemHelper.install_tasks
27
+
data/examples/README ADDED
@@ -0,0 +1,23 @@
1
+ The directory holds examples of how to use the partitioned gem.
2
+
3
+ The lib directory contains:
4
+ by_company_id.rb - a partitioned model where the partition's key is the column company_id that references companies.
5
+ company.rb - an ActiveRecord model for the table companies.
6
+ roman.rb - some helper routines for generating roman numerals.
7
+
8
+ This directory holds executable rails scripts that create and populate partitioned tables. The scripts accept the following
9
+ parameters:
10
+ --force delete used tables before starting
11
+ --cleanup delete used tables and exit
12
+
13
+ The scripts are:
14
+ company_id.rb - table 'employees' partitioned by company_id
15
+ company_id_and_created_at.rb - table 'employees' has multi-level partitioning by company_id then created_at
16
+ created_at is grouped by week where weeks start on Monday.
17
+ created_at.rb - table 'employees' partitioned by created_at
18
+ created_at is grouped by week where weeks start on Monday.
19
+ created_at_referencing_awards.rb - table 'employees' partitioned by created_at and table 'awards' is partitioned
20
+ by created_at which a reference to specific child table of employees with the
21
+ created_at range.
22
+ id.rb - partitioned on 'id' grouping each 10 records into separate child tables.
23
+ start_date.rb - grouped by column start_date which is a date grouped by month.
@@ -0,0 +1,417 @@
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
+ # ./company_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 a company (company_id).
56
+ #
57
+ # Implementation:
58
+ #
59
+ # Class Employee inherits from the abstract class ByCompanyId,
60
+ # which supports partitioning.
61
+ #
62
+ # class Employee < ByCompanyId
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
+ # end
76
+ #
77
+ # Create a schema employees_partitions, within which to store all of our partitions:
78
+ #
79
+ # Employee.create_infrastructure
80
+ #
81
+ # Create a partitions for each company:
82
+ #
83
+ # company_ids = Company.all.map(&:id)
84
+ # Employee.create_new_partition_tables(company_ids)
85
+ #
86
+ # Each of partition has the same structure as that of the employees table:
87
+ #
88
+ # id | created_at | updated_at | name | salary | company_id
89
+ # ----+------------+------------+------+--------+------------
90
+ #
91
+ # CREATE TABLE "employees_partitions"."p1" (CHECK (( company_id = 1 ))) INHERITS (employees);
92
+ # CREATE UNIQUE INDEX "index_employees_partitions.p1_on_id" ON "employees_partitions"."p1" ("id");
93
+ # ALTER TABLE employees_partitions.p1 add foreign key (company_id) references companies(id);
94
+ #
95
+ # CREATE TABLE "employees_partitions"."p2" (CHECK (( company_id = 2 ))) INHERITS (employees);
96
+ # CREATE UNIQUE INDEX "index_employees_partitions.p2_on_id" ON "employees_partitions"."p2" ("id");
97
+ # ALTER TABLE employees_partitions.p2 add foreign key (company_id) references companies(id);
98
+ #
99
+ # CREATE TABLE "employees_partitions"."p3" (CHECK (( company_id = 3 ))) INHERITS (employees);
100
+ # CREATE UNIQUE INDEX "index_employees_partitions.p3_on_id" ON "employees_partitions"."p3" ("id");
101
+ # ALTER TABLE employees_partitions.p3 add foreign key (company_id) references companies(id);
102
+ #
103
+ # CREATE TABLE "employees_partitions"."p4" (CHECK (( company_id = 4 ))) INHERITS (employees);
104
+ # CREATE UNIQUE INDEX "index_employees_partitions.p4_on_id" ON "employees_partitions"."p4" ("id");
105
+ # ALTER TABLE employees_partitions.p4 add foreign key (company_id) references companies(id);
106
+ #
107
+ # Since we have done four records of companies in the table,
108
+ # we have four partitions:
109
+ #
110
+ # employees_partitions.p1
111
+ # employees_partitions.p2
112
+ # employees_partitions.p3
113
+ # employees_partitions.p4
114
+ #
115
+ # Each of partitions inherits from employees table,
116
+ # thus a new row will automatically be added to the employees table .
117
+ #
118
+ # To add data, we use the following constructions,
119
+ # in which employees and employee_data - a random data:
120
+ #
121
+ # create_many - allows you to add multiple records
122
+ # Employee.create_many(employees)
123
+ # create - allows you to add one record
124
+ # Employee.create(employee_data)
125
+ # new/save! - allows you to add one record without using "create" method
126
+ # employee = Employee.new(employee_data)
127
+ # employee.save!
128
+ #
129
+ # For update data, we use the following constructions,
130
+ # in which updates - a random data:
131
+ #
132
+ # update_many - allows you to update multiple records.
133
+ # :set_array - additional option, you may read the description
134
+ # of the method in the file update_many bulk_methods_mixin.rb about this option.
135
+ # Employee.update_many(updates, { :set_array => '"salary = #{table_name}.salary +
136
+ # datatable.salary, updated_at = now()"' })
137
+ #
138
+ # This construction using for update one record. You also may use update method.
139
+ # employee = Employee.from_partition(employee_record[:company_id]).find(employee_record[:id])
140
+ # employee.save
141
+ #
142
+ # The data get into the employees table ONLY through partition tables.
143
+ # You can not do an insert row into a table employees directly.
144
+ # For this purpose special restrictions are imposed on the table employees.
145
+ #
146
+ # Result:
147
+ #
148
+ # We have table companies:
149
+ #
150
+ # id | created_at | updated_at | name
151
+ # ---+----------------------------+------------+---------------------
152
+ # 1 | 2012-03-11 13:26:52.184347 | | Fluent Mobile, inc.
153
+ # 2 | 2012-03-11 13:26:52.184347 | | Fiksu, inc.
154
+ # 3 | 2012-03-11 13:26:52.184347 | | AppExchanger, inc.
155
+ # 4 | 2012-03-11 13:26:52.184347 | | FreeMyApps, inc.
156
+ #
157
+ # Table employees with random data from 1 to 5000:
158
+ #
159
+ # id | created_at | updated_at | name | salary | company_id
160
+ #------+----------------------------+----------------------------+-------------------------------------+-------------+------------
161
+ # 1 | 2012-03-26 11:26:30.704959 | 2012-03-26 11:26:45.519874 | Winston J. Sillypants, I | $106,363.00 | 4
162
+ # 2 | 2012-03-26 11:26:30.704959 | | Winston J. Sillypants, II | $103,767.00 | 3
163
+ # 3 | 2012-03-26 11:26:30.704959 | 2012-03-26 11:26:43.250032 | Winston J. Sillypants, III | $128,998.00 | 1
164
+ # ...
165
+ # 4998 | 2012-03-26 11:26:40.43347 | 2012-03-26 11:26:44.570338 | Picholine Pimplenad, MMMMCMXCVIII | $93,628.00 | 3
166
+ # 4999 | 2012-03-26 11:26:40.437824 | 2012-03-26 11:26:40.437824 | Picholine Pimplenad, MMMMCMXCIX | $133,964.00 | 3
167
+ # 5000 | 2012-03-26 11:26:40.441958 | 2012-03-26 11:26:40.441958 | Picholine Pimplenad, _V | $76,519.00 | 4
168
+ #
169
+ # Partition employees_partitions.p1 - partition where company_id = 1:
170
+ #
171
+ # id | created_at | updated_at | name | salary | company_id
172
+ #------+----------------------------+----------------------------+-------------------------------------+-------------+------------
173
+ # 3 | 2012-03-26 11:26:30.704959 | 2012-03-26 11:26:43.250032 | Winston J. Sillypants, III | $128,998.00 | 1
174
+ # 5 | 2012-03-26 11:26:30.704959 | | Winston J. Sillypants, V | $134,319.00 | 1
175
+ # 8 | 2012-03-26 11:26:30.704959 | | Winston J. Sillypants, VIII | $82,995.00 | 1
176
+ # ...
177
+ # 4988 | 2012-03-26 11:26:40.392319 | 2012-03-26 11:26:44.077802 | Picholine Pimplenad, MMMMCMLXXXVIII | $132,535.00 | 1
178
+ # 4994 | 2012-03-26 11:26:40.416951 | 2012-03-26 11:26:40.416951 | Picholine Pimplenad, MMMMCMXCIV | $105,119.00 | 1
179
+ # 4996 | 2012-03-26 11:26:40.425268 | 2012-03-26 11:26:40.425268 | Picholine Pimplenad, MMMMCMXCVI | $81,403.00 | 1
180
+ #
181
+ # Partition employees_partitions.p2 - partition where company_id = 2:
182
+ #
183
+ # id | created_at | updated_at | name | salary | company_id
184
+ #------+----------------------------+----------------------------+-------------------------------------+-------------+------------
185
+ # 4 | 2012-03-26 11:26:30.704959 | | Winston J. Sillypants, IV | $136,540.00 | 2
186
+ # 12 | 2012-03-26 11:26:30.704959 | | Winston J. Sillypants, XII | $103,200.00 | 2
187
+ # 13 | 2012-03-26 11:26:30.704959 | | Winston J. Sillypants, XIII | $139,077.00 | 2
188
+ # ...
189
+ # 4991 | 2012-03-26 11:26:40.40451 | 2012-03-26 11:26:42.057637 | Picholine Pimplenad, MMMMCMXCI | $122,115.00 | 2
190
+ # 4992 | 2012-03-26 11:26:40.408519 | 2012-03-26 11:26:40.408519 | Picholine Pimplenad, MMMMCMXCII | $90,176.00 | 2
191
+ # 4995 | 2012-03-26 11:26:40.421126 | 2012-03-26 12:26:49.969993 | Picholine Pimplenad, MMMMCMXCV | $86,410.00 | 2
192
+ #
193
+ #
194
+ # Partition employees_partitions.p3 - partition where company_id = 3:
195
+ #
196
+ # id | created_at | updated_at | name | salary | company_id
197
+ #------+----------------------------+----------------------------+-------------------------------------+-------------+------------
198
+ # 2 | 2012-03-26 11:26:30.704959 | | Winston J. Sillypants, II | $103,767.00 | 3
199
+ # 6 | 2012-03-26 11:26:30.704959 | | Winston J. Sillypants, VI | $67,280.00 | 3
200
+ # 9 | 2012-03-26 11:26:30.704959 | | Winston J. Sillypants, IX | $75,396.00 | 3
201
+ # ...
202
+ # 4990 | 2012-03-26 11:26:40.400746 | 2012-03-26 11:26:43.604349 | Picholine Pimplenad, MMMMCMXC | $95,882.00 | 3
203
+ # 4998 | 2012-03-26 11:26:40.43347 | 2012-03-26 11:26:44.570338 | Picholine Pimplenad, MMMMCMXCVIII | $93,628.00 | 3
204
+ # 4999 | 2012-03-26 11:26:40.437824 | 2012-03-26 11:26:40.437824 | Picholine Pimplenad, MMMMCMXCIX | $133,964.00 | 3
205
+ #
206
+ #
207
+ # Partition employees_partitions.p4 - partition where company_id = 4:
208
+ #
209
+ # id | created_at | updated_at | name | salary | company_id
210
+ #------+----------------------------+----------------------------+-------------------------------------+-------------+------------
211
+ # 1 | 2012-03-26 11:26:30.704959 | 2012-03-26 11:26:45.519874 | Winston J. Sillypants, I | $106,363.00 | 4
212
+ # 7 | 2012-03-26 11:26:30.704959 | | Winston J. Sillypants, VII | $111,585.00 | 4
213
+ # 17 | 2012-03-26 11:26:30.704959 | | Winston J. Sillypants, XVII | $135,812.00 | 4
214
+ # ...
215
+ # 4993 | 2012-03-26 11:26:40.412815 | 2012-03-26 11:26:40.412815 | Picholine Pimplenad, MMMMCMXCIII | $95,851.00 | 4
216
+ # 4997 | 2012-03-26 11:26:40.429356 | 2012-03-26 11:26:40.429356 | Picholine Pimplenad, MMMMCMXCVII | $84,564.00 | 4
217
+ # 5000 | 2012-03-26 11:26:40.441958 | 2012-03-26 11:26:40.441958 | Picholine Pimplenad, _V | $76,519.00 | 4
218
+ #
219
+
220
+ require File.expand_path(File.dirname(__FILE__) + "/lib/command_line_tool_mixin")
221
+ require File.expand_path(File.dirname(__FILE__) + "/lib/get_options")
222
+
223
+ include CommandLineToolMixin
224
+
225
+ $cleanup = false
226
+ $force = false
227
+ $create_many = 3000
228
+ $create_individual = 1000
229
+ $new_individual = 1000
230
+ $update_many = 1000
231
+ $update_individual = 1000
232
+
233
+ @options = {
234
+ "--cleanup" => {
235
+ :short => "-C",
236
+ :argument => GetoptLong::NO_ARGUMENT,
237
+ :note => "cleanup data in database and exit"
238
+ },
239
+ "--force" => {
240
+ :short => "-F",
241
+ :argument => GetoptLong::NO_ARGUMENT,
242
+ :note => "cleanup data in database before creating new data"
243
+ },
244
+ "--create-many" => {
245
+ :short => "-m",
246
+ :argument => GetoptLong::REQUIRED_ARGUMENT,
247
+ :note => "how many objects to create via create_many",
248
+ :argument_note => "NUMBER"
249
+ },
250
+ "--create-individual" => {
251
+ :short => "-i",
252
+ :argument => GetoptLong::REQUIRED_ARGUMENT,
253
+ :note => "how many objects to create via create",
254
+ :argument_note => "NUMBER"
255
+ },
256
+ "--new-individual" => {
257
+ :short => "-I",
258
+ :argument => GetoptLong::REQUIRED_ARGUMENT,
259
+ :note => "how many objects to create via new/save",
260
+ :argument_note => "NUMBER"
261
+ },
262
+ "--update-individual" => {
263
+ :short => "-u",
264
+ :argument => GetoptLong::REQUIRED_ARGUMENT,
265
+ :note => "how many objects to update individually",
266
+ :argument_note => "NUMBER"
267
+ },
268
+ "--update-many" => {
269
+ :short => "-U",
270
+ :argument => GetoptLong::REQUIRED_ARGUMENT,
271
+ :note => "how many objects to update via update_many",
272
+ :argument_note => "NUMBER"
273
+ },
274
+ }
275
+
276
+ command_line_options(@options) do |option,argument|
277
+ if option == '--cleanup'
278
+ $cleanup = true
279
+ elsif option == '--force'
280
+ $force = true
281
+ elsif option == '--create-many'
282
+ $create_many = argument.to_i
283
+ elsif option == '--create-individual'
284
+ $create_individual = argument.to_i
285
+ elsif option == '--new-individual'
286
+ $new_individual = argument.to_i
287
+ elsif option == '--update-individual'
288
+ $update_individual = argument.to_i
289
+ elsif option == '--update-many'
290
+ $update_many = argument.to_i
291
+ end
292
+ end
293
+
294
+ if $cleanup || $force
295
+ ActiveRecord::Base.connection.drop_schema("employees_partitions", :cascade => true) rescue nil
296
+ ActiveRecord::Base.connection.drop_table("employees") rescue nil
297
+ ActiveRecord::Base.connection.drop_table("companies") rescue nil
298
+ exit(0) if $cleanup
299
+ end
300
+
301
+ $total_records = $create_many + $create_individual + $new_individual
302
+
303
+ puts "total records: #{$total_records}"
304
+
305
+ # the ActiveRecord classes
306
+
307
+ require File.expand_path(File.dirname(__FILE__) + "/lib/company")
308
+ require File.expand_path(File.dirname(__FILE__) + "/lib/by_company_id")
309
+
310
+ class Employee < ByCompanyId
311
+ belongs_to :company, :class_name => 'Company'
312
+ attr_accessible :salary, :company_id, :name
313
+
314
+ connection.execute <<-SQL
315
+ create table employees
316
+ (
317
+ id serial not null primary key,
318
+ created_at timestamp not null default now(),
319
+ updated_at timestamp,
320
+ name text not null,
321
+ salary money not null,
322
+ company_id integer not null
323
+ );
324
+ SQL
325
+ end
326
+
327
+ # You should have the following tables:
328
+ # public.companies
329
+ # public.employees
330
+
331
+ # create the infrastructure for EMPLOYEES table which includes the schema and partition tables
332
+
333
+ Employee.create_infrastructure
334
+
335
+ # You should have the following schema:
336
+ # employees_partitions
337
+
338
+ # add some companies
339
+
340
+ Company.create_many(COMPANIES)
341
+ company_ids = Company.all.map(&:id)
342
+
343
+ # create the employees partitions dependant on the all companies
344
+
345
+ Employee.create_new_partition_tables(company_ids)
346
+
347
+ # You should have the following tables:
348
+ # employees_partitions.p1
349
+ # employees_partitions.p2
350
+ # employees_partitions.p3
351
+ # employees_partitions.p4
352
+
353
+ employees = []
354
+
355
+ require File.expand_path(File.dirname(__FILE__) + "/lib/roman")
356
+
357
+ # generates data for employees_partitions and employees tables
358
+
359
+ base = 0
360
+ (1..$create_many).each do |i|
361
+ employees << {
362
+ :name => "Winston J. Sillypants, #{to_roman(base+i)}",
363
+ :salary => rand(80000) + 60000,
364
+ :company_id => company_ids[rand company_ids.length]
365
+ }
366
+ end
367
+
368
+ puts "creating many #{$create_many}"
369
+ Employee.create_many(employees)
370
+ base += $create_many
371
+
372
+ puts "creating individual #{$create_individual}"
373
+ (1..$create_individual).each do |i|
374
+ employee_data = {
375
+ :name => "Jonathan Crabapple, #{to_roman(base+i)}",
376
+ :salary => rand(80000) + 60000,
377
+ :company_id => company_ids[rand company_ids.length]
378
+ }
379
+ employees << Employee.create(employee_data)
380
+ end
381
+ base += $create_individual
382
+
383
+ puts "new individual #{$new_individual}"
384
+ (1..$new_individual).each do |i|
385
+ employee_data = {
386
+ :name => "Picholine Pimplenad, #{to_roman(base+i)}",
387
+ :salary => rand(80000) + 60000,
388
+ :company_id => company_ids[rand company_ids.length]
389
+ }
390
+ employee = Employee.new(employee_data)
391
+ employee.save!
392
+ employees << employee
393
+ end
394
+ base += $new_individual
395
+
396
+ updates = {}
397
+ puts "update many #{$update_many}"
398
+ (1..$update_many).each do |i|
399
+ employee_record = employees[rand(employees.length)]
400
+ updates[{
401
+ :id => employee_record[:id],
402
+ :company_id => employee_record[:company_id]
403
+ }] = {
404
+ :salary => 100
405
+ }
406
+ end
407
+
408
+ Employee.update_many(updates, {:set_array => '"salary = #{table_name}.salary + datatable.salary, updated_at = now()"'})
409
+
410
+ puts "update individual #{$update_individual}"
411
+ (1..$update_individual).each do |i|
412
+ employee_record = employees[rand(employees.length)]
413
+ employee = Employee.from_partition(employee_record[:company_id]).find(employee_record[:id])
414
+ employee.salary += 1000
415
+ employee.save
416
+ end
417
+