ridgepole 1.0.7 → 1.1.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: 7886d7c158b4776c9db77e73c72ab5d882241950ed6a9f2c945a99220b7bcc4a
4
- data.tar.gz: 6429c8b8ed0c17dd1361c0e01592180c521002fa64fead1e625e9ec7ab2436a9
3
+ metadata.gz: 5906641e6a784f8548801ef9b94acedf8580ce9f5fcf2d8c23640b29968d9a65
4
+ data.tar.gz: fcbbf42e5eba4bfa9d16f8ba813d5c2374c357265a96bbf0322a66b84c17b99b
5
5
  SHA512:
6
- metadata.gz: a7a06ba181dbdad2e0dd6f054366d745a3dbd119715bdb83b9a5e440c8a2258014859b2f9a8916b75fd5fb0ed9c27c4a32efe7d51761d7dd62a5e313cbad6fae
7
- data.tar.gz: '0277821bd5e0fc9c47ec038bf938a1b1a8c18c8395af8fd5ccfdf14ed9a8b80b03c5b6550f7b11d4da7220023be6e14782261a0a85f5b70ad7d136561bce4724'
6
+ metadata.gz: 8eab1b038598d76ad94806aeeeda51af292527fa9ca84cecbc9be8b28b8351225c80782069824c7f7ca8619cdbacb7f85a9c29ef647e783a5d850957273d5f25
7
+ data.tar.gz: 834667f47a46455e1969574fb2341d620742e119c8882e70dc7d30c29c5780bf2671698f9982dbfed7a99cfc61f29344e7bffc0ec654c6f161d37af8189e4531
data/.rubocop.yml CHANGED
@@ -30,12 +30,6 @@ Metrics/ParameterLists:
30
30
  Enabled: false
31
31
  Metrics/PerceivedComplexity:
32
32
  Enabled: false
33
- Naming/MethodName:
34
- Exclude:
35
- - "lib/ridgepole/ext/abstract_mysql_adapter/schema_creation.rb"
36
- Naming/MethodParameterName:
37
- Exclude:
38
- - "lib/ridgepole/ext/abstract_mysql_adapter/schema_creation.rb"
39
33
  Style/Documentation:
40
34
  Enabled: false
41
35
  Style/GuardClause:
data/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## 1.0
4
4
 
