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,62 @@
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 ByCreatedAt do
8
+
9
+ include TablesSpecHelper
10
+
11
+ module CreatedAt
12
+ class Employee < Partitioned::ByCreatedAt
13
+ belongs_to :company, :class_name => 'Company'
14
+ attr_accessible :company_id, :name, :created_at
15
+
16
+ partitioned do |partition|
17
+ partition.index :id, :unique => true
18
+ partition.foreign_key :company_id
19
+ end
20
+ end # Employee
21
+ end # CreatedAt
22
+
23
+ before(:all) do
24
+ @employee = CreatedAt::Employee
25
+ create_tables
26
+ dates = @employee.partition_generate_range(DATE_NOW,
27
+ DATE_NOW + 7.days)
28
+ @employee.create_new_partition_tables(dates)
29
+ ActiveRecord::Base.connection.execute <<-SQL
30
+ insert into employees_partitions.
31
+ p#{DATE_NOW.at_beginning_of_week.strftime('%Y%m%d')}
32
+ (company_id,name) values (1,'Keith');
33
+ SQL
34
+ end
35
+
36
+ after(:all) do
37
+ drop_tables
38
+ end
39
+
40
+ let(:class_by_created_at) { ::Partitioned::ByCreatedAt }
41
+
42
+ describe "model is abstract class" do
43
+
44
+ it "returns true" do
45
+ class_by_created_at.abstract_class.should be_true
46
+ end
47
+
48
+ end # model is abstract class
49
+
50
+ describe "#partition_time_field" do
51
+
52
+ it "returns :created_at" do
53
+ class_by_created_at.partition_time_field.should == :created_at
54
+ end
55
+
56
+ end # #partition_time_field
57
+
58
+ it_should_behave_like "check that basic operations with postgres works correctly for time key", CreatedAt::Employee
59
+
60
+ end # ByCreatedAt
61
+
62
+ end # Partitioned
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+ require "#{File.dirname(__FILE__)}/../support/tables_spec_helper"
3
+ require "#{File.dirname(__FILE__)}/../support/shared_example_spec_helper_for_integer_key"
4
+
5
+ module Partitioned
6
+
7
+ describe ByForeignKey do
8
+
9
+ include TablesSpecHelper
10
+
11
+ module ForeignKey
12
+ class Employee < ByForeignKey
13
+ belongs_to :company, :class_name => 'Company'
14
+ attr_accessible :name, :integer_field, :company_id
15
+
16
+ def self.partition_foreign_key
17
+ return :company_id
18
+ end
19
+
20
+ partitioned do |partition|
21
+ partition.foreign_key :company_id
22
+ end
23
+ end # Employee
24
+ end # ForeignKey
25
+
26
+ before(:all) do
27
+ @employee = ForeignKey::Employee
28
+ create_tables
29
+ @employee.create_new_partition_tables(Range.new(1, 3).step(@employee.partition_table_size))
30
+ ActiveRecord::Base.connection.execute <<-SQL
31
+ insert into employees_partitions.p1 (company_id,name) values (1,'Keith');
32
+ SQL
33
+ end
34
+
35
+ after(:all) do
36
+ drop_tables
37
+ end
38
+
39
+ let(:class_by_foreign_key) { ::Partitioned::ByForeignKey }
40
+
41
+ describe "model is abstract class" do
42
+
43
+ it "returns true" do
44
+ class_by_foreign_key.abstract_class.should be_true
45
+ end
46
+
47
+ end # model is abstract class
48
+
49
+ describe "#partition_foreign_key" do
50
+
51
+ it "raises MethodNotImplemented" do
52
+ lambda {
53
+ class_by_foreign_key.partition_foreign_key
54
+ }.should raise_error(MethodNotImplemented)
55
+ end
56
+
57
+ end # #partition_foreign_key
58
+
59
+ describe "partitioned block" do
60
+
61
+ context "checks data in the foreign_keys is Proc" do
62
+
63
+ it "returns Proc" do
64
+ class_by_foreign_key.configurator_dsl.data.foreign_keys.first.should be_is_a Proc
65
+ end
66
+
67
+ end # checks data in the foreign_keys is Proc
68
+
69
+ context "checks if there is data in the foreign_keys" do
70
+
71
+ let(:proc) do
72
+ class_by_foreign_key.configurator_dsl.data.foreign_keys.first.call(@employee, :id)
73
+ end
74
+
75
+ it "returns referencing_field" do
76
+ proc.referencing_field.should == :company_id
77
+ end
78
+
79
+ it "returns referenced_field" do
80
+ proc.referenced_field.should == :id
81
+ end
82
+
83
+ it "returns referencing_field" do
84
+ proc.referenced_table.should == "companies"
85
+ end
86
+
87
+ end # checks if there is data in the foreign_keys
88
+
89
+ end # partitioned block
90
+
91
+ it_should_behave_like "check that basic operations with postgres works correctly for integer key", ForeignKey::Employee
92
+
93
+ end # ByForeignKey
94
+
95
+ end # Partitioned
@@ -0,0 +1,97 @@
1
+ require 'spec_helper'
2
+ require "#{File.dirname(__FILE__)}/../support/tables_spec_helper"
3
+ require "#{File.dirname(__FILE__)}/../support/shared_example_spec_helper_for_integer_key"
4
+
5
+ module Partitioned
6
+
7
+ describe ById do
8
+
9
+ include TablesSpecHelper
10
+
11
+ module Id
12
+ class Employee < ById
13
+ belongs_to :company, :class_name => 'Company'
14
+ attr_accessible :company_id, :name, :integer_field
15
+
16
+ def self.partition_table_size
17
+ return 1
18
+ end
19
+
20
+ partitioned do |partition|
21
+ partition.foreign_key :company_id
22
+ end
23
+ end # Employee
24
+ end # Id
25
+
26
+ before(:all) do
27
+ @employee = Id::Employee
28
+ create_tables
29
+ @employee.create_new_partition_tables(Range.new(1, 5).step(@employee.partition_table_size))
30
+ ActiveRecord::Base.connection.execute <<-SQL
31
+ insert into employees_partitions.p1 (company_id,name) values (1,'Keith');
32
+ SQL
33
+ end
34
+
35
+ after(:all) do
36
+ drop_tables
37
+ end
38
+
39
+ let(:class_by_id) { ::Partitioned::ById }
40
+
41
+ describe "model is abstract class" do
42
+
43
+ it "returns true" do
44
+ class_by_id.abstract_class.should be_true
45
+ end
46
+
47
+ end # model is abstract class
48
+
49
+ describe "#prefetch_primary_key?" do
50
+
51
+ context "is :id set as a primary_key" do
52
+
53
+ it "returns true" do
54
+ class_by_id.prefetch_primary_key?.should be_true
55
+ end
56
+
57
+ end # is :id set as a primary_key
58
+
59
+ end # #prefetch_primary_key?
60
+
61
+ describe "#partition_table_size" do
62
+
63
+ it "returns 10000000" do
64
+ class_by_id.partition_table_size.should == 10000000
65
+ end
66
+
67
+ end # #partition_table_size
68
+
69
+ describe "#partition_integer_field" do
70
+
71
+ it "returns :id" do
72
+ class_by_id.partition_integer_field.should == :id
73
+ end
74
+
75
+ end # #partition_integer_field
76
+
77
+ describe "partitioned block" do
78
+
79
+ context "checks if there is data in the indexes field" do
80
+
81
+ it "returns :id" do
82
+ class_by_id.configurator_dsl.data.indexes.first.field.should == :id
83
+ end
84
+
85
+ it "returns { :unique => true }" do
86
+ class_by_id.configurator_dsl.data.indexes.first.options.should == { :unique => true }
87
+ end
88
+
89
+ end # checks if there is data in the indexes field
90
+
91
+ end # partitioned block
92
+
93
+ it_should_behave_like "check that basic operations with postgres works correctly for integer key", Id::Employee
94
+
95
+ end # ById
96
+
97
+ end # Partitioned
@@ -0,0 +1,143 @@
1
+ require 'spec_helper'
2
+ require "#{File.dirname(__FILE__)}/../support/tables_spec_helper"
3
+ require "#{File.dirname(__FILE__)}/../support/shared_example_spec_helper_for_integer_key"
4
+
5
+ module Partitioned
6
+
7
+ describe ByIntegerField do
8
+
9
+ include TablesSpecHelper
10
+
11
+ module IntegerField
12
+ class Employee < Partitioned::ByIntegerField
13
+ belongs_to :company, :class_name => 'Company'
14
+ attr_accessible :name, :integer_field, :company_id
15
+
16
+ def self.partition_integer_field
17
+ return :integer_field
18
+ end
19
+
20
+ partitioned do |partition|
21
+ partition.index :id, :unique => true
22
+ end
23
+ end # Employee
24
+ end # IntegerField
25
+
26
+ before(:all) do
27
+ create_tables
28
+ @employee = IntegerField::Employee
29
+ @employee.create_new_partition_tables(Range.new(1, 4).step(@employee.partition_table_size))
30
+ ActiveRecord::Base.connection.execute <<-SQL
31
+ insert into employees_partitions.p1 (integer_field,company_id,name) values (1,1,'Keith');
32
+ SQL
33
+ end
34
+
35
+ after(:all) do
36
+ drop_tables
37
+ end
38
+
39
+ let(:class_by_integer_field) { ::Partitioned::ByIntegerField }
40
+
41
+ describe "model is abstract class" do
42
+
43
+ it "returns true" do
44
+ class_by_integer_field.abstract_class.should be_true
45
+ end
46
+
47
+ end # model is abstract class
48
+
49
+ describe "#partition_table_size" do
50
+
51
+ it "returns 1" do
52
+ class_by_integer_field.partition_table_size.should == 1
53
+ end
54
+
55
+ end # #partition_table_size
56
+
57
+ describe "#partition_integer_field" do
58
+
59
+ it "raises MethodNotImplemented" do
60
+ lambda {
61
+ class_by_integer_field.partition_integer_field
62
+ }.should raise_error(MethodNotImplemented)
63
+ end
64
+
65
+ end # #partition_integer_field
66
+
67
+ describe "#partition_normalize_key_value" do
68
+
69
+ context "when call method with param equal five" do
70
+
71
+ it "returns 5" do
72
+ class_by_integer_field.partition_normalize_key_value(5).should == 5
73
+ end
74
+
75
+ end
76
+
77
+ end # #partition_normalize_key_value
78
+
79
+ describe "partitioned block" do
80
+
81
+ let(:data) do
82
+ class_by_integer_field.configurator_dsl.data
83
+ end
84
+
85
+ context "checks data in the on_field is Proc" do
86
+
87
+ it "returns Proc" do
88
+ data.on_field.should be_is_a Proc
89
+ end
90
+
91
+ end # checks data in the on_field is Proc
92
+
93
+ context "checks data in the check_constraint is Proc" do
94
+
95
+ it "returns Proc" do
96
+ data.check_constraint.should be_is_a Proc
97
+ end
98
+
99
+ end # checks data in the check_constraint is Proc
100
+
101
+ context "checks data in the on_field" do
102
+
103
+ it "returns on_field" do
104
+ data.on_field.call(@employee).should == :integer_field
105
+ end
106
+
107
+ end # checks data in the on_field
108
+
109
+ context "checks data in the last_partitions_order_by_clause" do
110
+
111
+ it "returns last_partitions_order_by_clause" do
112
+ data.last_partitions_order_by_clause.should == "substring(tablename, 2)::integer desc"
113
+ end
114
+
115
+ end # checks data in the last_partitions_order_by_clause
116
+
117
+ context "checks data in the check_constraint" do
118
+
119
+ it "returns check_constraint" do
120
+ data.check_constraint.call(@employee, 1).should == "( integer_field = 1 )"
121
+ end
122
+
123
+ end # checks data in the check_constraint
124
+
125
+ context "checks data in the check_constraint, when partition_table_size != 1" do
126
+
127
+ before do
128
+ @employee.stub!(:partition_table_size).and_return(2)
129
+ end
130
+
131
+ it "returns check_constraint" do
132
+ data.check_constraint.call(@employee, 1).should == "( integer_field >= 0 and integer_field < 2 )"
133
+ end
134
+
135
+ end # checks data in the check_constraint, when partition_table_size != 1
136
+
137
+ end # partitioned block
138
+
139
+ it_should_behave_like "check that basic operations with postgres works correctly for integer key", IntegerField::Employee
140
+
141
+ end # ByIntegerField
142
+
143
+ 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 ByMonthlyTimeField do
8
+
9
+ include TablesSpecHelper
10
+
11
+ module MonthlyTimeField
12
+ class Employee < Partitioned::ByMonthlyTimeField
13
+ belongs_to :company, :class_name => 'Company'
14
+ attr_accessible :company_id, :name, :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 # MonthlyTimeField
26
+
27
+ before(:all) do
28
+ @employee = MonthlyTimeField::Employee
29
+ create_tables
30
+ dates = @employee.partition_generate_range(DATE_NOW,
31
+ DATE_NOW + 1.month)
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_month.strftime('%Y%m')}
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_monthly_time_field) { ::Partitioned::ByMonthlyTimeField }
45
+
46
+ describe "model is abstract class" do
47
+
48
+ it "returns true" do
49
+ class_by_monthly_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 month" do
57
+ class_by_monthly_time_field.
58
+ partition_normalize_key_value(Date.parse('2011-01-05')).
59
+ should == Date.parse('2011-01-01')
60
+ end
61
+
62
+ end # #partition_normalize_key_value
63
+
64
+ describe "#partition_table_size" do
65
+
66
+ it "returns 1.month" do
67
+ class_by_monthly_time_field.partition_table_size.should == 1.month
68
+ end
69
+
70
+ end # #partition_table_size
71
+
72
+ describe "partitioned block" do
73
+
74
+ let(:data) do
75
+ class_by_monthly_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 on_field 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-02-05')).should == "201102"
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", MonthlyTimeField::Employee
97
+
98
+ end # ByMonthlyTimeField
99
+
100
+ end # Partitioned