sql_partitioner 0.6.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/.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
|