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
@@ -0,0 +1,204 @@
1
+ require 'spec_helper'
2
+
3
+ module Partitioned
4
+ class PartitionedBase
5
+ describe SqlAdapter do
6
+
7
+ before(:all) do
8
+ class SqlAdapter
9
+ def last_n_partitions_order_by_clause
10
+ return configurator.last_partitions_order_by_clause
11
+ end
12
+ end
13
+ module Sql
14
+ class Employee < PartitionedBase
15
+ def self.partition_table_size
16
+ return 2
17
+ end
18
+
19
+ def self.partition_integer_field
20
+ return :id
21
+ end
22
+
23
+ partitioned do |partition|
24
+ partition.foreign_key :company_id
25
+ partition.index :id, :unique => true
26
+ partition.check_constraint lambda { |model, id|
27
+ value = model.partition_normalize_key_value(id)
28
+ if model.partition_table_size == 1
29
+ return "( #{model.partition_integer_field} = #{value} )"
30
+ else
31
+ return "( #{model.partition_integer_field} >= #{value} and #{model.partition_integer_field} < #{value + model.partition_table_size} )"
32
+ end
33
+ }
34
+ end
35
+ end
36
+ end # Sql
37
+ ActiveRecord::Base.connection.execute <<-SQL
38
+ create table employees
39
+ (
40
+ id serial not null primary key,
41
+ name text not null,
42
+ company_id integer not null
43
+ );
44
+ SQL
45
+ end
46
+
47
+ after(:all) do
48
+ ActiveRecord::Base.connection.execute <<-SQL
49
+ drop table employees;
50
+ SQL
51
+ Partitioned::PartitionedBase::Sql.send(:remove_const, :Employee)
52
+ end
53
+
54
+ let(:sql_adapter) { Sql::Employee::SqlAdapter.new( Sql::Employee) }
55
+
56
+ let(:check_existence_schema) do
57
+ ActiveRecord::Base.connection.execute <<-SQL
58
+ select oid from pg_catalog.pg_namespace where nspname='employees_partitions';
59
+ SQL
60
+ end
61
+
62
+ let(:create_new_schema) do
63
+ ActiveRecord::Base.connection.execute <<-SQL
64
+ create schema employees_partitions;
65
+ SQL
66
+ end
67
+
68
+ let(:check_existence_table) do
69
+ ActiveRecord::Base.connection.execute <<-SQL
70
+ SELECT relname
71
+ FROM pg_class
72
+ WHERE relname !~ '^(pg_|sql_)'
73
+ AND relkind = 'r';
74
+ SQL
75
+ end
76
+
77
+ let(:create_new_partition_table) do
78
+ ActiveRecord::Base.connection.execute <<-SQL
79
+ create table employees_partitions.p1(
80
+ id serial not null primary key
81
+ );
82
+ SQL
83
+ end
84
+
85
+ describe "ensure_always_fail_on_insert_exists" do
86
+ it "generates the db function" do
87
+ sql_adapter.ensure_always_fail_on_insert_exists
88
+ result = ActiveRecord::Base.connection.execute <<-SQL
89
+ SELECT routine_name FROM information_schema.routines
90
+ WHERE specific_schema NOT IN ('pg_catalog', 'information_schema')
91
+ AND type_udt_name != 'trigger';
92
+ SQL
93
+ result.values.first.should == ["always_fail_on_insert"]
94
+ end
95
+ end # ensure_always_fail_on_insert_exists
96
+
97
+ describe "create_partition_schema" do
98
+ it "created schema" do
99
+ sql_adapter.create_partition_schema
100
+ check_existence_schema.values.should_not be_blank
101
+ end
102
+ end # create_partition_schema
103
+
104
+ describe "partition_exists?" do
105
+
106
+ context "when partition table don't exist" do
107
+ it "returns false" do
108
+ sql_adapter.partition_exists?(1).should be_false
109
+ end
110
+ end # when partition table don't exist
111
+
112
+ context "when partition table exist" do
113
+ it "returns true" do
114
+ create_new_schema
115
+ create_new_partition_table
116
+ sql_adapter.partition_exists?(1).should be_true
117
+ end
118
+ end # when partition table exist
119
+ end # partition_exists?
120
+
121
+ describe "last_n_partition_names" do
122
+
123
+ context "when partition table don't exist" do
124
+ it "returns empty array" do
125
+ sql_adapter.last_n_partition_names.should == []
126
+ end
127
+ end # when partition table don't exist
128
+
129
+ context "when partition table exist" do
130
+ it "returns partition table name" do
131
+ create_new_schema
132
+ create_new_partition_table
133
+ sql_adapter.last_n_partition_names.should == ["p1"]
134
+ end
135
+ end # when partition table exist
136
+ end
137
+
138
+ describe "add_parent_table_rules" do
139
+ context "when try to insert row into table with rules" do
140
+ it "raises ActiveRecord::StatementInvalid" do
141
+ sql_adapter.add_parent_table_rules
142
+ lambda { ActiveRecord::Base.connection.execute <<-SQL
143
+ insert into employee (name) values ('name');
144
+ SQL
145
+ }.should raise_error(ActiveRecord::StatementInvalid)
146
+ end
147
+ end # when try to insert row into table with rules
148
+ end # add_parent_table_rules
149
+
150
+ describe "create_partition_table" do
151
+ it "created partition table" do
152
+ create_new_schema
153
+ lambda {
154
+ sql_adapter.create_partition_table(1)
155
+ }.should_not raise_error
156
+ check_existence_table.values.sort.should == [["employees"], ["p1"]].sort
157
+ end
158
+ end # create_partition_table
159
+
160
+ describe "drop_partition_table" do
161
+ it "deleted partition table" do
162
+ create_new_schema
163
+ sql_adapter.create_partition_table(1)
164
+ sql_adapter.drop_partition_table(1)
165
+ check_existence_table.values.should == [["employees"]]
166
+ end
167
+ end # drop_partition_table
168
+
169
+ describe "add_partition_table_index" do
170
+ it "added index for partition table" do
171
+ create_new_schema
172
+ sql_adapter.create_partition_table(1)
173
+ sql_adapter.add_partition_table_index(1)
174
+ result = ActiveRecord::Base.connection.execute <<-SQL
175
+ SELECT count(*) FROM pg_class
176
+ where relname = 'p1_id_udx'
177
+ SQL
178
+ result.values.should == [["1"]]
179
+ end
180
+ end # add_partition_table_index
181
+
182
+ describe "add_references_to_partition_table" do
183
+ it "added foreign key constraint" do
184
+ create_new_schema
185
+ sql_adapter.create_partition_table(1)
186
+ ActiveRecord::Base.connection.execute <<-SQL
187
+ create table companies
188
+ (
189
+ id serial not null primary key,
190
+ name text null
191
+ );
192
+ SQL
193
+ sql_adapter.add_references_to_partition_table(1)
194
+ result = ActiveRecord::Base.connection.execute <<-SQL
195
+ SELECT constraint_type FROM information_schema.table_constraints
196
+ WHERE table_name = 'p1' AND constraint_name = 'p1_company_id_fkey';
197
+ SQL
198
+ result.values.first.should == ["FOREIGN KEY"]
199
+ end
200
+ end # add_references_to_partition_table
201
+
202
+ end # SqlAdapter
203
+ end # PartitionedBase
204
+ end # Partitioned
@@ -0,0 +1,173 @@
1
+ require 'spec_helper'
2
+
3
+ module Partitioned
4
+ describe PartitionedBase do
5
+
6
+ before(:all) do
7
+ class Employee < PartitionedBase
8
+ end
9
+ end
10
+
11
+ after(:all) do
12
+ Partitioned.send(:remove_const, :Employee)
13
+ end
14
+
15
+ let(:class_partitioned_base) { ::Partitioned::PartitionedBase }
16
+
17
+ describe "model is abstract class" do
18
+
19
+ it "returns true" do
20
+ class_partitioned_base.abstract_class.should be_true
21
+ end
22
+
23
+ end # model is abstract class
24
+
25
+ describe "partitioned block" do
26
+
27
+ let(:data) do
28
+ class_partitioned_base.configurator_dsl.data
29
+ end
30
+
31
+ context "checks data in the schema_name" do
32
+
33
+ it "returns schema_name" do
34
+ data.schema_name.call(Employee).should == "employees_partitions"
35
+ end
36
+
37
+ end # checks data in the schema_name
38
+
39
+ context "checks data in the parent_table_name" do
40
+
41
+ it "returns parent_table_name" do
42
+ data.parent_table_name.call(Employee).should == "employees"
43
+ end
44
+
45
+ end # checks data in the parent_table_name
46
+
47
+ context "checks data in the parent_table_schema_name" do
48
+
49
+ it "returns parent_table_schema_name" do
50
+ data.parent_table_schema_name.call(Employee).should == "public"
51
+ end
52
+
53
+ end # checks data in the parent_table_schema_name
54
+
55
+ context "checks data in the name_prefix" do
56
+
57
+ it "returns name_prefix" do
58
+ data.name_prefix.call(Employee).should == "p"
59
+ end
60
+
61
+ end # checks data in the name_prefix
62
+
63
+ context "checks data in the part_name" do
64
+
65
+ it "returns part_name" do
66
+ data.part_name.call(Employee, 1).should == "p1"
67
+ end
68
+
69
+ end # checks data in the part_name
70
+
71
+ context "checks data in the table_name" do
72
+
73
+ it "returns table_name" do
74
+ data.table_name.call(Employee, 1).should == "employees_partitions.p1"
75
+ end
76
+
77
+ end # checks data in the table_name
78
+
79
+ context "checks data in the base_name" do
80
+
81
+ it "returns base_name" do
82
+ data.base_name.call(Employee, 1).should == "1"
83
+ end
84
+
85
+ end # checks data in the base_name
86
+ end # partitioned block
87
+
88
+ context "#partition_key_values" do
89
+
90
+ before do
91
+ class_partitioned_base.stub!(:partition_keys).and_return([:id])
92
+ end
93
+
94
+ context "call method with key that represented as a string" do
95
+
96
+ it "returns values" do
97
+ class_partitioned_base.partition_key_values( "id" => 1 ).should == [1]
98
+ end
99
+
100
+ end # call method with key that represented as a string
101
+
102
+ context "call method with key that represented as a symbol" do
103
+
104
+ it "returns values" do
105
+ class_partitioned_base.partition_key_values( :id => 2 ).should == [2]
106
+ end
107
+
108
+ end # call method with key that represented as a symbol
109
+
110
+ end # #partition_key_values
111
+
112
+ context "checks instance methods" do
113
+
114
+ before do
115
+ ActiveRecord::Base.connection.execute <<-SQL
116
+ create table employees (
117
+ id serial not null primary key,
118
+ created_at timestamp not null default now(),
119
+ updated_at timestamp,
120
+ name text not null
121
+ );
122
+ SQL
123
+ Employee.stub!(:partition_keys).and_return([:id])
124
+ @employee = Employee.new
125
+ end
126
+
127
+ context "partition_table_name" do
128
+
129
+ context "call method with attributes key that represented as a string" do
130
+
131
+ it "returns employees_partitions.p1" do
132
+ @employee.stub!(:attributes).and_return("id" => 1)
133
+ @employee.partition_table_name.should == "employees_partitions.p1"
134
+ end
135
+
136
+ end # call method with attributes key that represented as a string
137
+
138
+ context "call method with attributes key that represented as a symbol" do
139
+
140
+ it "returns employees_partitions.p2" do
141
+ @employee.stub!(:attributes).and_return(:id => 2)
142
+ @employee.partition_table_name.should == "employees_partitions.p2"
143
+ end
144
+
145
+ end # call method with attributes key that represented as a symbol
146
+
147
+ end # partition_table_name
148
+
149
+ context "dynamic_arel_table" do
150
+
151
+ context "call method with attributes key that represented as a string" do
152
+
153
+ it "returns arel table name employees_partitions.p1" do
154
+ @employee.stub!(:attributes).and_return("id" => 1)
155
+ @employee.dynamic_arel_table.name.should == "employees_partitions.p1"
156
+ end
157
+
158
+ end # call method with attributes key that represented as a string
159
+
160
+ context "call method with attributes key that represented as a symbol" do
161
+
162
+ it "returns arel table name employees_partitions.p2" do
163
+ @employee.stub!(:attributes).and_return(:id => 2)
164
+ @employee.dynamic_arel_table.name.should == "employees_partitions.p2"
165
+ end
166
+
167
+ end # call method with attributes key that represented as a symbol
168
+
169
+ end # dynamic_arel_table
170
+
171
+ end # checks instance methods
172
+ end # PartitionedBase
173
+ end # Partitioned
@@ -0,0 +1,32 @@
1
+ # This file is copied to spec/ when you run 'rails generate rspec:install'
2
+ ENV["RAILS_ENV"] ||= 'test'
3
+ require File.expand_path("../dummy/config/environment", __FILE__)
4
+ require 'rspec/rails'
5
+ require 'rspec/autorun'
6
+
7
+ # Requires supporting ruby files with custom matchers and macros, etc,
8
+ # in spec/support/ and its subdirectories.
9
+ Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
10
+
11
+ RSpec.configure do |config|
12
+ # ## Mock Framework
13
+ #
14
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
15
+ #
16
+ # config.mock_with :mocha
17
+ # config.mock_with :flexmock
18
+ # config.mock_with :rr
19
+
20
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
21
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
22
+
23
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
24
+ # examples within a transaction, remove the following line or assign false
25
+ # instead of true.
26
+ config.use_transactional_fixtures = true
27
+
28
+ # If true, the base class of anonymous controllers will be inferred
29
+ # automatically. This will be the default behavior in future versions of
30
+ # rspec-rails.
31
+ config.infer_base_class_for_anonymous_controllers = false
32
+ end
@@ -0,0 +1,137 @@
1
+ shared_examples_for "check that basic operations with postgres works correctly for integer key" do |class_name|
2
+
3
+ let!(:subject) do
4
+ class_name.reset_column_information
5
+ class_name
6
+ end
7
+
8
+ context "when try to create one record" do
9
+
10
+ it "record created" do
11
+ lambda { subject.create(:name => 'Phil', :company_id => 3, :integer_field => 2)
12
+ }.should_not raise_error
13
+ end
14
+
15
+ end # when try to create one record
16
+
17
+ context "when try to create one record using new/save" do
18
+
19
+ it "record created" do
20
+ lambda {
21
+ instance = subject.new(:name => 'Mike', :company_id => 1, :integer_field => 1)
22
+ instance.save!
23
+ }.should_not raise_error
24
+ end
25
+
26
+ end # when try to create one record using new/save
27
+
28
+ context "when try to create many records" do
29
+
30
+ it "records created" do
31
+ lambda { subject.create_many([
32
+ { :name => 'Alex', :company_id => 2, :integer_field => 4 },
33
+ { :name => 'Aaron', :company_id => 3, :integer_field => 2 }])
34
+ }.should_not raise_error
35
+ end
36
+
37
+ end # when try to create many records
38
+
39
+ context "when try to find a record with the search term is id" do
40
+
41
+ it "returns employee name" do
42
+ subject.find(1).name.should == "Keith"
43
+ end
44
+
45
+ end # when try to find a record with the search term is id
46
+
47
+ context "when try to find a record with the search term is name" do
48
+
49
+ it "returns employee name" do
50
+ subject.where(:name => 'Keith').first.name.should == "Keith"
51
+ end
52
+
53
+ end # when try to find a record with the search term is name
54
+
55
+ context "when try to find a record which is showing partition table" do
56
+
57
+ it "returns employee name" do
58
+ subject.from_partition(1).find(1).name.should == "Keith"
59
+ end
60
+
61
+ end # when try to find a record which is showing partition table
62
+
63
+ context "when try to update a record with id = 1" do
64
+
65
+ it "returns updated employee name" do
66
+ subject.update(1, :name => 'Kevin')
67
+ subject.find(1).name.should == "Kevin"
68
+ end
69
+
70
+ end # when try to update a record with id = 1
71
+
72
+ context "when try to update a record with update_many functions" do
73
+
74
+ it "returns updated employee name" do
75
+ subject.update_many( {
76
+ { :id => 1, :integer_field => 1, :company_id => 1 } => {
77
+ :name => 'Alex'
78
+ }
79
+ } )
80
+ subject.find(1).name.should == "Alex"
81
+ end
82
+
83
+ it "returns updated employee name" do
84
+ rows = [{
85
+ :id => 1,
86
+ :integer_field => 1,
87
+ :company_id => 1,
88
+ :name => 'Pit',
89
+ }]
90
+
91
+ options = {
92
+ :set_array => '"name = datatable.name"',
93
+ :where => '"#{table_name}.id = datatable.id"'
94
+ }
95
+ subject.update_many(rows, options)
96
+ subject.find(1).name.should == "Pit"
97
+ end
98
+
99
+ end # when try to update a record with update_many functions
100
+
101
+ context "when try to delete a record with id = 1" do
102
+
103
+ it "returns empty array" do
104
+ subject.delete(1)
105
+ subject.find(:all).should == []
106
+ end
107
+
108
+ end # when try to delete a record with id = 1
109
+
110
+ context "when try to create new record outside the range of partitions" do
111
+
112
+ it "raises ActiveRecord::StatementInvalid" do
113
+ lambda { subject.create_many([{ :name => 'Mark', :company_id => 13, :integer_field => 5 } ])
114
+ }.should raise_error(ActiveRecord::StatementInvalid)
115
+ end
116
+
117
+ end # when try to create new record outside the range of partitions
118
+
119
+ context "when try to update a record outside the range of partitions" do
120
+
121
+ it "raises ActiveRecord::RecordNotFound" do
122
+ lambda { subject.update(100500, :name => 'Kevin')
123
+ }.should raise_error(ActiveRecord::RecordNotFound)
124
+ end
125
+
126
+ end # when try to update a record outside the range of partitions
127
+
128
+ context "when try to find a record outside the range of partitions" do
129
+
130
+ it "raises ActiveRecord::StatementInvalid" do
131
+ lambda { subject.from_partition(8).find(1)
132
+ }.should raise_error(ActiveRecord::StatementInvalid)
133
+ end
134
+
135
+ end # when try to find a record outside the range of partitions
136
+
137
+ end # check that basic operations with postgres works correctly for integer key