pg_party 1.2.1 → 1.3.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.
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