pg_party 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2de3fe17d288034fdb27f8bef0d5c01bad51f568dae6bf92d3e4d547da88b0ac
4
- data.tar.gz: b67b26808b013d71a393d3cdc1bd90d5b28c3e318661df1c56ebf8098407579b
3
+ metadata.gz: ee226c4523ca2b7099761ad517be99938078f7977281d88920beff47396f0c51
4
+ data.tar.gz: 2843ee1eb9fbe92e9998d8da0a3a20dfa989fa6c6dfcf3a261b80bac0caa47da
5
5
  SHA512:
6
- metadata.gz: d00eca782f9b7205a8c9bc3fd90a59c69a9e5ecefc828288c9d07ec61c94460e4344da121394aa6bb7b24d7a37a73e137b990ee504d7b78de28d7f29ac901f74
7
- data.tar.gz: bc753cae774726c2edb8adad720c59b92214ecb75e1a955df8882f4a733d409c8170202dc65904547a71d8b6ecba65eed237c1d56b4c76f36d33c0ce739eff7b
6
+ metadata.gz: 6cb4e5e42f08dcca3ec065c5d73656b6075e5a647d60722607cb4a9ff3cfeee24a94f4048544f3442284c816e7e37fe196579b9037e1ddacaaf1136e440efd4a
7
+ data.tar.gz: fdb593463dace1bdcfd844cac214cb6e6489dc7cd533226b90d11e506955ff48ad959fa80320423f3485637f89e3f6dbaeec5812ec0c1f640eb2d620e91de6dc
data/README.md CHANGED
@@ -351,9 +351,35 @@ SomeRangeRecord.in_partition(:some_range_records_partition_name)
351
351
  SomeListRecord.in_partition(:some_list_records_partition_name)
