pg_enums 0.0.1

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.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/pg_enums.rb +112 -0
  3. metadata +86 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6984b2a6b097469fc73dd768518c7e03d6439fb6
4
+ data.tar.gz: b6e6e20cb417f77fa99fe23ff7485a8497c380bb
5
+ SHA512:
6
+ metadata.gz: c3dc8b830126e25c6b97133f059a8efa3eac46bfaaf486211c9b45d0605dca93e594f398d47d462c22cbfe9cbd8146ee9b681c04298da3de15f562b0c1e7bd8f
7
+ data.tar.gz: 869fe82f72c9c76cefc8b04f315c71e989350d8ff04d7eeb08cd9ea9967a7978640796f637d9892e62e6e4b92ea590f18ab298217e944b977fdda6518fd93d25
data/lib/pg_enums.rb ADDED
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+ module PGEnums
3
+
4
+ def update_enum(table:, column:, enum_type:, old_value:, new_value:)
5
+ # Select default store it and drop it if defined
6
+ default = default(table, column, enum_type, old_value, new_value)
7
+ drop_default(table, column) if default
8
+ # Generate the new labels
9
+ new_enumlabels = new_enumlabels(enum_type, old_value, new_value)
10
+ # Add the new label to the enum
11
+ ActiveRecord::Base.connection.execute <<-SQL
12
+ ALTER TYPE #{enum_type} ADD VALUE IF NOT EXISTS '#{new_value}';
13
+ SQL
14
+ # update the enum and the column
15
+ change_enum_labels(table, column, enum_type, old_value, new_value, new_enumlabels)
16
+ # restaure the default value
17
+ restaure_default(table, column, default, enum_type) if default
18
+ end
19
+
20
+ def delete_from_enum(table:, column:, enum_type:, value_to_drop:, map_to:)
21
+ # Select default store it and drop it if defined
22
+ default = default(table, column, enum_type, value_to_drop, map_to)
23
+ drop_default(table, column) if default
24
+ # Generate the new labels
25
+ new_enumlabels = new_enumlabels(enum_type, value_to_drop)
26
+ # update the enum and the column
27
+ change_enum_labels(table, column, enum_type, value_to_drop, map_to, new_enumlabels)
28
+ # restaure the default value
29
+ restaure_default(table, column, default, enum_type) if default
30
+ end
31
+
32
+ def add_to_enum(enum_type:, new_value:)
33
+ ActiveRecord::Base.connection.execute <<-SQL
34
+ ALTER TYPE #{enum_type} ADD VALUE IF NOT EXISTS '#{new_value}';
35
+ SQL
36
+ end
37
+
38
+ def rename_enum(enum:, new_name:)
39
+ ActiveRecord::Base.connection.execute <<-SQL
40
+ ALTER TYPE #{enum} RENAME TO #{new_name};
41
+ SQL
42
+ end
43
+
44
+ def delete_enum(enum:, table:, column:)
45
+ remove_column table, column
46
+ ActiveRecord::Base.connection.execute <<-SQL
47
+ DROP TYPE #{enum};
48
+ SQL
49
+ end
50
+
51
+ def create_enum(enum_type:, table:, column:, values:)
52
+ ActiveRecord::Base.connection.execute <<-SQL
53
+ CREATE TYPE #{enum_type} AS ENUM (#{"'" + values.join("', '") + "'"});
54
+ SQL
55
+ add_column table, column, enum_type
56
+ end
57
+
58
+ private
59
+
60
+ def change_enum_labels(table, column, enum_type, old_value, new_value, new_enumlabels)
61
+ # Rename the enum
62
+ # Create a new enum with the new labels
63
+ # Update the table to set each old value to the new one
64
+ # Update the table to map the column to the new enum
65
+ # Drop the old enum
66
+ ActiveRecord::Base.connection.execute <<-SQL
67
+ ALTER TYPE #{enum_type} RENAME TO old_#{enum_type};
68
+ CREATE TYPE #{enum_type} AS ENUM (#{new_enumlabels});
69
+ UPDATE #{table} SET #{column} = '#{new_value}' WHERE #{table}.#{column} = '#{old_value}';
70
+ ALTER TABLE #{table} ALTER COLUMN #{column} TYPE #{enum_type} USING #{column}::text::#{enum_type};
71
+ DROP TYPE old_#{enum_type};
72
+ SQL
73
+ end
74
+
75
+ # Fetch the enum labels from the data base
76
+ def new_enumlabels(enum_type, old_value, new_value = nil)
77
+ enumlabels = ActiveRecord::Base.connection.execute <<-SQL
78
+ SELECT enumlabel from pg_enum
79
+ WHERE enumtypid=(
80
+ SELECT oid FROM pg_type WHERE typname='#{enum_type}'
81
+ )
82
+ ORDER BY enumsortorder;
83
+ SQL
84
+ enumlabels = enumlabels.map { |e| "'#{e["enumlabel"]}'" } - ["'#{old_value}'"]
85
+ enumlabels << "'#{new_value}'" if new_value
86
+ enumlabels.uniq.join(", ").chomp(", ")
87
+ end
88
+
89
+ def default(table, column, enum_type, old_value, new_value)
90
+ default = ActiveRecord::Base.connection.execute <<-SQL
91
+ SELECT column_default FROM information_schema.columns
92
+ WHERE (table_schema, table_name, column_name) = ('public', '#{table}', '#{column}')
93
+ SQL
94
+ return unless default.first["column_default"]
95
+ default = default.first["column_default"]
96
+ default.slice!("::#{enum_type}")
97
+ (default == "'#{old_value}'") ? "'#{new_value}'" : default
98
+ end
99
+
100
+ def drop_default(table, column)
101
+ ActiveRecord::Base.connection.execute <<-SQL
102
+ ALTER TABLE #{table} ALTER #{column} DROP default
103
+ SQL
104
+ end
105
+
106
+ def restaure_default(table, column, default, enum_type)
107
+ ActiveRecord::Base.connection.execute <<-SQL
108
+ ALTER TABLE #{table} ALTER #{column} SET DEFAULT #{default}::#{enum_type}
109
+ SQL
110
+ end
111
+
112
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pg_enums
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - François Sevaistre
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-09-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pg
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ description: Simple usage of postgreSQL for Rails
56
+ email: frasevaistre+github@gmail.com
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - lib/pg_enums.rb
62
+ homepage: http://rubygems.org/gems/pg_enums
63
+ licenses:
64
+ - MIT
65
+ metadata: {}
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubyforge_project:
82
+ rubygems_version: 2.6.13
83
+ signing_key:
84
+ specification_version: 4
85
+ summary: PG Enums
86
+ test_files: []