partitioned 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. data/Gemfile +17 -0
  2. data/LICENSE +30 -0
  3. data/PARTITIONING_EXPLAINED.txt +351 -0
  4. data/README +111 -0
  5. data/Rakefile +27 -0
  6. data/examples/README +23 -0
  7. data/examples/company_id.rb +417 -0
  8. data/examples/company_id_and_created_at.rb +689 -0
  9. data/examples/created_at.rb +590 -0
  10. data/examples/created_at_referencing_awards.rb +1000 -0
  11. data/examples/id.rb +475 -0
  12. data/examples/lib/by_company_id.rb +11 -0
  13. data/examples/lib/command_line_tool_mixin.rb +71 -0
  14. data/examples/lib/company.rb +29 -0
  15. data/examples/lib/get_options.rb +44 -0
  16. data/examples/lib/roman.rb +41 -0
  17. data/examples/start_date.rb +621 -0
  18. data/init.rb +1 -0
  19. data/lib/monkey_patch_activerecord.rb +92 -0
  20. data/lib/monkey_patch_postgres.rb +73 -0
  21. data/lib/partitioned.rb +26 -0
  22. data/lib/partitioned/active_record_overrides.rb +34 -0
  23. data/lib/partitioned/bulk_methods_mixin.rb +288 -0
  24. data/lib/partitioned/by_created_at.rb +13 -0
  25. data/lib/partitioned/by_foreign_key.rb +21 -0
  26. data/lib/partitioned/by_id.rb +35 -0
  27. data/lib/partitioned/by_integer_field.rb +32 -0
  28. data/lib/partitioned/by_monthly_time_field.rb +23 -0
  29. data/lib/partitioned/by_time_field.rb +65 -0
  30. data/lib/partitioned/by_weekly_time_field.rb +30 -0
  31. data/lib/partitioned/multi_level.rb +20 -0
  32. data/lib/partitioned/multi_level/configurator/data.rb +14 -0
  33. data/lib/partitioned/multi_level/configurator/dsl.rb +32 -0
  34. data/lib/partitioned/multi_level/configurator/reader.rb +162 -0
  35. data/lib/partitioned/multi_level/partition_manager.rb +47 -0
  36. data/lib/partitioned/partitioned_base.rb +354 -0
  37. data/lib/partitioned/partitioned_base/configurator.rb +6 -0
  38. data/lib/partitioned/partitioned_base/configurator/data.rb +62 -0
  39. data/lib/partitioned/partitioned_base/configurator/dsl.rb +628 -0
  40. data/lib/partitioned/partitioned_base/configurator/reader.rb +209 -0
  41. data/lib/partitioned/partitioned_base/partition_manager.rb +138 -0
  42. data/lib/partitioned/partitioned_base/sql_adapter.rb +286 -0
  43. data/lib/partitioned/version.rb +3 -0
  44. data/lib/tasks/desirable_tasks.rake +4 -0
  45. data/partitioned.gemspec +21 -0
  46. data/spec/dummy/.rspec +1 -0
  47. data/spec/dummy/README.rdoc +261 -0
  48. data/spec/dummy/Rakefile +7 -0
  49. data/spec/dummy/app/assets/javascripts/application.js +9 -0
  50. data/spec/dummy/app/assets/stylesheets/application.css +7 -0
  51. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  52. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  53. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  54. data/spec/dummy/config.ru +4 -0
  55. data/spec/dummy/config/application.rb +51 -0
  56. data/spec/dummy/config/boot.rb +10 -0
  57. data/spec/dummy/config/database.yml +32 -0
  58. data/spec/dummy/config/environment.rb +5 -0
  59. data/spec/dummy/config/environments/development.rb +30 -0
  60. data/spec/dummy/config/environments/production.rb +60 -0
  61. data/spec/dummy/config/environments/test.rb +39 -0
  62. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  63. data/spec/dummy/config/initializers/inflections.rb +10 -0
  64. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  65. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  66. data/spec/dummy/config/initializers/session_store.rb +8 -0
  67. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  68. data/spec/dummy/config/locales/en.yml +5 -0
  69. data/spec/dummy/config/routes.rb +58 -0
  70. data/spec/dummy/public/404.html +26 -0
  71. data/spec/dummy/public/422.html +26 -0
  72. data/spec/dummy/public/500.html +26 -0
  73. data/spec/dummy/public/favicon.ico +0 -0
  74. data/spec/dummy/script/rails +6 -0
  75. data/spec/dummy/spec/spec_helper.rb +27 -0
  76. data/spec/monkey_patch_posgres_spec.rb +176 -0
  77. data/spec/partitioned/bulk_methods_mixin_spec.rb +512 -0
  78. data/spec/partitioned/by_created_at_spec.rb +62 -0
  79. data/spec/partitioned/by_foreign_key_spec.rb +95 -0
  80. data/spec/partitioned/by_id_spec.rb +97 -0
  81. data/spec/partitioned/by_integer_field_spec.rb +143 -0
  82. data/spec/partitioned/by_monthly_time_field_spec.rb +100 -0
  83. data/spec/partitioned/by_time_field_spec.rb +182 -0
  84. data/spec/partitioned/by_weekly_time_field_spec.rb +100 -0
  85. data/spec/partitioned/multi_level/configurator/dsl_spec.rb +88 -0
  86. data/spec/partitioned/multi_level/configurator/reader_spec.rb +147 -0
  87. data/spec/partitioned/partitioned_base/configurator/dsl_spec.rb +459 -0
  88. data/spec/partitioned/partitioned_base/configurator/reader_spec.rb +513 -0
  89. data/spec/partitioned/partitioned_base/sql_adapter_spec.rb +204 -0
  90. data/spec/partitioned/partitioned_base_spec.rb +173 -0
  91. data/spec/spec_helper.rb +32 -0
  92. data/spec/support/shared_example_spec_helper_for_integer_key.rb +137 -0
  93. data/spec/support/shared_example_spec_helper_for_time_key.rb +147 -0
  94. data/spec/support/tables_spec_helper.rb +47 -0
  95. metadata +250 -0
