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.
- data/Gemfile +17 -0
- data/LICENSE +30 -0
- data/PARTITIONING_EXPLAINED.txt +351 -0
- data/README +111 -0
- data/Rakefile +27 -0
- data/examples/README +23 -0
- data/examples/company_id.rb +417 -0
- data/examples/company_id_and_created_at.rb +689 -0
- data/examples/created_at.rb +590 -0
- data/examples/created_at_referencing_awards.rb +1000 -0
- data/examples/id.rb +475 -0
- data/examples/lib/by_company_id.rb +11 -0
- data/examples/lib/command_line_tool_mixin.rb +71 -0
- data/examples/lib/company.rb +29 -0
- data/examples/lib/get_options.rb +44 -0
- data/examples/lib/roman.rb +41 -0
- data/examples/start_date.rb +621 -0
- data/init.rb +1 -0
- data/lib/monkey_patch_activerecord.rb +92 -0
- data/lib/monkey_patch_postgres.rb +73 -0
- data/lib/partitioned.rb +26 -0
- data/lib/partitioned/active_record_overrides.rb +34 -0
- data/lib/partitioned/bulk_methods_mixin.rb +288 -0
- data/lib/partitioned/by_created_at.rb +13 -0
- data/lib/partitioned/by_foreign_key.rb +21 -0
- data/lib/partitioned/by_id.rb +35 -0
- data/lib/partitioned/by_integer_field.rb +32 -0
- data/lib/partitioned/by_monthly_time_field.rb +23 -0
- data/lib/partitioned/by_time_field.rb +65 -0
- data/lib/partitioned/by_weekly_time_field.rb +30 -0
- data/lib/partitioned/multi_level.rb +20 -0
- data/lib/partitioned/multi_level/configurator/data.rb +14 -0
- data/lib/partitioned/multi_level/configurator/dsl.rb +32 -0
- data/lib/partitioned/multi_level/configurator/reader.rb +162 -0
- data/lib/partitioned/multi_level/partition_manager.rb +47 -0
- data/lib/partitioned/partitioned_base.rb +354 -0
- data/lib/partitioned/partitioned_base/configurator.rb +6 -0
- data/lib/partitioned/partitioned_base/configurator/data.rb +62 -0
- data/lib/partitioned/partitioned_base/configurator/dsl.rb +628 -0
- data/lib/partitioned/partitioned_base/configurator/reader.rb +209 -0
- data/lib/partitioned/partitioned_base/partition_manager.rb +138 -0
- data/lib/partitioned/partitioned_base/sql_adapter.rb +286 -0
- data/lib/partitioned/version.rb +3 -0
- data/lib/tasks/desirable_tasks.rake +4 -0
- data/partitioned.gemspec +21 -0
- data/spec/dummy/.rspec +1 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +9 -0
- data/spec/dummy/app/assets/stylesheets/application.css +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +51 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +32 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +30 -0
- data/spec/dummy/config/environments/production.rb +60 -0
- data/spec/dummy/config/environments/test.rb +39 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +58 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/dummy/spec/spec_helper.rb +27 -0
- data/spec/monkey_patch_posgres_spec.rb +176 -0
- data/spec/partitioned/bulk_methods_mixin_spec.rb +512 -0
- data/spec/partitioned/by_created_at_spec.rb +62 -0
- data/spec/partitioned/by_foreign_key_spec.rb +95 -0
- data/spec/partitioned/by_id_spec.rb +97 -0
- data/spec/partitioned/by_integer_field_spec.rb +143 -0
- data/spec/partitioned/by_monthly_time_field_spec.rb +100 -0
- data/spec/partitioned/by_time_field_spec.rb +182 -0
- data/spec/partitioned/by_weekly_time_field_spec.rb +100 -0
- data/spec/partitioned/multi_level/configurator/dsl_spec.rb +88 -0
- data/spec/partitioned/multi_level/configurator/reader_spec.rb +147 -0
- data/spec/partitioned/partitioned_base/configurator/dsl_spec.rb +459 -0
- data/spec/partitioned/partitioned_base/configurator/reader_spec.rb +513 -0
- data/spec/partitioned/partitioned_base/sql_adapter_spec.rb +204 -0
- data/spec/partitioned/partitioned_base_spec.rb +173 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/support/shared_example_spec_helper_for_integer_key.rb +137 -0
- data/spec/support/shared_example_spec_helper_for_time_key.rb +147 -0
- data/spec/support/tables_spec_helper.rb +47 -0
- 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
|
data/spec/spec_helper.rb
ADDED
|
@@ -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
|