5
+ ### 1.1.0 (2022/06/18)
6
+
7
+ * Revert partitioning support [pull#392](https://github.com/ridgepole/ridgepole/pull/392)
8
+
9
+ ## 1.0
10
+
5
11
  ### 1.0.7 (2022/06/09)
6
12
 
7
13
  * Normalize list partition values for PostgreSQL [pull#389](https://github.com/ridgepole/ridgepole/pull/389)
data/README.md CHANGED
@@ -11,6 +11,7 @@ It defines DB schema using [Rails DSL](http://guides.rubyonrails.org/migrations.
11
11
 
12
12
  **Notice**
13
13
 
14
+ * Partitioning is no longer supported in ridgepole v1.1.0.
14
15
  * ActiveRecord 7.x has some incompatible changes. If you get unintended differences in `datetime`, add `precision`.
15
16
  * cf. https://github.com/ridgepole/ridgepole/issues/381
16
17
  * For ActiveRecord 7.x series, please use AcriveRecord 7.0.2 or higher / Ridgepole 1.0.3 or higher.
@@ -216,7 +217,7 @@ See `mysql> show character set;` to find charset / collation pair for your syste
216
217
 
217
218
  ## Generated Column (MySQL)
218
219
 
219
- There should be NO extra white spaces in the expression (such as after comma).
220
+ There should be NO extra white spaces in the expression (such as after comma).
220
221
  Quotes in expression may cause the operations failure with MySQL 8.0.
221
222
 
222
223
  ```ruby
@@ -318,31 +319,6 @@ Apply `Schemafile`
318
319
  ...
319
320
  ```
320
321
 
321
- ## Partitioning
322
-
323
- **Notice:** PostgreSQL `PARTITION BY` must be specified with the create_table option.
324
-
325
- ### List Partitioning
326
-
327
- ```ruby
328
- create_table "articles", force: :cascade, options: "PARTITION BY LIST(id)" do |t|
329
- end
330
-
331
- add_partition("articles", :list, :id, partition_definitions: [{ name: 'p0', values: { in: [0,1,2] } }, { name: 'p1', values: { in: [3,4,5] } }])
332
- ```
333
-
334
- ### Range Partitioning
335
-
336
- ```ruby
337
- create_table "articles", force: :cascade, options: "PARTITION BY RANGE(id)" do |t|
338
- end
339
-
340
- # postgresql
341
- add_partition("articles", :range, :id, partition_definitions: [{ name: 'p0', values: { from: 'MINVALUE', to: 5 }}, { name: 'p1', values: { from: 5, to: 10 } }])
342
- # mysql
343
- add_partition("articles", :range, :id, partition_definitions: [{ name: 'p0', values: { to: 5 }}, { name: 'p1', values: { to: 10 } }])
344
- ```
345
-
346
322
  ## Run tests
347
323
 
348
324
 
@@ -15,12 +15,7 @@ module Ridgepole
15
15
  @parser = Ridgepole::DSLParser.new(@options)
16
16
  @diff = Ridgepole::Diff.new(@options)
17
17
 
18
- if Ridgepole::ConnectionAdapters.mysql?
19
- require 'ridgepole/ext/abstract_mysql_adapter/partitioning'
20
- require 'ridgepole/ext/abstract_mysql_adapter/schema_creation'
21
- end
22
18
  require 'ridgepole/ext/abstract_mysql_adapter/dump_auto_increment' if @options[:mysql_dump_auto_increment]
23
- require 'ridgepole/ext/postgresql_adapter/partitioning' if Ridgepole::ConnectionAdapters.postgresql?
24
19
  end
25
20
 
26
21
  def dump(&block)
@@ -310,29 +310,11 @@ execute "ALTER TABLE #{ActiveRecord::Base.connection.quote_table_name(table_name
310
310
  append_change_table_options(table_name, comment_literal, buf)
311
311
  end
312
312
 
313
- def append_change_partition(table_name, delta, buf)
314
- (delta[:add] || {}).each do |_, attrs|
315
- buf.puts "create_partition #{table_name.inspect}, **#{attrs.inspect}"
316
- end
317
- end
318
-
319
- def append_change_partition_definitions(table_name, partition_definitions, buf, _post_buf_for_fk)
320
- (partition_definitions[:add] || []).each do |partition_name, attrs|
321
- buf.puts "add_partition #{table_name.inspect}, name: #{partition_name.inspect}, values: #{attrs[:values].inspect}"
322
- end
323
-
324
- (partition_definitions[:delete] || []).each do |partition_name, _attrs|
325
- buf.puts "remove_partition #{table_name.inspect}, name: #{partition_name.inspect}"
326
- end
327
- end
328
-
329
313
  def append_change(table_name, attrs, buf, pre_buf_for_fk, post_buf_for_fk)
330
314
  definition = attrs[:definition] || {}
331
315
  primary_key_definition = attrs[:primary_key_definition] || {}
332
316
  indices = attrs[:indices] || {}
333
317
  foreign_keys = attrs[:foreign_keys] || {}
334
- partition = attrs[:partition] || {}
335
- partition_definitions = attrs[:partition_definitions] || {}
336
318
  table_options = attrs[:table_options]
337
319
  table_charset = attrs[:table_charset]
338
320
  table_collation = attrs[:table_collation]
@@ -356,10 +338,6 @@ execute "ALTER TABLE #{ActiveRecord::Base.connection.quote_table_name(table_name
356
338
 
357
339
  append_change_table_comment(table_name, table_comment, buf) if table_comment
358
340
 
359
- append_change_partition(table_name, partition, buf) unless partition.empty?
360
-
361
- append_change_partition_definitions(table_name, partition_definitions, buf, post_buf_for_fk) unless partition_definitions.empty?
362
-
363
341
  buf.puts
364
342
  pre_buf_for_fk.puts
365
343
  post_buf_for_fk.puts
@@ -37,9 +37,6 @@ module Ridgepole
37
37
  delta[:add] ||= {}
38
38
  delta[:add][table_name] = to_attrs
39
39
  end
40
- delta[:change] ||= {}
41
- delta[:change][table_name] ||= {}
42
- scan_partition_change(table_name, from_attrs&.fetch(:partition, nil), to_attrs&.fetch(:partition, nil), delta[:change][table_name])
43
40
  end
44
41
 
45
42
  scan_relation_info(relation_info)
@@ -620,56 +617,6 @@ module Ridgepole
620
617
  end
621
618
  end
622
619
 
623
- def scan_partition_change(table_name, from, to, table_delta)
624
- from = (from || {}).dup
625
- to = (to || {}).dup
626
- partition_delta = {}
627
-
628
- return if to.empty? && from.empty?
629
-
630
- if from.empty? && Ridgepole::ConnectionAdapters.mysql?
631
- partition_delta[:add] ||= {}
632
- partition_delta[:add][table_name] = to
633
- else
634
- if from.present? && (to[:type] != from[:type] || to[:columns] != from[:columns])
635
- @logger.warn(<<-MSG)
636
- "[WARNING] '#{table_name}' partition is skipped because of the different partition type.
637
- to: #{to[:type]} #{to[:columns]}
638
- from: #{from[:type]}" #{from[:columns]}
639
- MSG
640
- return
641
- end
642
-
643
- if from[:partition_definitions].present? && (to[:partition_definitions] & from[:partition_definitions]).empty?
644
- raise "All partition is different. please check partition settings.to: #{to}, from: #{from}"
645
- end
646
-
647
- scan_partition_definition_chanage(from, to, table_delta)
648
- end
649
-
650
- table_delta[:partition] = partition_delta unless partition_delta.empty?
651
- end
652
-
653
- def scan_partition_definition_chanage(from, to, table_delta)
654
- partition_definitions_delta = {}
655
- attrs = { type: from[:type] || to[:type] }
656
-
657
- from_partitions = (from[:partition_definitions] || []).index_by { |partition| partition[:name] }
658
- to_partitions = (to[:partition_definitions] || []).index_by { |partition| partition[:name] }
659
-
660
- (from_partitions.keys - to_partitions.keys).each do |name|
661
- partition_definitions_delta[:delete] ||= {}
662
- partition_definitions_delta[:delete][name] = attrs.merge(values: from_partitions[name][:values])
663
- end
664
-
665
- (to_partitions.keys - from_partitions.keys).each do |name|
666
- partition_definitions_delta[:add] ||= {}
667
- partition_definitions_delta[:add][name] = attrs.merge(values: to_partitions[name][:values])
668
- end
669
-
670
- table_delta[:partition_definitions] = partition_definitions_delta unless partition_definitions_delta.empty?
671
- end
672
-
673
620
  def check_table_existence(definition)
674
621
  return unless @options[:tables]
675
622
 
@@ -91,25 +91,6 @@ module Ridgepole
91
91
  }
92
92
  end
93
93
 
94
- def add_partition(table_name, type, columns, partition_definitions: [])
95
- partition_definitions.each do |partition_definition|
96
- values = partition_definition.fetch(:values)
97
- raise ArgumentError unless values.is_a?(Hash)
98
-
99
- if values.key?(:in)
100
- values[:in] = Array.wrap(values[:in])
101
- values[:in] = values[:in].map(&:to_s) if Ridgepole::ConnectionAdapters.postgresql?
102
- end
103
- values[:to] = Array.wrap(values[:to]) if values.key?(:to)
104
- values[:from] = Array.wrap(values[:from]) if values.key?(:from)
105
- end
106
- @__definition[table_name][:partition] = {
107
- type: type,
108
- columns: Array.wrap(columns),
109
- partition_definitions: partition_definitions,
110
- }
111
- end
112
-
113
94
  def require(file)
114
95
  schemafile = %r{\A/}.match?(file) ? file : File.join(@__working_dir, file)
115
96
 
@@ -45,30 +45,6 @@ module Ridgepole
45
45
  stream.puts add_foreign_key_statements.sort.join("\n")
46
46
  end
47
47
  end
48
-
49
- def tables(stream)
50
- original = ignore_tables.dup
51
- ignore_tables.concat(@connection.partition_tables)
52
- super
53
- ensure
54
- self.ignore_tables = original
55
- end
56
-
57
- def table(table, stream)
58
- super
59
- partition(table, stream)
60
- end
61
-
62
- def partition(table, stream)
63
- if (partition = @connection.partition(table))
64
- partition_definitions = partition.partition_definitions.map do |partition_definition|
65
- "{ name: #{partition_definition.name.inspect}, values: #{partition_definition.values} }"
66
- end.join(' ,')
67
-
68
- stream.puts " add_partition #{partition.table.inspect}, #{partition.type.inspect}, #{partition.columns.inspect}, partition_definitions: [#{partition_definitions}]"
69
- stream.puts
70
- end
71
- end
72
48
  end
73
49
  end
74
50
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ridgepole
4
- VERSION = '1.0.7'
4
+ VERSION = '1.1.0'
5
5
  end
data/lib/ridgepole.rb CHANGED
@@ -16,9 +16,6 @@ require 'diffy'
16
16
  module Ridgepole; end
17
17
 
18
18
  require 'ridgepole/ext/abstract_adapter/disable_table_options'
19
- require 'ridgepole/ext/abstract_adapter/partition_definition'
20
- require 'ridgepole/ext/abstract_adapter/partition_options'
21
- require 'ridgepole/ext/abstract_adapter/partitioning'
22
19
  require 'ridgepole/ext/pp_sort_hash'
23
20
  require 'ridgepole/ext/schema_dumper'
24
21
  require 'ridgepole/client'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ridgepole
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.7
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Genki Sugawara
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-06-08 00:00:00.000000000 Z
11
+ date: 2022-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -306,13 +306,7 @@ files:
306
306
  - lib/ridgepole/dumper.rb
307
307
  - lib/ridgepole/execute_expander.rb
308
308
  - lib/ridgepole/ext/abstract_adapter/disable_table_options.rb
309
- - lib/ridgepole/ext/abstract_adapter/partition_definition.rb
310
- - lib/ridgepole/ext/abstract_adapter/partition_options.rb
311
- - lib/ridgepole/ext/abstract_adapter/partitioning.rb
312
309
  - lib/ridgepole/ext/abstract_mysql_adapter/dump_auto_increment.rb
313
- - lib/ridgepole/ext/abstract_mysql_adapter/partitioning.rb
314
- - lib/ridgepole/ext/abstract_mysql_adapter/schema_creation.rb
315
- - lib/ridgepole/ext/postgresql_adapter/partitioning.rb
316
310
  - lib/ridgepole/ext/pp_sort_hash.rb
317
311
  - lib/ridgepole/ext/schema_dumper.rb
318
312
  - lib/ridgepole/external_sql_executer.rb
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_record/connection_adapters/abstract_adapter'
4
-
5
- module ActiveRecord
6
- module ConnectionAdapters
7
- class PartitionDefinition
8
- attr_reader :name, :values
9
-
10
- def initialize(
11
- name,
12
- values
13
- )
14
- @name = name
15
- @values = values
16
- end
17
- end
18
- end
19
- end
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_record/connection_adapters/abstract_adapter'
4
-
5
- module ActiveRecord
6
- module ConnectionAdapters
7
- class PartitionOptions
8
- attr_reader :table, :type, :columns, :partition_definitions
9
-
10
- TYPES = %i[range list].freeze
11
-
12
- def initialize(
13
- table, type,
14
- columns,
15
- partition_definitions: []
16
- )
17
- @table = table
18
- @type = type
19
- @columns = Array.wrap(columns)
20
- @partition_definitions = build_definitions(partition_definitions)
21
- end
22
-
23
- private
24
-
25
- def build_definitions(definitions)
26
- definitions.map do |definition|
27
- next if definition.is_a?(PartitionDefinition)
28
-
29
- PartitionDefinition.new(definition.fetch(:name), definition.fetch(:values))
30
- end.compact
31
- end
32
- end
33
- end
34
- end
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_record/connection_adapters/abstract_adapter'
4
-
5
- module Ridgepole
6
- module Ext
7
- module AbstractAdapter
8
- module Partitioning
9
- def partition(*)
10
- nil
11
- end
12
-
13
- def partition_tables
14
- []
15
- end
16
-
17
- # SchemaStatements
18
- def create_partition(*)
19
- raise NotImplementedError
20
- end
21
-
22
- def add_partition(*)
23
- raise NotImplementedError
24
- end
25
-
26
- def remove_partition(*)
27
- raise NotImplementedError
28
- end
29
- end
30
- end
31
- end
32
- end
33
-
34
- module ActiveRecord
35
- module ConnectionAdapters
36
- class AbstractAdapter
37
- prepend Ridgepole::Ext::AbstractAdapter::Partitioning
38
- end
39
- end
40
- end
@@ -1,72 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_record/connection_adapters/abstract_mysql_adapter'
4
-
5
- module Ridgepole
6
- module Ext
7
- module AbstractMysqlAdapter
8
- module Partitioning
9
- def partition(table_name)
10
- scope = quoted_scope(table_name)
11
-
12
- partition_info = exec_query(<<~SQL, 'SCHEMA')
13
- SELECT PARTITION_NAME, PARTITION_DESCRIPTION, PARTITION_METHOD, PARTITION_EXPRESSION
14
- FROM information_schema.partitions
15
- WHERE partition_name IS NOT NULL
16
- AND table_schema = #{scope[:schema]}
17
- AND table_name = #{scope[:name]}
18
- SQL
19
- return if partition_info.count == 0
20
-
21
- type = case partition_info.first['PARTITION_METHOD']
22
- when 'LIST COLUMNS'
23
- :list
24
- when 'RANGE COLUMNS'
25
- :range
26
- else
27
- raise NotImplementedError, partition_info.first['PARTITION_METHOD'].to_s
28
- end
29
- columns = partition_info.first['PARTITION_EXPRESSION'].delete('`').split(',').map(&:to_sym)
30
-
31
- partition_definitions = partition_info.map do |row|
32
- values = case type
33
- when :list
34
- { in: instance_eval("[#{row['PARTITION_DESCRIPTION'].gsub(/\(/, '[').gsub(/\)/, ']')}] # [1,2]", __FILE__, __LINE__) }
35
- when :range
36
- { to: instance_eval("[#{row['PARTITION_DESCRIPTION']}] # [1,2]", __FILE__, __LINE__) }
37
- else
38
- raise NotImplementedError
39
- end
40
-
41
- { name: row['PARTITION_NAME'], values: values }
42
- end
43
-
44
- ActiveRecord::ConnectionAdapters::PartitionOptions.new(table_name, type, columns, partition_definitions: partition_definitions)
45
- end
46
-
47
- # SchemaStatements
48
- def create_partition(table_name, type:, columns:, partition_definitions:)
49
- execute schema_creation.accept(ActiveRecord::ConnectionAdapters::PartitionOptions.new(table_name, type, columns,
50
- partition_definitions: partition_definitions))
51
- end
52
-
53
- def add_partition(table_name, name:, values:)
54
- pd = ActiveRecord::ConnectionAdapters::PartitionDefinition.new(name, values)
55
- execute "ALTER TABLE #{quote_table_name(table_name)} ADD PARTITION (#{schema_creation.accept(pd)})"
56
- end
57
-
58
- def remove_partition(table_name, name:)
59
- execute "ALTER TABLE #{quote_table_name(table_name)} DROP PARTITION #{name}"
60
- end
61
- end
62
- end
63
- end
64
- end
65
-
66
- module ActiveRecord
67
- module ConnectionAdapters
68
- class AbstractMysqlAdapter < AbstractAdapter
69
- prepend Ridgepole::Ext::AbstractMysqlAdapter::Partitioning
70
- end
71
- end
72
- end
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_record/connection_adapters/mysql/schema_creation'
4
-
5
- module Ridgepole
6
- module Ext
7
- module AbstractMysqlAdapter
8
- module SchemaCreation
9
- def visit_PartitionOptions(o)
10
- sqls = o.partition_definitions.map { |partition_definition| accept partition_definition }
11
- function = case o.type
12
- when :list
13
- "LIST COLUMNS(#{o.columns.map { |column| quote_column_name(column) }.join(',')})"
14
- when :range
15
- "RANGE COLUMNS(#{o.columns.map { |column| quote_column_name(column) }.join(',')})"
16
- else
17
- raise NotImplementedError
18
- end
19
- "ALTER TABLE #{quote_table_name(o.table)} PARTITION BY #{function} (#{sqls.join(',')})"
20
- end
21
-
22
- def visit_PartitionDefinition(o)
23
- if o.values.key?(:in)
24
- "PARTITION #{o.name} VALUES IN (#{o.values[:in].map do |value|
25
- value.is_a?(Array) ? "(#{value.map(&:inspect).join(',')})" : value.inspect
26
- end.join(',')})"
27
- elsif o.values.key?(:to)
28
- "PARTITION #{o.name} VALUES LESS THAN (#{o.values[:to].map(&:inspect).join(',')})"
29
- else
30
- raise NotImplementedError
31
- end
32
- end
33
- end
34
- end
35
- end
36
- end
37
-
38
- module ActiveRecord
39
- module ConnectionAdapters
40
- module MySQL
41
- class SchemaCreation
42
- prepend Ridgepole::Ext::AbstractMysqlAdapter::SchemaCreation
43
- end
44
- end
45
- end
46
- end
@@ -1,138 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_record/connection_adapters/postgresql_adapter'
4
-
5
- module Ridgepole
6
- module Ext
7
- module PostgreSQLAdapter
8
- module Partitioning
9
- def supports_partitions?
10
- ActiveRecord::VERSION::MAJOR >= 6 && postgresql_version >= 100_000 # >= 10.0
11
- end
12
-
13
- def table_options(table_name)
14
- options = partition_options(table_name)
15
- if options
16
- (super || {}).merge(options: "PARTITION BY #{options[:type].to_s.upcase}(#{options[:columns].join(',')})")
17
- else
18
- super
19
- end
20
- end
21
-
22
- def partition_options(table_name)
23
- return unless supports_partitions?
24
-
25
- scope = quoted_scope(table_name)
26
- result = query_value(<<~SQL, 'SCHEMA')
27
- SELECT pg_get_partkeydef(t.oid)
28
- FROM pg_class t
29
- LEFT JOIN pg_namespace n ON n.oid = t.relnamespace
30
- WHERE t.relname = #{scope[:name]}
31
- AND n.nspname = #{scope[:schema]}
32
- SQL
33
- return unless result
34
-
35
- type, *columns = result.scan(/\w+/).map { |value| value.downcase.to_sym }
36
- { type: type, columns: columns }
37
- end
38
-
39
- def partition(table_name)
40
- options = partition_options(table_name)
41
- return unless options
42
-
43
- scope = quoted_scope(table_name)
44
- partition_info = query(<<~SQL, 'SCHEMA')
45
- SELECT p.relname, pg_get_expr(p.relpartbound, p.oid, true)
46
- FROM pg_class t
47
- JOIN pg_inherits i on i.inhparent = t.oid
48
- JOIN pg_class p on p.oid = i.inhrelid
49
- WHERE t.relname = #{scope[:name]}
50
- AND p.relnamespace::regnamespace::text = #{scope[:schema]}
51
- ORDER BY p.relname
52
- SQL
53
-
54
- partition_definitions = partition_info.map do |name, val_str|
55
- values = if val_str == 'DEFAULT'
56
- { default: true }
57
- else
58
- case options[:type]
59
- when :list
60
- values = val_str.match(/FOR VALUES IN \((?<csv>.+)\)$/)[:csv].split(',').map(&:strip).map { |value| cast_value(value) }
61
- { in: Array.wrap(values) }
62
- when :range
63
- match = val_str.match(/FOR VALUES FROM \((?<from>.+)\) TO \((?<to>.+)\)/)
64
- from = match[:from].split(',').map(&:strip).map { |value| cast_value(value) }
65
- to = match[:to].split(',').map(&:strip).map { |value| cast_value(value) }
66
- { from: from, to: to }
67
- when :hash
68
- match = val_str.match(/FOR VALUES WITH \(modulus (?<modulus>\d+), remainder (?<remainder>\d+)\)/)
69
- { modulus: match[:modulus].to_i, remainder: match[:remainder].to_i }
70
- else
71
- raise NotImplementedError
72
- end
73
- end
74
- { name: name, values: values }
75
- end
76
-
77
- ActiveRecord::ConnectionAdapters::PartitionOptions.new(table_name, options[:type], options[:columns],
78
- partition_definitions: partition_definitions)
79
- end
80
-
81
- def cast_value(value)
82
- Integer(value)
83
- rescue ArgumentError
84
- value.delete(%q("')) # "
85
- end
86
-
87
- def quote_value(value)
88
- if %w[MINVALUE MAXVALUE].include?(value)
89
- value
90
- else
91
- quote(value)
92
- end
93
- end
94
-
95
- def partition_tables
96
- partition_info = query(<<~SQL, 'SCHEMA')
97
- SELECT p.relname
98
- FROM pg_class t
99
- JOIN pg_inherits i on i.inhparent = t.oid
100
- JOIN pg_class p on p.oid = i.inhrelid
101
- ORDER BY p.relname
102
- SQL
103
- partition_info.map { |row| row[0] }
104
- end
105
-
106
- # SchemaStatements
107
- def add_partition(table_name, name:, values:)
108
- condition = if values.key?(:default)
109
- 'DEFAULT'
110
- elsif values.key?(:in)
111
- "FOR VALUES IN (#{values[:in].map { |v| quote_value(v) }.join(',')})"
112
- elsif values.key?(:to)
113
- from = values[:from].map { |v| quote_value(v) }.join(',')
114
- to = values[:to].map { |v| quote_value(v) }.join(',')
115
- "FOR VALUES FROM (#{from}) TO (#{to})"
116
- elsif values.key?(:modulus)
117
- "FOR VALUES WITH (modulus #{values[:modulus]}, remainder #{values[:remainder]})"
118
- else
119
- raise NotImplementedError
120
- end
121
- create_table(name, id: false, options: "PARTITION OF #{table_name} #{condition}")
122
- end
123
-
124
- def remove_partition(_table_name, name:)
125
- drop_table(name)
126
- end
127
- end
128
- end
129
- end
130
- end
131
-
132
- module ActiveRecord
133
- module ConnectionAdapters
134
- class PostgreSQLAdapter
135
- prepend Ridgepole::Ext::PostgreSQLAdapter::Partitioning
136
- end
137
- end
138
- end