352
352
  ```
353
353
 
354
+ To create _range_ partitions by month for previous, current and next months it's possible to use this example. To automate creation of partitions, run `Log.maintenance` every day with cron:
355
+
356
+ ```ruby
357
+ class Log < ApplicationRecord
358
+ range_partition_by { '(created_at::date)' }
359
+
360
+ def self.maintenance
361
+ partitions = [Date.today.prev_month, Date.today, Date.today.next_month]
362
+
363
+ partitions.each do |day|
364
+ name = Log.partition_name_for(day)
365
+ next if ActiveRecord::Base.connection.table_exists?(name)
366
+ Log.create_partition(
367
+ name: name,
368
+ start_range: day.beginning_of_month,
369
+ end_range: day.next_month.beginning_of_month
370
+ )
371
+ end
372
+ end
373
+
374
+ def self.partition_name_for(day)
375
+ "logs_y#{day.year}_m#{day.month}"
376
+ end
377
+ end
378
+ ```
379
+
354
380
  For more examples, take a look at the model integration specs:
355
381
 
356
- - https://github.com/rkrage/pg_party/tree/documentation/spec/integration/model
382
+ - https://github.com/rkrage/pg_party/tree/master/spec/integration/model
357
383
 
358
384
  ## Development
359
385
 
@@ -34,12 +34,6 @@ ActiveSupport.on_load(:active_record) do
34
34
  PgParty::Adapter::AbstractMethods
35
35
  )
36
36
 
37
- require "pg_party/hacks/schema_cache"
38
-
39
- ActiveRecord::ConnectionAdapters::SchemaCache.include(
40
- PgParty::Hacks::SchemaCache
41
- )
42
-
43
37
  require "active_record/tasks/postgresql_database_tasks"
44
38
  require "pg_party/hacks/postgresql_database_tasks"
45
39
 
@@ -1,39 +1,40 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "pg_party/adapter_decorator"
4
+ require "ruby2_keywords"
4
5
 
5
6
  module PgParty
6
7
  module Adapter
7
8
  module PostgreSQLMethods
8
- def create_range_partition(*args, &blk)
9
+ ruby2_keywords def create_range_partition(*args, &blk)
9
10
  PgParty::AdapterDecorator.new(self).create_range_partition(*args, &blk)
10
11
  end
11
12
 
12
- def create_list_partition(*args, &blk)
13
+ ruby2_keywords def create_list_partition(*args, &blk)
13
14
  PgParty::AdapterDecorator.new(self).create_list_partition(*args, &blk)
14
15
  end
15
16
 
16
- def create_range_partition_of(*args)
17
+ ruby2_keywords def create_range_partition_of(*args)
17
18
  PgParty::AdapterDecorator.new(self).create_range_partition_of(*args)
18
19
  end
19
20
 
20
- def create_list_partition_of(*args)
21
+ ruby2_keywords def create_list_partition_of(*args)
21
22
  PgParty::AdapterDecorator.new(self).create_list_partition_of(*args)
22
23
  end
23
24
 
24
- def create_table_like(*args)
25
+ ruby2_keywords def create_table_like(*args)
25
26
  PgParty::AdapterDecorator.new(self).create_table_like(*args)
26
27
  end
27
28
 
28
- def attach_range_partition(*args)
29
+ ruby2_keywords def attach_range_partition(*args)
29
30
  PgParty::AdapterDecorator.new(self).attach_range_partition(*args)
30
31
  end
31
32
 
32
- def attach_list_partition(*args)
33
+ ruby2_keywords def attach_list_partition(*args)
33
34
  PgParty::AdapterDecorator.new(self).attach_list_partition(*args)
34
35
  end
35
36
 
36
- def detach_partition(*args)
37
+ ruby2_keywords def detach_partition(*args)
37
38
  PgParty::AdapterDecorator.new(self).detach_partition(*args)
38
39
  end
39
40
  end
@@ -148,7 +148,7 @@ module PgParty
148
148
  if key.is_a?(Proc)
149
149
  key.call.to_s # very difficult to determine how to sanitize a complex expression
150
150
  else
151
- quote_column_name(key)
151
+ Array.wrap(key).map(&method(:quote_column_name)).join(",")
152
152
  end
153
153
  end
154
154
 
@@ -1,15 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "pg_party/model_decorator"
4
+ require "ruby2_keywords"
4
5
 
5
6
  module PgParty
6
7
  module Model
7
8
  module ListMethods
8
- def create_partition(*args)
9
+ ruby2_keywords def create_partition(*args)
9
10
  PgParty::ModelDecorator.new(self).create_list_partition(*args)
10
11
  end
11
12
 
12
- def partition_key_in(*args)
13
+ ruby2_keywords def partition_key_in(*args)
13
14
  PgParty::ModelDecorator.new(self).list_partition_key_in(*args)
14
15
  end
15
16
  end
@@ -5,12 +5,12 @@ require "pg_party/model_injector"
5
5
  module PgParty
6
6
  module Model
7
7
  module Methods
8
- def range_partition_by(key=nil, &blk)
9
- PgParty::ModelInjector.new(self, key || blk).inject_range_methods
8
+ def range_partition_by(*key, &blk)
9
+ PgParty::ModelInjector.new(self, *key, &blk).inject_range_methods
10
10
  end
11
11
 
12
- def list_partition_by(key=nil, &blk)
13
- PgParty::ModelInjector.new(self, key || blk).inject_list_methods
12
+ def list_partition_by(*key, &blk)
13
+ PgParty::ModelInjector.new(self, *key, &blk).inject_list_methods
14
14
  end
15
15
 
16
16
  def partitioned?
@@ -1,15 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "pg_party/model_decorator"
4
+ require "ruby2_keywords"
4
5
 
5
6
  module PgParty
6
7
  module Model
7
8
  module RangeMethods
8
- def create_partition(*args)
9
+ ruby2_keywords def create_partition(*args)
9
10
  PgParty::ModelDecorator.new(self).create_range_partition(*args)
10
11
  end
11
12
 
12
- def partition_key_in(*args)
13
+ ruby2_keywords def partition_key_in(*args)
13
14
  PgParty::ModelDecorator.new(self).range_partition_key_in(*args)
14
15
  end
15
16
  end
@@ -36,7 +36,7 @@ module PgParty
36
36
  if complex_partition_key
37
37
  complex_partition_key_query("(#{partition_key}) = (?)", value)
38
38
  else
39
- where(current_arel_table[partition_key].eq(value))
39
+ where_partition_key(:eq, value)
40
40
  end
41
41
  end
42
42
 
@@ -48,9 +48,9 @@ module PgParty
48
48
  end_range
49
49
  )
50
50
  else
51
- node = current_arel_table[partition_key]
52
-
53
- where(node.gteq(start_range).and(node.lt(end_range)))
51
+ where_partition_key(:gteq, start_range).merge(
52
+ where_partition_key(:lt, end_range)
53
+ )
54
54
  end
55
55
  end
56
56
 
@@ -132,5 +132,26 @@ module PgParty
132
132
 
133
133
  from(subquery, current_alias)
134
134
  end
135
+
136
+ def where_partition_key(meth, values)
137
+ partition_key_array = Array.wrap(partition_key)
138
+ values = Array.wrap(values)
139
+
140
+ if partition_key_array.size != values.size
141
+ raise "number of provided values does not match the number of partition key columns"
142
+ end
143
+
144
+ arel_query = partition_key_array.zip(values).inject(nil) do |obj, (column, value)|
145
+ node = current_arel_table[column].send(meth, value)
146
+
147
+ if obj.nil?
148
+ node
149
+ else
150
+ obj.and(node)
151
+ end
152
+ end
153
+
154
+ where(arel_query)
155
+ end
135
156
  end
136
157
  end
@@ -2,9 +2,10 @@
2
2
 
3
3
  module PgParty
4
4
  class ModelInjector
5
- def initialize(model, key)
5
+ def initialize(model, *key, &blk)
6
6
  @model = model
7
- @key = key
7
+ @key = key.flatten.compact
8
+ @key_blk = blk
8
9
  end
9
10
 
10
11
  def inject_range_methods
@@ -38,11 +39,16 @@ module PgParty
38
39
  instance_predicate: false
39
40
  )
40
41
 
41
- if @key.is_a?(Proc)
42
- @model.partition_key = @key.call
42
+ if @key_blk
43
+ @model.partition_key = @key_blk.call
43
44
  @model.complex_partition_key = true
44
45
  else
45
- @model.partition_key = @key
46
+ if @key.size == 1
47
+ @model.partition_key = @key.first
48
+ else
49
+ @model.partition_key = @key
50
+ end
51
+
46
52
  @model.complex_partition_key = false
47
53
  end
48
54
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgParty
4
- VERSION = "1.2.1"
4
+ VERSION = "1.3.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_party
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Krage
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-28 00:00:00.000000000 Z
11
+ date: 2020-06-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,7 +16,7 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '4.2'
19
+ version: '5.0'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
22
  version: '6.1'
@@ -26,10 +26,24 @@ dependencies:
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: '4.2'
29
+ version: '5.0'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '6.1'
33
+ - !ruby/object:Gem::Dependency
34
+ name: ruby2_keywords
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 0.0.2
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 0.0.2
33
47
  - !ruby/object:Gem::Dependency
34
48
  name: appraisal
35
49
  requirement: !ruby/object:Gem::Requirement
@@ -182,14 +196,14 @@ dependencies:
182
196
  requirements:
183
197
  - - "~>"
184
198
  - !ruby/object:Gem::Version
185
- version: '0.17'
199
+ version: 0.17.0
186
200
  type: :development
187
201
  prerelease: false
188
202
  version_requirements: !ruby/object:Gem::Requirement
189
203
  requirements:
190
204
  - - "~>"
191
205
  - !ruby/object:Gem::Version
192
- version: '0.17'
206
+ version: 0.17.0
193
207
  - !ruby/object:Gem::Dependency
194
208
  name: timecop
195
209
  requirement: !ruby/object:Gem::Requirement
@@ -221,7 +235,6 @@ files:
221
235
  - lib/pg_party/cache.rb
222
236
  - lib/pg_party/config.rb
223
237
  - lib/pg_party/hacks/postgresql_database_tasks.rb
224
- - lib/pg_party/hacks/schema_cache.rb
225
238
  - lib/pg_party/model/list_methods.rb
226
239
  - lib/pg_party/model/methods.rb
227
240
  - lib/pg_party/model/range_methods.rb
@@ -241,14 +254,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
241
254
  requirements:
242
255
  - - ">="
243
256
  - !ruby/object:Gem::Version
244
- version: 2.3.0
257
+ version: 2.5.0
245
258
  required_rubygems_version: !ruby/object:Gem::Requirement
246
259
  requirements:
247
260
  - - ">="
248
261
  - !ruby/object:Gem::Version
249
262
  version: '0'
250
263
  requirements: []
251
- rubygems_version: 3.0.6
264
+ rubygems_version: 3.1.4
252
265
  signing_key:
253
266
  specification_version: 4
254
267
  summary: ActiveRecord PostgreSQL Partitioning
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module PgParty
4
- module Hacks
5
- module SchemaCache
6
- def self.included(base)
7
- return if base.method_defined?(:data_source_exists?)
8
-
9
- base.send(:alias_method, :data_source_exists?, :table_exists?)
10
- end
11
- end
12
- end
13
- end