sql_partitioner 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +61 -0
- data/.rspec +3 -0
- data/.travis.yml +10 -0
- data/CHANGELOG.md +30 -0
- data/Gemfile +4 -0
- data/LICENSE +19 -0
- data/README.md +119 -0
- data/Rakefile +6 -0
- data/lib/sql_partitioner/adapters/ar_adapter.rb +39 -0
- data/lib/sql_partitioner/adapters/base_adapter.rb +18 -0
- data/lib/sql_partitioner/adapters/dm_adapter.rb +24 -0
- data/lib/sql_partitioner/base_partitions_manager.rb +231 -0
- data/lib/sql_partitioner/loader.rb +16 -0
- data/lib/sql_partitioner/lock_wait_timeout_handler.rb +17 -0
- data/lib/sql_partitioner/partition.rb +158 -0
- data/lib/sql_partitioner/partitions_manager.rb +128 -0
- data/lib/sql_partitioner/sql_helper.rb +122 -0
- data/lib/sql_partitioner/time_unit_converter.rb +92 -0
- data/lib/sql_partitioner/version.rb +3 -0
- data/lib/sql_partitioner.rb +14 -0
- data/spec/db_conf.yml +7 -0
- data/spec/lib/spec_helper.rb +52 -0
- data/spec/lib/sql_partitioner/adapters/adapters_spec.rb +82 -0
- data/spec/lib/sql_partitioner/adapters/base_adapter_spec.rb +28 -0
- data/spec/lib/sql_partitioner/base_partitions_manager_spec.rb +442 -0
- data/spec/lib/sql_partitioner/loader_spec.rb +12 -0
- data/spec/lib/sql_partitioner/lock_wait_timeout_spec.rb +136 -0
- data/spec/lib/sql_partitioner/partition_spec.rb +268 -0
- data/spec/lib/sql_partitioner/partitions_manager_spec.rb +275 -0
- data/spec/lib/sql_partitioner/sql_helper_spec.rb +43 -0
- data/spec/lib/sql_partitioner/time_unit_converter_spec.rb +91 -0
- data/sql_partitioner.gemspec +47 -0
- metadata +234 -0
@@ -0,0 +1,268 @@
|
|
1
|
+
require File.expand_path("../spec_helper", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
shared_examples_for "PartitionCollection" do
|
4
|
+
before(:each) do
|
5
|
+
@partition_manager = SqlPartitioner::BasePartitionsManager.new(
|
6
|
+
:adapter => adapter,
|
7
|
+
:current_time => Time.utc(2014,04,18),
|
8
|
+
:table_name => 'test_events',
|
9
|
+
:logger => SPEC_LOGGER
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
context "with some partitions" do
|
14
|
+
before(:each) do
|
15
|
+
@partitions = {'until_2014_03_17' => 1395014400, 'until_2014_04_17' => 1397692800}
|
16
|
+
@sorted = SqlPartitioner::SQL.sort_partition_data(@partitions)
|
17
|
+
@newest_partition_ts = @sorted.last[1]
|
18
|
+
@oldest_partition_ts = @sorted.first[1]
|
19
|
+
@partition_manager.initialize_partitioning(@partitions)
|
20
|
+
@all_partitions = SqlPartitioner::Partition.all(adapter, 'test_events')
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#current_partition" do
|
24
|
+
it "should return nil when timestamp > newest partition.timestamp" do
|
25
|
+
@all_partitions.current_partition(@newest_partition_ts + 1).should == nil
|
26
|
+
end
|
27
|
+
it "should return nil when timestamp == newest partition.timestamp" do
|
28
|
+
@all_partitions.current_partition(@newest_partition_ts).should == nil
|
29
|
+
end
|
30
|
+
it "should return the newest partition when timestamp < newest partition.timestamp" do
|
31
|
+
@all_partitions.current_partition(@newest_partition_ts - 1).name.should == @sorted.last[0]
|
32
|
+
end
|
33
|
+
it "should return the oldest partition when timestamp < oldest partition.timestamp" do
|
34
|
+
@all_partitions.current_partition(@oldest_partition_ts - 1).name.should == @sorted.first[0]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#older_than_timestamp" do
|
39
|
+
it "should return nil when timestamp < oldest partition.timestamp" do
|
40
|
+
@all_partitions.older_than_timestamp(@oldest_partition_ts - 1).should == []
|
41
|
+
end
|
42
|
+
it "should return nil when timestamp == partition.timestamp" do
|
43
|
+
@all_partitions.older_than_timestamp(@oldest_partition_ts).should == []
|
44
|
+
end
|
45
|
+
it "should return the partition when timestamp > newest partition timestamp" do
|
46
|
+
@all_partitions.older_than_timestamp(@newest_partition_ts + 1).map{|p| [p.name, p.timestamp]}.should == [
|
47
|
+
['until_2014_03_17', 1395014400],
|
48
|
+
['until_2014_04_17', 1397692800],
|
49
|
+
]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#newer_than_timestamp" do
|
54
|
+
it "should return nil when timestamp > newest partition.timestamp" do
|
55
|
+
@all_partitions.newer_than_timestamp(@newest_partition_ts + 1).should == []
|
56
|
+
end
|
57
|
+
it "should return the newest partition when timestamp == partition.timestamp" do
|
58
|
+
@all_partitions.newer_than_timestamp(@newest_partition_ts).map{|p| [p.name, p.timestamp]}.should == [
|
59
|
+
['until_2014_04_17', 1397692800]
|
60
|
+
]
|
61
|
+
end
|
62
|
+
it "should return all the partition when timestamp < oldest partition timestamp" do
|
63
|
+
@all_partitions.newer_than_timestamp(@oldest_partition_ts - 1).map{|p| [p.name, p.timestamp]}.should == [
|
64
|
+
['until_2014_03_17', 1395014400],
|
65
|
+
['until_2014_04_17', 1397692800],
|
66
|
+
]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
describe "#non_future_partitions" do
|
74
|
+
before(:each) do
|
75
|
+
@partition_manager = SqlPartitioner::BasePartitionsManager.new(
|
76
|
+
:adapter => adapter,
|
77
|
+
:current_time => Time.utc(2014,04,18),
|
78
|
+
:table_name => 'test_events',
|
79
|
+
:logger => SPEC_LOGGER
|
80
|
+
)
|
81
|
+
|
82
|
+
@partitions = {'until_2014_03_17' => 1395014400}
|
83
|
+
@partition_manager.initialize_partitioning(@partitions)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should not return the future partition" do
|
87
|
+
SqlPartitioner::Partition.all(adapter, 'test_events').non_future_partitions.map{|p| [p.name, p.timestamp]}.should == [
|
88
|
+
['until_2014_03_17', 1395014400]
|
89
|
+
]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "#latest_partition" do
|
94
|
+
before(:each) do
|
95
|
+
@partition_manager = SqlPartitioner::BasePartitionsManager.new(
|
96
|
+
:adapter => adapter,
|
97
|
+
:current_time => Time.utc(2014,04,18),
|
98
|
+
:table_name => 'test_events',
|
99
|
+
:logger => SPEC_LOGGER
|
100
|
+
)
|
101
|
+
end
|
102
|
+
|
103
|
+
context "with some partitions" do
|
104
|
+
before(:each) do
|
105
|
+
@partitions = {'until_2014_03_17' => 1395014400, 'until_2014_04_17' => 1397692800}
|
106
|
+
@partition_manager.initialize_partitioning(@partitions)
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should return the latest partition" do
|
110
|
+
partition = SqlPartitioner::Partition.all(adapter, 'test_events').latest_partition
|
111
|
+
|
112
|
+
partition.name.should == 'until_2014_04_17'
|
113
|
+
partition.timestamp.should == 1397692800
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context "with no partitions" do
|
118
|
+
before(:each) do
|
119
|
+
@partition_manager.initialize_partitioning({})
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should not return the future partition" do
|
123
|
+
SqlPartitioner::Partition.all(adapter, 'test_events').latest_partition.should == nil
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "#oldest_partition" do
|
129
|
+
before(:each) do
|
130
|
+
@partition_manager = SqlPartitioner::BasePartitionsManager.new(
|
131
|
+
:adapter => adapter,
|
132
|
+
:current_time => Time.utc(2014,04,18),
|
133
|
+
:table_name => 'test_events',
|
134
|
+
:logger => SPEC_LOGGER
|
135
|
+
)
|
136
|
+
end
|
137
|
+
|
138
|
+
context "with some partitions" do
|
139
|
+
before(:each) do
|
140
|
+
@partitions = {'until_2014_03_17' => 1395014400, 'until_2014_04_17' => 1397692800}
|
141
|
+
@partition_manager.initialize_partitioning(@partitions)
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should the oldest partition" do
|
145
|
+
partition = SqlPartitioner::Partition.all(adapter, 'test_events').oldest_partition
|
146
|
+
|
147
|
+
partition.name.should == 'until_2014_03_17'
|
148
|
+
partition.timestamp.should == 1395014400
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
shared_examples_for "Partition" do
|
156
|
+
before(:each) do
|
157
|
+
@partition_manager = SqlPartitioner::BasePartitionsManager.new(
|
158
|
+
:adapter => adapter,
|
159
|
+
:current_time => Time.utc(2014,04,18),
|
160
|
+
:table_name => 'test_events',
|
161
|
+
:logger => SPEC_LOGGER
|
162
|
+
)
|
163
|
+
end
|
164
|
+
describe ".all" do
|
165
|
+
context "with no partitions" do
|
166
|
+
it "should an empty PartitionCollection" do
|
167
|
+
SqlPartitioner::Partition.all(adapter, 'test_events').should == []
|
168
|
+
end
|
169
|
+
end
|
170
|
+
context "with some partitions" do
|
171
|
+
before(:each) do
|
172
|
+
@partitions = {'until_2014_03_17' => 1395014400}
|
173
|
+
@partition_manager.initialize_partitioning(@partitions)
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should return a PartitionCollection containing all the partitions" do
|
177
|
+
SqlPartitioner::Partition.all(adapter, 'test_events').map{|p| [p.name, p.timestamp]}.should == [
|
178
|
+
['until_2014_03_17', 1395014400],
|
179
|
+
["future", "MAXVALUE"]
|
180
|
+
]
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
describe "#future_partition?" do
|
186
|
+
before(:each) do
|
187
|
+
@partitions = {'until_2014_03_17' => 1395014400}
|
188
|
+
@partition_manager.initialize_partitioning(@partitions)
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should return true for the future partition" do
|
192
|
+
SqlPartitioner::Partition.all(adapter, 'test_events').last.future_partition?.should == true
|
193
|
+
end
|
194
|
+
it "should return false for non-future partition" do
|
195
|
+
SqlPartitioner::Partition.all(adapter, 'test_events').first.future_partition?.should == false
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
describe "#timestamp" do
|
200
|
+
before(:each) do
|
201
|
+
@partitions = {'until_2014_03_17' => 1395014400}
|
202
|
+
@partition_manager.initialize_partitioning(@partitions)
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should return 'MAXVALUE' for the future partition" do
|
206
|
+
SqlPartitioner::Partition.all(adapter, 'test_events').last.timestamp.should == SqlPartitioner::Partition::FUTURE_PARTITION_VALUE
|
207
|
+
end
|
208
|
+
it "should return the timestamp for non-future partition" do
|
209
|
+
SqlPartitioner::Partition.all(adapter, 'test_events').first.timestamp.should == @partitions.values.last
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
describe "#to_log" do
|
214
|
+
before(:each) do
|
215
|
+
@partitions = {'until_2014_03_17' => 1395014400}
|
216
|
+
@partition_manager.initialize_partitioning(@partitions)
|
217
|
+
end
|
218
|
+
|
219
|
+
it "should return 'none' for no partitions" do
|
220
|
+
SqlPartitioner::Partition.to_log([]).should == 'none'
|
221
|
+
end
|
222
|
+
|
223
|
+
it "should return a pretty log message with partitions" do
|
224
|
+
log_msg = "---------------------------------------------------------------------------------------------\n" +
|
225
|
+
"ordinal_position name timestamp table_rows data_length index_length \n" +
|
226
|
+
"---------------------------------------------------------------------------------------------\n" +
|
227
|
+
"1 until_2014_03_17 1395014400 0 16384 0 \n" +
|
228
|
+
"2 future MAXVALUE 0 16384 0 \n" +
|
229
|
+
"---------------------------------------------------------------------------------------------"
|
230
|
+
|
231
|
+
SqlPartitioner::Partition.to_log(SqlPartitioner::Partition.all(adapter, 'test_events')).should == log_msg
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
236
|
+
|
237
|
+
|
238
|
+
describe "PartitionCollection with ARAdapter" do
|
239
|
+
it_should_behave_like "PartitionCollection" do
|
240
|
+
let(:adapter) do
|
241
|
+
SqlPartitioner::ARAdapter.new(ActiveRecord::Base.connection)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
describe "Partition with ARAdapter" do
|
247
|
+
it_should_behave_like "Partition" do
|
248
|
+
let(:adapter) do
|
249
|
+
SqlPartitioner::ARAdapter.new(ActiveRecord::Base.connection)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
describe "PartitionCollection with DMAdapter" do
|
255
|
+
it_should_behave_like "PartitionCollection" do
|
256
|
+
let(:adapter) do
|
257
|
+
SqlPartitioner::DMAdapter.new(DataMapper.repository.adapter)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
describe "Partition with DMAdapter" do
|
263
|
+
it_should_behave_like "Partition" do
|
264
|
+
let(:adapter) do
|
265
|
+
SqlPartitioner::DMAdapter.new(DataMapper.repository.adapter)
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
@@ -0,0 +1,275 @@
|
|
1
|
+
require File.expand_path("../spec_helper", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
shared_examples_for "PartitionsManager with an Adapter" do
|
4
|
+
describe "#initialize_partitioning_in_intervals" do
|
5
|
+
before(:each) do
|
6
|
+
@partition_manager = SqlPartitioner::PartitionsManager.new(
|
7
|
+
:adapter => adapter,
|
8
|
+
:current_time => Time.utc(2014,04,18),
|
9
|
+
:table_name => 'test_events',
|
10
|
+
:logger => SPEC_LOGGER
|
11
|
+
)
|
12
|
+
end
|
13
|
+
it "should initialize the database table as requested" do
|
14
|
+
days_into_future = 50
|
15
|
+
|
16
|
+
@partition_manager.initialize_partitioning_in_intervals(days_into_future)
|
17
|
+
|
18
|
+
SqlPartitioner::Partition.all(adapter, 'test_events').map{|p| [p.name, p.timestamp]}.should == [
|
19
|
+
["until_2014_05_18", Time.utc(2014,05,18).to_i],
|
20
|
+
["until_2014_06_18", Time.utc(2014,06,18).to_i],
|
21
|
+
["future", "MAXVALUE"]
|
22
|
+
]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
describe "#append_partition_intervals" do
|
26
|
+
before(:each) do
|
27
|
+
@partition_manager = SqlPartitioner::PartitionsManager.new(
|
28
|
+
:adapter => adapter,
|
29
|
+
:current_time => Time.utc(2014,04,18),
|
30
|
+
:table_name => 'test_events',
|
31
|
+
:logger => SPEC_LOGGER
|
32
|
+
)
|
33
|
+
end
|
34
|
+
context "with an unpartitioned database table" do
|
35
|
+
it "should raise a RuntimeError" do
|
36
|
+
lambda{
|
37
|
+
@partition_manager.append_partition_intervals(:months, 1, days_into_future = 30, dry_run = false)
|
38
|
+
}.should raise_error(RuntimeError, /initialized/)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
context "with a partitioned database table" do
|
42
|
+
context "and only the future partition exists" do
|
43
|
+
before(:each) do
|
44
|
+
@partition_manager.initialize_partitioning({})
|
45
|
+
end
|
46
|
+
it "should raise a RuntimeError" do
|
47
|
+
lambda{
|
48
|
+
@partition_manager.append_partition_intervals(:months, 1, days_into_future = 30, dry_run = false)
|
49
|
+
}.should raise_error(RuntimeError, /initialized/)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
context "and the future partition as well as other partitions exist" do
|
53
|
+
context "and all requested partitions already exist" do
|
54
|
+
before(:each) do
|
55
|
+
@partition_manager.initialize_partitioning({'until_2014_05_18' => Time.utc(2014,05,18).to_i})
|
56
|
+
end
|
57
|
+
it "should log and do nothing" do
|
58
|
+
expect(@partition_manager.append_partition_intervals(:months, 1, days_into_future = 30, dry_run = false)).to eq({})
|
59
|
+
end
|
60
|
+
end
|
61
|
+
context "and not all of the requested partitions exist yet" do
|
62
|
+
before(:each) do
|
63
|
+
@partition_manager.initialize_partitioning({'until_2014_05_18' => Time.utc(2014,05,18).to_i})
|
64
|
+
end
|
65
|
+
it "should log and do nothing" do
|
66
|
+
expect(@partition_manager.append_partition_intervals(:months, 1, days_into_future = 60, dry_run = false)).to eq({
|
67
|
+
'until_2014_06_18' => Time.utc(2014,06,18).to_i
|
68
|
+
})
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
describe "#drop_partitions_older_than_in_days" do
|
75
|
+
before(:each) do
|
76
|
+
@partition_manager = SqlPartitioner::PartitionsManager.new(
|
77
|
+
:adapter => adapter,
|
78
|
+
:current_time => Time.utc(2014,04,18),
|
79
|
+
:table_name => 'test_events',
|
80
|
+
:logger => SPEC_LOGGER
|
81
|
+
)
|
82
|
+
end
|
83
|
+
it "should drop the requested partition" do
|
84
|
+
@partition_manager.initialize_partitioning({
|
85
|
+
'until_2014_02_18' => Time.utc(2014,02,18).to_i,
|
86
|
+
'until_2014_03_18' => Time.utc(2014,03,18).to_i,
|
87
|
+
'until_2014_04_18' => Time.utc(2014,04,18).to_i
|
88
|
+
})
|
89
|
+
@partition_manager.drop_partitions_older_than_in_days(days_from_now = 40)
|
90
|
+
|
91
|
+
SqlPartitioner::Partition.all(adapter, 'test_events').map{|p| [p.name, p.timestamp]}.should == [
|
92
|
+
["until_2014_03_18", Time.utc(2014,03,18).to_i],
|
93
|
+
["until_2014_04_18", Time.utc(2014,04,18).to_i],
|
94
|
+
["future", "MAXVALUE"]
|
95
|
+
]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "#drop_partitions_older_than" do
|
100
|
+
before(:each) do
|
101
|
+
@partition_manager = SqlPartitioner::PartitionsManager.new(
|
102
|
+
:adapter => adapter,
|
103
|
+
:current_time => Time.utc(2014,04,18),
|
104
|
+
:table_name => 'test_events',
|
105
|
+
:logger => SPEC_LOGGER
|
106
|
+
)
|
107
|
+
end
|
108
|
+
context "with no partition requested to be dropped" do
|
109
|
+
before(:each) do
|
110
|
+
@partition_manager.initialize_partitioning({
|
111
|
+
'until_2014_03_18' => Time.utc(2014,03,18).to_i,
|
112
|
+
'until_2014_04_18' => Time.utc(2014,04,18).to_i
|
113
|
+
})
|
114
|
+
end
|
115
|
+
it "should not drop anything" do
|
116
|
+
expect(@partition_manager.drop_partitions_older_than(Time.utc(2014,03,18).to_i)).to eq []
|
117
|
+
end
|
118
|
+
end
|
119
|
+
context "with one partition requested to be dropped" do
|
120
|
+
before(:each) do
|
121
|
+
@partition_manager.initialize_partitioning({
|
122
|
+
'until_2014_03_18' => Time.utc(2014,03,18).to_i,
|
123
|
+
'until_2014_04_18' => Time.utc(2014,04,18).to_i
|
124
|
+
})
|
125
|
+
end
|
126
|
+
it "should drop the requeuest partition to be dropped" do
|
127
|
+
expect(@partition_manager.drop_partitions_older_than(Time.utc(2014,04,18).to_i)).to eq [
|
128
|
+
'until_2014_03_18'
|
129
|
+
]
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe "PartitionsManager with ARAdapter" do
|
136
|
+
it_should_behave_like "PartitionsManager with an Adapter" do
|
137
|
+
let(:adapter) do
|
138
|
+
SqlPartitioner::ARAdapter.new(ActiveRecord::Base.connection)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe "PartitionsManager with DMAdapter" do
|
144
|
+
it_should_behave_like "PartitionsManager with an Adapter" do
|
145
|
+
let(:adapter) do
|
146
|
+
SqlPartitioner::DMAdapter.new(DataMapper.repository.adapter)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe "PartitionsManager" do
|
152
|
+
before(:each) do
|
153
|
+
@adapter = Struct.new(:schema_name).new("sql_partitioner_test")
|
154
|
+
|
155
|
+
@partition_manager = SqlPartitioner::PartitionsManager.new(
|
156
|
+
:adapter => @adapter,
|
157
|
+
:current_time => Time.utc(2014,01,01),
|
158
|
+
:table_name => 'test_events',
|
159
|
+
:logger => SPEC_LOGGER
|
160
|
+
)
|
161
|
+
end
|
162
|
+
|
163
|
+
describe "#partitions_to_append" do
|
164
|
+
it "should return the partitions to create" do
|
165
|
+
partition_start_timestamp = Time.utc(2013,12,01).to_i
|
166
|
+
partition_size = 2
|
167
|
+
days_into_future = 32
|
168
|
+
|
169
|
+
expect(@partition_manager.partitions_to_append(partition_start_timestamp, :months, partition_size, days_into_future)).to eq({
|
170
|
+
"until_2014_02_01"=>Time.utc(2014,02,01).to_i,
|
171
|
+
"until_2014_04_01"=>Time.utc(2014,04,01).to_i
|
172
|
+
})
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe "#partitions_to_append_by_ts_range" do
|
177
|
+
context "with end_timestamp == partition_start_timestamp" do
|
178
|
+
before(:each) do
|
179
|
+
@start_ts = Time.utc(2014,01,01).to_i
|
180
|
+
@end_ts = Time.utc(2014,01,01).to_i
|
181
|
+
end
|
182
|
+
it "should create no partitions" do
|
183
|
+
expect(@partition_manager.partitions_to_append_by_ts_range(@start_ts, @end_ts, :months, 1)).to eq({})
|
184
|
+
end
|
185
|
+
end
|
186
|
+
context "with end_timestamp - partition_start_timestamp < partition_size_unit * partition_size" do
|
187
|
+
before(:each) do
|
188
|
+
@start_ts = Time.utc(2014,01,01).to_i
|
189
|
+
@end_ts = Time.utc(2014,01,02).to_i
|
190
|
+
end
|
191
|
+
it "should create 1 partition" do
|
192
|
+
expect(@partition_manager.partitions_to_append_by_ts_range(@start_ts, @end_ts, :months, 1)).to eq({
|
193
|
+
"until_2014_02_01"=>Time.utc(2014,02,01).to_i
|
194
|
+
}
|
195
|
+
)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
context "with end_timestamp - partition_start_timestamp == partition_size_unit * partition_size" do
|
199
|
+
before(:each) do
|
200
|
+
@start_ts = Time.utc(2014,01,01).to_i
|
201
|
+
@end_ts = Time.utc(2014,02,01).to_i
|
202
|
+
end
|
203
|
+
it "should create 1 partition to cover it" do
|
204
|
+
expect(@partition_manager.partitions_to_append_by_ts_range(@start_ts, @end_ts, :months, 1)).to eq({
|
205
|
+
"until_2014_02_01"=>Time.utc(2014,02,01).to_i
|
206
|
+
}
|
207
|
+
)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
context "with end_timestamp - partition_start_timestamp > partition_size_unit * partition_size" do
|
211
|
+
before(:each) do
|
212
|
+
@start_ts = Time.utc(2014,01,01).to_i
|
213
|
+
@end_ts = Time.utc(2014,03,01).to_i
|
214
|
+
end
|
215
|
+
context "with one months partition size" do
|
216
|
+
it "should create two partitions to cover two months in the future from start_ts" do
|
217
|
+
expect(@partition_manager.partitions_to_append_by_ts_range(@start_ts, @end_ts, :months, 1)).to eq({
|
218
|
+
"until_2014_02_01"=>Time.utc(2014,02,01).to_i,
|
219
|
+
"until_2014_03_01"=>Time.utc(2014,03,01).to_i
|
220
|
+
}
|
221
|
+
)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
context "with two months partition size" do
|
225
|
+
it "should create one partition to cover two months in the future from start_ts" do
|
226
|
+
expect(@partition_manager.partitions_to_append_by_ts_range(@start_ts, @end_ts, :months, 2)).to eq({
|
227
|
+
"until_2014_03_01"=>Time.utc(2014,03,01).to_i
|
228
|
+
}
|
229
|
+
)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
context "with 20 day partition size" do
|
233
|
+
it "should create three partitions to cover two months in the future from start_ts" do
|
234
|
+
expect(@partition_manager.partitions_to_append_by_ts_range(@start_ts, @end_ts, :days, 20)).to eq({
|
235
|
+
"until_2014_01_21" => Time.utc(2014,01,21).to_i,
|
236
|
+
"until_2014_02_10" => Time.utc(2014,02,10).to_i,
|
237
|
+
"until_2014_03_02" => Time.utc(2014,03,02).to_i
|
238
|
+
}
|
239
|
+
)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
context "with end_timestamp < partition_start_timestamp" do
|
244
|
+
before(:each) do
|
245
|
+
@start_ts = Time.utc(2014,02,01).to_i
|
246
|
+
@end_ts = Time.utc(2014,01,01).to_i
|
247
|
+
end
|
248
|
+
it "should create no partitions" do
|
249
|
+
expect(@partition_manager.partitions_to_append_by_ts_range(@start_ts, @end_ts, :months, 1)).to eq({})
|
250
|
+
end
|
251
|
+
end
|
252
|
+
context "with invalid parameters" do
|
253
|
+
it "should raise an Argument error with a start_ts < 0" do
|
254
|
+
lambda do
|
255
|
+
expect(@partition_manager.partitions_to_append_by_ts_range(start_ts = -1, end_ts = 1, :months, 1)).to eq({})
|
256
|
+
end.should raise_error(ArgumentError, /should be > 0/)
|
257
|
+
end
|
258
|
+
it "should raise an Argument error with a end_ts < 0" do
|
259
|
+
lambda do
|
260
|
+
expect(@partition_manager.partitions_to_append_by_ts_range(start_ts = 1, end_ts = -1, :months, 1)).to eq({})
|
261
|
+
end.should raise_error(ArgumentError, /should be > 0/)
|
262
|
+
end
|
263
|
+
it "should raise an Argument error with an invalid partition_size_unit" do
|
264
|
+
lambda do
|
265
|
+
expect(@partition_manager.partitions_to_append_by_ts_range(start_ts = 1, end_ts = 1, :potatoes, 1)).to eq({})
|
266
|
+
end.should raise_error(ArgumentError, /partition_size_unit must be one of/)
|
267
|
+
end
|
268
|
+
it "should raise an Argument error with an invalid partition_size" do
|
269
|
+
lambda do
|
270
|
+
expect(@partition_manager.partitions_to_append_by_ts_range(start_ts = 1, end_ts = 1, :months, -1)).to eq({})
|
271
|
+
end.should raise_error(ArgumentError, /should be > 0/)
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.expand_path("../spec_helper", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe "SqlHelper" do
|
4
|
+
before(:each) do
|
5
|
+
@table_name = 'my_table'
|
6
|
+
end
|
7
|
+
describe ".drop_partitions" do
|
8
|
+
it "should return nil when no partition_names are passed" do
|
9
|
+
SqlPartitioner::SQL.drop_partitions(@table_name, []).should == nil
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe ".reorg_partitions" do
|
14
|
+
it "should return nil when no partition_names are passed" do
|
15
|
+
SqlPartitioner::SQL.reorg_partitions(@table_name, [], "future").should == nil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe ".create_partition" do
|
20
|
+
it "should return something" do
|
21
|
+
SqlPartitioner::SQL.create_partition(@table_name, "until_2014_03_17", "future").should_not be_empty
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe ".sort_partition_data" do
|
26
|
+
before(:each) do
|
27
|
+
@partition_data = {
|
28
|
+
'until_2014_04_17' => 1397692800,
|
29
|
+
SqlPartitioner::BasePartitionsManager::FUTURE_PARTITION_NAME =>
|
30
|
+
SqlPartitioner::BasePartitionsManager::FUTURE_PARTITION_VALUE,
|
31
|
+
'until_2014_03_17' => 1395014400,
|
32
|
+
}
|
33
|
+
end
|
34
|
+
it "should sort into an array by timestamp (key) with the 'future' partition at the end" do
|
35
|
+
SqlPartitioner::SQL.sort_partition_data(@partition_data).should == [
|
36
|
+
['until_2014_03_17', 1395014400],
|
37
|
+
['until_2014_04_17', 1397692800],
|
38
|
+
[SqlPartitioner::BasePartitionsManager::FUTURE_PARTITION_NAME,
|
39
|
+
SqlPartitioner::BasePartitionsManager::FUTURE_PARTITION_VALUE],
|
40
|
+
]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require File.expand_path("../spec_helper", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe "TimeUnitConverter" do
|
4
|
+
describe "#initialize" do
|
5
|
+
it "should initalize a new TimeUnitConverter with a supported time unit" do
|
6
|
+
SqlPartitioner::TimeUnitConverter.new(SqlPartitioner::TimeUnitConverter::SUPPORTED_TIME_UNITS.first)
|
7
|
+
end
|
8
|
+
it "should raise an ArgumentError with with a unsupported time unit" do
|
9
|
+
lambda{ SqlPartitioner::TimeUnitConverter.new(:potatoes) }.should raise_error(ArgumentError)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#to_date_time" do
|
14
|
+
before(:each) do
|
15
|
+
@tuc = SqlPartitioner::TimeUnitConverter.new(:seconds)
|
16
|
+
end
|
17
|
+
it "should return a DateTime object" do
|
18
|
+
timestamp = Time.utc(2014,01,15).to_i
|
19
|
+
@tuc.to_date_time(timestamp).to_s.should == "2014-01-15T00:00:00+00:00"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
describe "#from_seconds" do
|
23
|
+
it "should return a timestamp in the configured time unit" do
|
24
|
+
timestamp_in_secs = Time.utc(2014,01,15).to_i
|
25
|
+
|
26
|
+
tum = SqlPartitioner::TimeUnitConverter.new(:micro_seconds)
|
27
|
+
tum.from_seconds(timestamp_in_secs).should == timestamp_in_secs * 1_000_000
|
28
|
+
|
29
|
+
tum = SqlPartitioner::TimeUnitConverter.new(:seconds)
|
30
|
+
tum.from_seconds(timestamp_in_secs).should == timestamp_in_secs
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#to_seconds" do
|
35
|
+
it "should return a timestamp in the configured time unit" do
|
36
|
+
timestamp_in_secs = Time.utc(2014,01,15).to_i
|
37
|
+
|
38
|
+
tum = SqlPartitioner::TimeUnitConverter.new(:micro_seconds)
|
39
|
+
tum.to_seconds(timestamp_in_secs * 1_000_000).should == timestamp_in_secs
|
40
|
+
|
41
|
+
tum = SqlPartitioner::TimeUnitConverter.new(:seconds)
|
42
|
+
tum.to_seconds(timestamp_in_secs).should == timestamp_in_secs
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#advance_date_time" do
|
47
|
+
before(:each) do
|
48
|
+
@date_time = DateTime.new(2014,01,31)
|
49
|
+
end
|
50
|
+
context "using days" do
|
51
|
+
before(:each) do
|
52
|
+
@calendar_unit = :days
|
53
|
+
end
|
54
|
+
it "should return the correct DateTime when adding" do
|
55
|
+
SqlPartitioner::TimeUnitConverter.advance_date_time(@date_time, @calendar_unit, days = 2).to_s.should == "2014-02-02T00:00:00+00:00"
|
56
|
+
end
|
57
|
+
it "should return the correct DateTime when subtracting" do
|
58
|
+
SqlPartitioner::TimeUnitConverter.advance_date_time(@date_time, @calendar_unit, days = -2).to_s.should == "2014-01-29T00:00:00+00:00"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
context "using months" do
|
62
|
+
before(:each) do
|
63
|
+
@calendar_unit = :months
|
64
|
+
end
|
65
|
+
it "should return the correct DateTime when adding" do
|
66
|
+
SqlPartitioner::TimeUnitConverter.advance_date_time(@date_time, @calendar_unit, months = 2).to_s.should == "2014-03-31T00:00:00+00:00"
|
67
|
+
end
|
68
|
+
it "should return the correct DateTime when subtracting" do
|
69
|
+
SqlPartitioner::TimeUnitConverter.advance_date_time(@date_time, @calendar_unit, months = -2).to_s.should == "2013-11-30T00:00:00+00:00"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe ".time_units_per_second" do
|
75
|
+
it "should return the proper seconds multiplier to get the specified time unit" do
|
76
|
+
SqlPartitioner::TimeUnitConverter.time_units_per_second(:micro_seconds).should == 1_000_000
|
77
|
+
SqlPartitioner::TimeUnitConverter.time_units_per_second(:seconds).should == 1
|
78
|
+
end
|
79
|
+
it "all SUPPORTED_TIME_UNITS accounted for" do
|
80
|
+
SqlPartitioner::TimeUnitConverter::SUPPORTED_TIME_UNITS.each do |u|
|
81
|
+
SqlPartitioner::TimeUnitConverter.time_units_per_second(u).should be_a(Fixnum)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
it "unknown time unit should raise an error" do
|
85
|
+
lambda {
|
86
|
+
SqlPartitioner::TimeUnitConverter.time_units_per_second(:bogus)
|
87
|
+
}.should raise_error(RuntimeError, /unknown time_unit :bogus/)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|