torque-postgresql 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +31 -0
- data/lib/torque/postgresql/adapter/database_statements.rb +103 -0
- data/lib/torque/postgresql/adapter/oid/array.rb +19 -0
- data/lib/torque/postgresql/adapter/oid/enum.rb +46 -0
- data/lib/torque/postgresql/adapter/oid/interval.rb +94 -0
- data/lib/torque/postgresql/adapter/oid.rb +15 -0
- data/lib/torque/postgresql/adapter/quoting.rb +23 -0
- data/lib/torque/postgresql/adapter/schema_definitions.rb +28 -0
- data/lib/torque/postgresql/adapter/schema_dumper.rb +31 -0
- data/lib/torque/postgresql/adapter/schema_statements.rb +89 -0
- data/lib/torque/postgresql/adapter.rb +29 -0
- data/lib/torque/postgresql/attributes/builder/enum.rb +151 -0
- data/lib/torque/postgresql/attributes/builder.rb +1 -0
- data/lib/torque/postgresql/attributes/enum.rb +231 -0
- data/lib/torque/postgresql/attributes/lazy.rb +33 -0
- data/lib/torque/postgresql/attributes/type_map.rb +46 -0
- data/lib/torque/postgresql/attributes.rb +32 -0
- data/lib/torque/postgresql/auxiliary_statement.rb +192 -0
- data/lib/torque/postgresql/base.rb +28 -0
- data/lib/torque/postgresql/collector.rb +31 -0
- data/lib/torque/postgresql/config.rb +50 -0
- data/lib/torque/postgresql/migration/command_recorder.rb +31 -0
- data/lib/torque/postgresql/migration.rb +1 -0
- data/lib/torque/postgresql/relation/auxiliary_statement.rb +65 -0
- data/lib/torque/postgresql/relation/distinct_on.rb +43 -0
- data/lib/torque/postgresql/relation.rb +62 -0
- data/lib/torque/postgresql/schema_dumper.rb +37 -0
- data/lib/torque/postgresql/version.rb +5 -0
- data/lib/torque/postgresql.rb +18 -0
- data/lib/torque-postgresql.rb +1 -0
- metadata +236 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d27d24270072d57ca693a53b5fcd29ac72b509e0
|
4
|
+
data.tar.gz: cc63789993cf2817a2857d6cf5c6b8d31c38dabb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8b6bd7dc8af51496eecd1c7c7a33f4d3ce8e885e7918668068b8ecf8e7ac9961c1ee4cfe342ecf46c31ccead863b82fe4c3296e523cffd28a5d4ce4c7499be75
|
7
|
+
data.tar.gz: 41141267915f0e8ad1d5b6052cab7cc45c9e2bb37ff4d02fc4e819a4c8cf199ba33ea924884c8732bfd691c354908e330f8390e8836906806bc7e685ce2d7f84
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2016 Carlos Silva
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'Torque::Postgresql'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'Prints a schema dump of the test database'
|
18
|
+
task :dump do |t|
|
19
|
+
lib = File.expand_path('../lib', __FILE__)
|
20
|
+
spec = File.expand_path('../spec', __FILE__)
|
21
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
22
|
+
$LOAD_PATH.unshift(spec) unless $LOAD_PATH.include?(spec)
|
23
|
+
|
24
|
+
require 'byebug'
|
25
|
+
require 'spec_helper'
|
26
|
+
ActiveRecord::SchemaDumper.dump
|
27
|
+
end
|
28
|
+
|
29
|
+
require 'rspec/core/rake_task'
|
30
|
+
RSpec::Core::RakeTask.new(:spec)
|
31
|
+
task default: :spec
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module Torque
|
2
|
+
module PostgreSQL
|
3
|
+
module Adapter
|
4
|
+
module DatabaseStatements
|
5
|
+
|
6
|
+
EXTENDED_DATABASE_TYPES = %i(enum interval)
|
7
|
+
|
8
|
+
# Check if a given type is valid.
|
9
|
+
def valid_type?(type)
|
10
|
+
super || extended_types.include?(type)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Get the list of extended types
|
14
|
+
def extended_types
|
15
|
+
EXTENDED_DATABASE_TYPES
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns true if type exists.
|
19
|
+
def type_exists?(name)
|
20
|
+
user_defined_types.key? name.to_s
|
21
|
+
end
|
22
|
+
alias data_type_exists? type_exists?
|
23
|
+
|
24
|
+
# Configure the interval format
|
25
|
+
def configure_connection
|
26
|
+
super
|
27
|
+
execute("SET SESSION IntervalStyle TO 'iso_8601'", 'SCHEMA')
|
28
|
+
end
|
29
|
+
|
30
|
+
# Change some of the types being mapped
|
31
|
+
def initialize_type_map(m)
|
32
|
+
super
|
33
|
+
m.register_type 'interval', OID::Interval.new
|
34
|
+
end
|
35
|
+
|
36
|
+
# Add the composite types to be loaded too.
|
37
|
+
def load_additional_types(type_map, oids = nil)
|
38
|
+
super
|
39
|
+
|
40
|
+
filter = "AND a.typelem::integer IN (%s)" % oids.join(", ") if oids
|
41
|
+
|
42
|
+
query = <<-SQL
|
43
|
+
SELECT a.typelem AS oid, t.typname, t.typelem,
|
44
|
+
t.typdelim, t.typbasetype, t.typtype
|
45
|
+
FROM pg_type t
|
46
|
+
INNER JOIN pg_type a ON (a.oid = t.typarray)
|
47
|
+
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
|
48
|
+
WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
|
49
|
+
AND t.typtype IN ( 'c','e' )
|
50
|
+
#{filter}
|
51
|
+
AND NOT EXISTS(
|
52
|
+
SELECT 1 FROM pg_catalog.pg_type el
|
53
|
+
WHERE el.oid = t.typelem AND el.typarray = t.oid
|
54
|
+
)
|
55
|
+
AND (t.typrelid = 0 OR (
|
56
|
+
SELECT c.relkind = 'c' FROM pg_catalog.pg_class c
|
57
|
+
WHERE c.oid = t.typrelid
|
58
|
+
))
|
59
|
+
SQL
|
60
|
+
|
61
|
+
execute_and_clear(query, 'SCHEMA', []) do |records|
|
62
|
+
records.each do |row|
|
63
|
+
typtype = row['typtype']
|
64
|
+
type = begin
|
65
|
+
case
|
66
|
+
when typtype == 'e'.freeze then OID::Enum.create(row)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
type_map.register_type row['oid'].to_i, type
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Gets a list of user defined types.
|
76
|
+
# You can even choose the +typcategory+ filter
|
77
|
+
def user_defined_types(category = nil)
|
78
|
+
category_condition = "AND typtype = '#{category}'" unless category.nil?
|
79
|
+
select_all(<<-SQL).rows.to_h
|
80
|
+
SELECT t.typname AS name,
|
81
|
+
CASE t.typtype
|
82
|
+
WHEN 'e' THEN 'enum'
|
83
|
+
END AS type
|
84
|
+
FROM pg_type t
|
85
|
+
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
|
86
|
+
WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
|
87
|
+
#{category_condition}
|
88
|
+
AND NOT EXISTS(
|
89
|
+
SELECT 1 FROM pg_catalog.pg_type el
|
90
|
+
WHERE el.oid = t.typelem AND el.typarray = t.oid
|
91
|
+
)
|
92
|
+
AND (t.typrelid = 0 OR (
|
93
|
+
SELECT c.relkind = 'c' FROM pg_catalog.pg_class c
|
94
|
+
WHERE c.oid = t.typrelid
|
95
|
+
))
|
96
|
+
ORDER BY t.typtype DESC
|
97
|
+
SQL
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Torque
|
2
|
+
module PostgreSQL
|
3
|
+
module Adapter
|
4
|
+
module OID
|
5
|
+
module Array
|
6
|
+
|
7
|
+
def initialize(subtype, delimiter = ',')
|
8
|
+
super
|
9
|
+
@pg_encoder = Coder
|
10
|
+
@pg_decoder = Coder
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Array.prepend Array
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Torque
|
2
|
+
module PostgreSQL
|
3
|
+
module Adapter
|
4
|
+
module OID
|
5
|
+
class Enum < ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Enum
|
6
|
+
|
7
|
+
attr_reader :name, :klass
|
8
|
+
|
9
|
+
def self.create(row)
|
10
|
+
new(row['typname'])
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(name)
|
14
|
+
@name = name
|
15
|
+
@klass = Attributes::Enum.lookup(name)
|
16
|
+
end
|
17
|
+
|
18
|
+
def hash
|
19
|
+
[self.class, name].hash
|
20
|
+
end
|
21
|
+
|
22
|
+
def serialize(value)
|
23
|
+
return if value.blank?
|
24
|
+
value = cast_value(value)
|
25
|
+
value.to_s unless value.nil?
|
26
|
+
end
|
27
|
+
|
28
|
+
def assert_valid_value(value)
|
29
|
+
cast_value(value)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def cast_value(value)
|
35
|
+
return if value.blank?
|
36
|
+
return value if value.is_a?(@klass)
|
37
|
+
@klass.new(value)
|
38
|
+
rescue Attributes::Enum::EnumError
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Torque
|
2
|
+
module PostgreSQL
|
3
|
+
module Adapter
|
4
|
+
module OID
|
5
|
+
class Interval < ActiveModel::Type::Value
|
6
|
+
|
7
|
+
CAST_PARTS = [:years, :months, :days, :hours, :minutes, :seconds]
|
8
|
+
|
9
|
+
def type
|
10
|
+
:interval
|
11
|
+
end
|
12
|
+
|
13
|
+
# Accepts database-style string, numeric as seconds, array of parts
|
14
|
+
# padded to left, or a hash
|
15
|
+
#
|
16
|
+
# Examples:
|
17
|
+
# [12, 0, 0]
|
18
|
+
# produces: 12 hours, 0 minutes, and 0 seconds
|
19
|
+
#
|
20
|
+
# [nil, nil, 3, 0, 0, 0]
|
21
|
+
# produces: 3 days, 0 hours, 0 minutes, and 0 seconds
|
22
|
+
#
|
23
|
+
# {minutes: 12, seconds: 0}
|
24
|
+
# produces: 12 minutes, and 0 seconds
|
25
|
+
def cast(value)
|
26
|
+
return if value.blank?
|
27
|
+
case value
|
28
|
+
when ::String then deserialize(value)
|
29
|
+
when ::ActiveSupport::Duration then value
|
30
|
+
when ::Numeric
|
31
|
+
parts = CAST_PARTS.map do |part|
|
32
|
+
rest, value = value.divmod(1.send(part))
|
33
|
+
rest == 0 ? nil : [part, rest]
|
34
|
+
end
|
35
|
+
parts_to_duration(parts.compact)
|
36
|
+
when ::Array
|
37
|
+
value.compact!
|
38
|
+
parts = CAST_PARTS.drop(6 - value.size).zip(value).to_h
|
39
|
+
parts_to_duration(parts)
|
40
|
+
when ::Hash
|
41
|
+
parts_to_duration(value)
|
42
|
+
else
|
43
|
+
value
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Uses the ActiveSupport::Duration::ISO8601Parser
|
48
|
+
# See ActiveSupport::Duration#parse
|
49
|
+
# The value must be Integer when no precision is given
|
50
|
+
def deserialize(value)
|
51
|
+
return if value.blank?
|
52
|
+
parts = ActiveSupport::Duration::ISO8601Parser.new(value).parse!
|
53
|
+
parts_to_duration(parts)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Uses the ActiveSupport::Duration::ISO8601Serializer
|
57
|
+
# See ActiveSupport::Duration#iso8601
|
58
|
+
def serialize(value)
|
59
|
+
return if value.blank?
|
60
|
+
value = cast(value) unless value.is_a?(ActiveSupport::Duration)
|
61
|
+
value.iso8601(precision: @scale)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Always use the numeric value for schema dumper
|
65
|
+
def type_cast_for_schema(value)
|
66
|
+
cast(value).value.inspect
|
67
|
+
end
|
68
|
+
|
69
|
+
# Check if the user input has the correct format
|
70
|
+
def assert_valid_value(value)
|
71
|
+
# TODO: Implement!
|
72
|
+
end
|
73
|
+
|
74
|
+
# Transform a list of parts into a duration object
|
75
|
+
def parts_to_duration(parts)
|
76
|
+
parts = parts.to_h.with_indifferent_access.slice(*CAST_PARTS)
|
77
|
+
return 0.seconds if parts.blank?
|
78
|
+
|
79
|
+
seconds = 0
|
80
|
+
parts = parts.map do |part, num|
|
81
|
+
num = num.to_i unless num.is_a?(Numeric)
|
82
|
+
if num > 0
|
83
|
+
seconds += num.send(part).value
|
84
|
+
[part, num]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
ActiveSupport::Duration.new(seconds, parts.compact)
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative 'oid/array'
|
2
|
+
require_relative 'oid/enum'
|
3
|
+
require_relative 'oid/interval'
|
4
|
+
|
5
|
+
module Torque
|
6
|
+
module PostgreSQL
|
7
|
+
module Adapter
|
8
|
+
module OID
|
9
|
+
end
|
10
|
+
|
11
|
+
ActiveRecord::Type.register(:enum, OID::Enum, adapter: :postgresql)
|
12
|
+
ActiveRecord::Type.register(:interval, OID::Interval, adapter: :postgresql)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Torque
|
2
|
+
module PostgreSQL
|
3
|
+
module Adapter
|
4
|
+
module Quoting
|
5
|
+
|
6
|
+
Name = ActiveRecord::ConnectionAdapters::PostgreSQL::Name
|
7
|
+
|
8
|
+
# Quotes type names for use in SQL queries.
|
9
|
+
def quote_type_name(string, schema = nil)
|
10
|
+
name_schema, table = string.to_s.scan(/[^".\s]+|"[^"]*"/)
|
11
|
+
if table.nil?
|
12
|
+
table = name_schema
|
13
|
+
name_schema = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
schema = schema || name_schema || 'public'
|
17
|
+
Name.new(schema, table).quoted
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Torque
|
2
|
+
module PostgreSQL
|
3
|
+
module Adapter
|
4
|
+
module ColumnMethods
|
5
|
+
|
6
|
+
def interval(*args, **options)
|
7
|
+
args.each { |name| column(name, :interval, options) }
|
8
|
+
end
|
9
|
+
|
10
|
+
def enum(*args, **options)
|
11
|
+
args.each do |name|
|
12
|
+
type = options.fetch(:subtype, name)
|
13
|
+
column(name, type, options)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
module ColumnDefinition
|
20
|
+
attr_accessor :subtype
|
21
|
+
end
|
22
|
+
|
23
|
+
ActiveRecord::ConnectionAdapters::PostgreSQL::Table.include ColumnMethods
|
24
|
+
ActiveRecord::ConnectionAdapters::PostgreSQL::TableDefinition.include ColumnMethods
|
25
|
+
ActiveRecord::ConnectionAdapters::PostgreSQL::ColumnDefinition.include ColumnDefinition
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Torque
|
2
|
+
module PostgreSQL
|
3
|
+
module Adapter
|
4
|
+
module ColumnDumper
|
5
|
+
|
6
|
+
# Adds +:subtype+ as a valid migration key
|
7
|
+
def migration_keys
|
8
|
+
super + [:subtype]
|
9
|
+
end
|
10
|
+
|
11
|
+
# Adds +:subtype+ option to the default set
|
12
|
+
def prepare_column_options(column)
|
13
|
+
spec = super
|
14
|
+
|
15
|
+
if subtype = schema_subtype(column)
|
16
|
+
spec[:subtype] = subtype
|
17
|
+
end
|
18
|
+
|
19
|
+
spec
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def schema_subtype(column)
|
25
|
+
column.sql_type.to_sym.inspect if [:enum].include? column.type
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module Torque
|
2
|
+
module PostgreSQL
|
3
|
+
module Adapter
|
4
|
+
module SchemaStatements
|
5
|
+
|
6
|
+
# Drops a type.
|
7
|
+
def drop_type(name, options = {})
|
8
|
+
force = options.fetch(:force, '').upcase
|
9
|
+
check = 'IF EXISTS' if options.fetch(:check, true)
|
10
|
+
execute <<-SQL
|
11
|
+
DROP TYPE #{check}
|
12
|
+
#{quote_type_name(name, options[:schema])} #{force}
|
13
|
+
SQL
|
14
|
+
end
|
15
|
+
|
16
|
+
# Renames a type.
|
17
|
+
def rename_type(type_name, new_name)
|
18
|
+
execute <<-SQL
|
19
|
+
ALTER TYPE #{quote_type_name(type_name)}
|
20
|
+
RENAME TO #{Quoting::Name.new(nil, new_name.to_s).quoted}
|
21
|
+
SQL
|
22
|
+
end
|
23
|
+
|
24
|
+
# Creates a new PostgreSQL enumerator type
|
25
|
+
#
|
26
|
+
# Example:
|
27
|
+
# create_enum 'status', ['foo', 'bar']
|
28
|
+
# create_enum 'status', ['foo', 'bar'], prefix: true
|
29
|
+
# create_enum 'status', ['foo', 'bar'], suffix: 'test'
|
30
|
+
# create_enum 'status', ['foo', 'bar'], force: true
|
31
|
+
def create_enum(name, values, options = {})
|
32
|
+
drop_type(name, options) if options[:force]
|
33
|
+
execute <<-SQL
|
34
|
+
CREATE TYPE #{quote_type_name(name, options[:schema])} AS ENUM
|
35
|
+
(#{quote_enum_values(name, values, options).join(', ')})
|
36
|
+
SQL
|
37
|
+
end
|
38
|
+
|
39
|
+
# Changes the enumerator by adding new values
|
40
|
+
#
|
41
|
+
# Example:
|
42
|
+
# add_enum_values 'status', ['baz']
|
43
|
+
# add_enum_values 'status', ['baz'], before: 'bar'
|
44
|
+
# add_enum_values 'status', ['baz'], after: 'foo'
|
45
|
+
# add_enum_values 'status', ['baz'], prepend: true
|
46
|
+
def add_enum_values(name, values, options = {})
|
47
|
+
before = options.fetch(:before, false)
|
48
|
+
after = options.fetch(:after, false)
|
49
|
+
|
50
|
+
before = enum_values(name).first if options.key? :prepend
|
51
|
+
before = quote(before) unless before == false
|
52
|
+
after = quote(after) unless after == false
|
53
|
+
|
54
|
+
quote_enum_values(name, values, options).each do |value|
|
55
|
+
reference = "BEFORE #{before}" unless before == false
|
56
|
+
reference = "AFTER #{after}" unless after == false
|
57
|
+
execute <<-SQL
|
58
|
+
ALTER TYPE #{quote_type_name(name, options[:schema])}
|
59
|
+
ADD VALUE #{value} #{reference}
|
60
|
+
SQL
|
61
|
+
|
62
|
+
before = false
|
63
|
+
after = value
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns all values that an enum type can have.
|
68
|
+
def enum_values(name)
|
69
|
+
select_values("SELECT unnest(enum_range(NULL::#{name}))")
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def quote_enum_values(name, values, options)
|
75
|
+
prefix = options[:prefix]
|
76
|
+
prefix = name if prefix === true
|
77
|
+
|
78
|
+
suffix = options[:suffix]
|
79
|
+
suffix = name if suffix === true
|
80
|
+
|
81
|
+
values.map! do |value|
|
82
|
+
quote([prefix, value, suffix].compact.join('_'))
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|