@@ -0,0 +1,182 @@
1
+ require 'spec_helper'
2
+ require "#{File.dirname(__FILE__)}/../support/tables_spec_helper"
3
+ require "#{File.dirname(__FILE__)}/../support/shared_example_spec_helper_for_time_key"
4
+
5
+ module Partitioned
6
+
7
+ describe ByTimeField do
8
+
9
+ include TablesSpecHelper
10
+
11
+ module TimeField
12
+ class Employee < Partitioned::ByTimeField
13
+ belongs_to :company, :class_name => 'Company'
14
+ attr_accessible :created_at, :name, :company_id
15
+
16
+ def self.partition_time_field
17
+ return :created_at
18
+ end
19
+
20
+ partitioned do |partition|
21
+ partition.index :id, :unique => true
22
+ partition.foreign_key :company_id
23
+ end
24
+ end # Employee
25
+ end # TimeField
26
+
27
+ before(:all) do
28
+ @employee = TimeField::Employee
29
+ create_tables
30
+ dates = @employee.partition_generate_range(DATE_NOW,
31
+ DATE_NOW + 1.day)
32
+ @employee.create_new_partition_tables(dates)
33
+ ActiveRecord::Base.connection.execute <<-SQL
34
+ insert into employees_partitions.
35
+ p#{DATE_NOW.strftime('%Y%m%d')}
36
+ (company_id,name) values (1,'Keith');
37
+ SQL
38
+ end
39
+
40
+ after(:all) do
41
+ drop_tables
42
+ end
43
+
44
+ let(:class_by_time_field) { ::Partitioned::ByTimeField }
45
+
46
+ describe "model is abstract class" do
47
+
48
+ it "returns true" do
49
+ class_by_time_field.abstract_class.should be_true
50
+ end
51
+
52
+ end # model is abstract class
53
+
54
+ describe "#partition_generate_range" do
55
+
56
+ it "returns dates array" do
57
+ class_by_time_field.
58
+ partition_generate_range(Date.parse('2011-01-05'), Date.parse('2011-01-07')).
59
+ should == [Date.parse('2011-01-05'), Date.parse('2011-01-06'), Date.parse('2011-01-07')]
60
+ end
61
+
62
+ end # #partition_generate_range
63
+
64
+ describe "#partition_normalize_key_value" do
65
+
66
+ it "returns date" do
67
+ class_by_time_field.
68
+ partition_normalize_key_value(Date.parse('2011-01-05')).
69
+ should == Date.parse('2011-01-05')
70
+ end
71
+
72
+ end # #partition_normalize_key_value
73
+
74
+ describe "#partition_table_size" do
75
+
76
+ it "returns 1.day" do
77
+ class_by_time_field.partition_table_size.should == 1.day
78
+ end
79
+
80
+ end # #partition_table_size
81
+
82
+ describe "#partition_time_field" do
83
+
84
+ it "raises MethodNotImplemented" do
85
+ lambda {
86
+ class_by_time_field.partition_time_field
87
+ }.should raise_error(MethodNotImplemented)
88
+ end
89
+
90
+ end # #partition_time_field
91
+
92
+ describe "partitioned block" do
93
+
94
+ let(:data) do
95
+ class_by_time_field.configurator_dsl.data
96
+ end
97
+
98
+ context "checks data in the on_field is Proc" do
99
+
100
+ it "returns Proc" do
101
+ data.on_field.should be_is_a Proc
102
+ end
103
+
104
+ end # checks data in the on_field is Proc
105
+
106
+ context "checks data in the indexes is Proc" do
107
+
108
+ it "returns Proc" do
109
+ data.indexes.first.should be_is_a Proc
110
+ end
111
+
112
+ end # checks data in the indexes is Proc
113
+
114
+ context "checks data in the base_name is Proc" do
115
+
116
+ it "returns Proc" do
117
+ data.base_name.should be_is_a Proc
118
+ end
119
+
120
+ end # checks data in the base_name is Proc
121
+
122
+ context "checks data in the check_constraint is Proc" do
123
+
124
+ it "returns Proc" do
125
+ data.check_constraint.should be_is_a Proc
126
+ end
127
+
128
+ end # checks data in the check_constraint is Proc
129
+
130
+ context "checks data in the on_field" do
131
+
132
+ it "returns on_field" do
133
+ data.on_field.call(@employee).should == :created_at
134
+ end
135
+
136
+ end # checks data in the on_field
137
+
138
+ context "checks data in the indexes" do
139
+
140
+ it "returns :created_at" do
141
+ data.indexes.first.call(@employee, nil).field.should == :created_at
142
+ end
143
+
144
+ it "returns empty options hash" do
145
+ data.indexes.first.call(@employee, nil).options.should == {}
146
+ end
147
+
148
+ end # checks data in the indexes
149
+
150
+ context "checks data in the last_partitions_order_by_clause" do
151
+
152
+ it "returns last_partitions_order_by_clause" do
153
+ data.last_partitions_order_by_clause.should == "tablename desc"
154
+ end
155
+
156
+ end # checks data in the last_partitions_order_by_clause
157
+
158
+ context "checks data in the base_name" do
159
+
160
+ it "returns base_name" do
161
+ data.base_name.call(@employee, Date.parse('2011-01-05')).should == "20110105"
162
+ end
163
+
164
+ end # checks data in the base_name
165
+
166
+ context "checks data in the check_constraint" do
167
+
168
+ it "returns check_constraint" do
169
+ data.check_constraint.
170
+ call(@employee, Date.parse('2011-01-05')).
171
+ should == "created_at >= '2011-01-05' AND created_at < '2011-01-06'"
172
+ end
173
+
174
+ end # checks data in the check_constraint
175
+
176
+ end # partitioned block
177
+
178
+ it_should_behave_like "check that basic operations with postgres works correctly for time key", TimeField::Employee
179
+
180
+ end # ByTimeField
181
+
182
+ end # Partitioned
@@ -0,0 +1,100 @@
1
+ require 'spec_helper'
2
+ require "#{File.dirname(__FILE__)}/../support/tables_spec_helper"
3
+ require "#{File.dirname(__FILE__)}/../support/shared_example_spec_helper_for_time_key"
4
+
5
+ module Partitioned
6
+
7
+ describe ByWeeklyTimeField do
8
+
9
+ include TablesSpecHelper
10
+
11
+ module WeeklyTimeField
12
+ class Employee < ByWeeklyTimeField
13
+ belongs_to :company, :class_name => 'Company'
14
+ attr_accessible :name, :company_id, :created_at
15
+
16
+ def self.partition_time_field
17
+ return :created_at
18
+ end
19
+
20
+ partitioned do |partition|
21
+ partition.index :id, :unique => true
22
+ partition.foreign_key :company_id
23
+ end
24
+ end # Employee
25
+ end # WeeklyTimeField
26
+
27
+ before(:all) do
28
+ @employee = WeeklyTimeField::Employee
29
+ create_tables
30
+ dates = @employee.partition_generate_range(DATE_NOW,
31
+ DATE_NOW + 7.days)
32
+ @employee.create_new_partition_tables(dates)
33
+ ActiveRecord::Base.connection.execute <<-SQL
34
+ insert into employees_partitions.
35
+ p#{DATE_NOW.at_beginning_of_week.strftime('%Y%m%d')}
36
+ (company_id,name) values (1,'Keith');
37
+ SQL
38
+ end
39
+
40
+ after(:all) do
41
+ drop_tables
42
+ end
43
+
44
+ let(:class_by_weekly_time_field) { ::Partitioned::ByWeeklyTimeField }
45
+
46
+ describe "model is abstract class" do
47
+
48
+ it "returns true" do
49
+ class_by_weekly_time_field.abstract_class.should be_true
50
+ end
51
+
52
+ end # model is abstract class
53
+
54
+ describe "#partition_normalize_key_value" do
55
+
56
+ it "returns date with day set to 1st of the week" do
57
+ class_by_weekly_time_field.
58
+ partition_normalize_key_value(Date.parse('2011-01-05')).
59
+ should == Date.parse('2011-01-03')
60
+ end
61
+
62
+ end # #partition_normalize_key_value
63
+
64
+ describe "#partition_table_size" do
65
+
66
+ it "returns 1.week" do
67
+ class_by_weekly_time_field.partition_table_size.should == 1.week
68
+ end
69
+
70
+ end # #partition_table_size
71
+
72
+ describe "partitioned block" do
73
+
74
+ let(:data) do
75
+ class_by_weekly_time_field.configurator_dsl.data
76
+ end
77
+
78
+ context "checks data in the base_name is Proc" do
79
+
80
+ it "returns Proc" do
81
+ data.base_name.should be_is_a Proc
82
+ end
83
+
84
+ end # checks data in the base_name is Proc
85
+
86
+ context "checks data in the base_name" do
87
+
88
+ it "returns base_name" do
89
+ data.base_name.call(@employee, Date.parse('2011-01-05')).should == "20110103"
90
+ end
91
+
92
+ end # checks data in the base_name
93
+
94
+ end # partitioned block
95
+
96
+ it_should_behave_like "check that basic operations with postgres works correctly for time key", WeeklyTimeField::Employee
97
+
98
+ end # ByWeeklyTimeField
99
+
100
+ end # Partitioned
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+
3
+ describe Partitioned::MultiLevel::Configurator::Dsl do
4
+
5
+ before(:all) do
6
+ class Employee
7
+
8
+ end
9
+ end
10
+
11
+ after(:all) do
12
+ Object.send(:remove_const, :Employee)
13
+ end
14
+
15
+ let!(:dsl) { Partitioned::MultiLevel::Configurator::Dsl.new(Employee) }
16
+
17
+ describe "initialize" do
18
+
19
+ let!(:data_stubs) do
20
+ {
21
+ "on_field" => nil,
22
+ "indexes" => [],
23
+ "foreign_keys" => [],
24
+ "last_partitions_order_by_clause" => nil,
25
+ "schema_name" => nil,
26
+ "name_prefix" => nil,
27
+ "base_name" => nil,
28
+ "part_name" => nil,
29
+ "table_name" => nil,
30
+ "parent_table_schema_name" => nil,
31
+ "parent_table_name" => nil,
32
+ "check_constraint" => nil,
33
+ "encoded_name" => nil,
34
+ "using_classes" => []
35
+ }
36
+ end
37
+
38
+ context "when try to create the new object" do
39
+
40
+ context "check the model name" do
41
+
42
+ it "returns Employer" do
43
+ dsl.model.should == Employee
44
+ end
45
+
46
+ end # check the model name
47
+
48
+ context "check the object data" do
49
+
50
+ it "returns data" do
51
+ dsl.data.instance_values.should == data_stubs
52
+ end
53
+
54
+ end # check the object data
55
+
56
+ end # when try to create a new object
57
+
58
+ end # initialize
59
+
60
+ describe "on" do
61
+
62
+ context "when try to set the field which used to partition child tables" do
63
+
64
+ it "raises InvalidForMultiLevelPartitioning" do
65
+ lambda {
66
+ dsl.on
67
+ }.should raise_error(Partitioned::MultiLevel::Configurator::Dsl::InvalidForMultiLevelPartitioning)
68
+ end
69
+
70
+ end # when try to set the field which used to partition child tables
71
+
72
+ end # on
73
+
74
+ describe "using_classes" do
75
+
76
+ context "when try to set the using_classes field" do
77
+
78
+ it "returns using_classes" do
79
+ dsl.using_classes("ByCompanyId", "ByCreatedAt")
80
+ dsl.data.using_classes.first.should == "ByCompanyId"
81
+ dsl.data.using_classes.last.should == "ByCreatedAt"
82
+ end
83
+
84
+ end # when try to set the using_classes field
85
+
86
+ end # using_classes
87
+
88
+ end
@@ -0,0 +1,147 @@
1
+ require 'spec_helper'
2
+
3
+ module Partitioned
4
+ class MultiLevel
5
+ module Configurator
6
+ describe Reader do
7
+
8
+ before(:all) do
9
+ class Partitioned::ById
10
+ def self.partition_field
11
+ :id
12
+ end
13
+ def self.partition_table_size
14
+ return 1
15
+ end
16
+ end
17
+ class Partitioned::ByCreatedAt
18
+ def self.partition_field
19
+ :created_at
20
+ end
21
+ end
22
+ class Employee < MultiLevel
23
+ def self.first_partition_field
24
+ :id
25
+ end
26
+ def self.second_partition_field
27
+ :created_at
28
+ end
29
+ partitioned do |partition|
30
+ partition.index :id, :unique => true
31
+ partition.using_classes Partitioned::ById, Partitioned::ByCreatedAt
32
+ end
33
+ end
34
+ end
35
+
36
+ after(:all) do
37
+ Partitioned::MultiLevel::Configurator.send(:remove_const, :Employee)
38
+ end
39
+
40
+ let!(:reader) do
41
+ Partitioned::MultiLevel::Configurator::Reader.new(Employee)
42
+ end
43
+
44
+ describe "using_configurators" do
45
+
46
+ context "checking arrays length" do
47
+
48
+ it "returns 6" do
49
+ reader.send(:using_configurators).length.should == 6
50
+ end
51
+
52
+ end # checking array length
53
+
54
+ context "checking models class for each of using_configurators" do
55
+
56
+ it "returns 'Partitioned::ById'" do
57
+ for i in 0..2
58
+ reader.send(:using_configurators)[i].model.to_s.should == "Partitioned::ById"
59
+ end
60
+ end
61
+
62
+ it "returns 'Partitioned::ByCreatedAt'" do
63
+ for i in 3..5
64
+ reader.send(:using_configurators)[i].model.to_s.should == "Partitioned::ByCreatedAt"
65
+ end
66
+ end
67
+
68
+ end # checking models class for each of using_configurators
69
+
70
+ end # using_configurators
71
+
72
+ describe "on_fields" do
73
+
74
+ context "when on_field value is set by default" do
75
+
76
+ it "returns [:id, :created_at]" do
77
+ reader.on_fields.sort{|a,b| a.to_s <=> b.to_s}.
78
+ should == [:id, :created_at].sort{|a,b| a.to_s <=> b.to_s}
79
+ end
80
+
81
+ end # when on_filed value is set by default
82
+
83
+ end # on_fields
84
+
85
+ describe "parent_table_schema_name" do
86
+
87
+ context "when parent_table_schema_name value is set without options" do
88
+
89
+ it "returns public" do
90
+ reader.parent_table_schema_name.should == "public"
91
+ end
92
+
93
+ end # when parent_table_schema_name value is set by default
94
+
95
+ context "when parent_table_schema_name value is set with options" do
96
+
97
+ it "returns employees_partitions" do
98
+ reader.parent_table_schema_name(1, Date.parse("2011-01-03")).should == "employees_partitions"
99
+ end
100
+
101
+ end # when parent_table_schema_name value is set by value
102
+
103
+ end # parent_table_schema_name
104
+
105
+ describe "parent_table_name" do
106
+
107
+ context "when parent_table_name value is set without options" do
108
+
109
+ it "returns employees" do
110
+ reader.parent_table_name.should == "employees"
111
+ end
112
+
113
+ end # when parent_table_name value is set without options
114
+
115
+ context "when parent_table_name value is set with options" do
116
+
117
+ it "returns employees_partitions.p0" do
118
+ reader.parent_table_name(1, Date.parse("2011-01-03")).should == "employees_partitions.p1"
119
+ end
120
+
121
+ end # when parent_table_name value is set with options
122
+
123
+ end # parent_table_name
124
+
125
+ describe "check_constraint" do
126
+
127
+ it "returns check_constraint" do
128
+ reader.check_constraint(1).
129
+ should == "( id = 1 )"
130
+ reader.check_constraint(1, Date.parse('2011-10-10')).
131
+ should == "created_at >= '2011-10-10' AND created_at < '2011-10-17'"
132
+ end
133
+
134
+ end # check_constraint
135
+
136
+ describe "base_name" do
137
+
138
+ it "returns base_name" do
139
+ reader.base_name(1, Date.parse('2011-10-10')).should == "1_20111010"
140
+ end
141
+
142
+ end # base_name
143
+
144
+ end # Reader
145
+ end # Configurator
146
+ end # MultiLevel
147
+ end # Partitioned