torque-postgresql 2.4.4 → 3.0.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 +4 -4
- data/README.rdoc +0 -17
- data/lib/torque/postgresql/adapter/database_statements.rb +32 -74
- data/lib/torque/postgresql/adapter/oid/enum_set.rb +1 -1
- data/lib/torque/postgresql/adapter/oid.rb +0 -3
- data/lib/torque/postgresql/adapter/quoting.rb +12 -20
- data/lib/torque/postgresql/adapter/schema_creation.rb +1 -2
- data/lib/torque/postgresql/adapter/schema_definitions.rb +0 -37
- data/lib/torque/postgresql/adapter/schema_dumper.rb +2 -60
- data/lib/torque/postgresql/adapter/schema_statements.rb +2 -74
- data/lib/torque/postgresql/adapter.rb +2 -11
- data/lib/torque/postgresql/associations/belongs_to_many_association.rb +7 -6
- data/lib/torque/postgresql/associations/{association.rb → foreign_association.rb} +1 -4
- data/lib/torque/postgresql/associations/preloader/association.rb +53 -26
- data/lib/torque/postgresql/associations/preloader/loader_query.rb +36 -0
- data/lib/torque/postgresql/associations/preloader.rb +1 -0
- data/lib/torque/postgresql/associations.rb +6 -1
- data/lib/torque/postgresql/attributes/builder/period.rb +6 -2
- data/lib/torque/postgresql/auxiliary_statement/settings.rb +22 -75
- data/lib/torque/postgresql/auxiliary_statement.rb +40 -39
- data/lib/torque/postgresql/base.rb +13 -33
- data/lib/torque/postgresql/config.rb +3 -30
- data/lib/torque/postgresql/inheritance.rb +1 -3
- data/lib/torque/postgresql/migration/command_recorder.rb +2 -12
- data/lib/torque/postgresql/railtie.rb +1 -5
- data/lib/torque/postgresql/reflection/abstract_reflection.rb +44 -20
- data/lib/torque/postgresql/reflection/belongs_to_many_reflection.rb +2 -2
- data/lib/torque/postgresql/relation/auxiliary_statement.rb +15 -28
- data/lib/torque/postgresql/relation.rb +10 -12
- data/lib/torque/postgresql/schema_cache.rb +2 -7
- data/lib/torque/postgresql/version.rb +1 -1
- data/lib/torque/postgresql.rb +1 -2
- data/lib/torque-postgresql.rb +0 -1
- data/spec/schema.rb +14 -30
- data/spec/spec_helper.rb +1 -2
- data/spec/tests/arel_spec.rb +2 -4
- data/spec/tests/auxiliary_statement_spec.rb +35 -374
- data/spec/tests/belongs_to_many_spec.rb +2 -99
- data/spec/tests/distinct_on_spec.rb +1 -1
- data/spec/tests/enum_set_spec.rb +10 -10
- data/spec/tests/enum_spec.rb +0 -90
- data/spec/tests/has_many_spec.rb +0 -46
- data/spec/tests/relation_spec.rb +1 -1
- data/spec/tests/table_inheritance_spec.rb +15 -11
- metadata +11 -37
- data/lib/torque/postgresql/auxiliary_statement/recursive.rb +0 -149
- data/lib/torque/postgresql/table_name.rb +0 -41
- data/lib/torque/range.rb +0 -22
- data/spec/models/category.rb +0 -2
- data/spec/models/internal/user.rb +0 -5
- data/spec/tests/range_spec.rb +0 -36
- data/spec/tests/schema_spec.rb +0 -134
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4fac19ef8680f477df0f79502331ddda06266658a54c8128321d68145a9f18b
|
4
|
+
data.tar.gz: 0e93ec49f80d40ec9ce9b7fcc5ef0eff65a882cad79a63e5429657ad9c66691b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a9abd492b544296c29e0949e1ad0ad4852a1ed0c48379551e5ffbbaad7018579cad994ac2a841231603bdddd8da4b448d7771a9086312289f818124d842d6a6
|
7
|
+
data.tar.gz: 8019255d20eff471ed177078e1bd6042a0a9b95752d32578bdb8ce86afdf9cffbefa8ed181caab0143f0dbbf80cfc39c99fd005cfc2b28089687b26a635268ef
|
data/README.rdoc
CHANGED
@@ -128,23 +128,6 @@ reconfigured on the model, and then can be used during querying process.
|
|
128
128
|
|
129
129
|
{Learn more}[link:classes/Torque/PostgreSQL/AuxiliaryStatement.html]
|
130
130
|
|
131
|
-
* Multiple Schemas
|
132
|
-
|
133
|
-
Allows models and modules to have a schema associated with them, so that
|
134
|
-
developers can better organize their tables into schemas and build features in
|
135
|
-
a way that the database can better represent how they are separated.
|
136
|
-
|
137
|
-
create_schema "internal", force: :cascade
|
138
|
-
|
139
|
-
module Internal
|
140
|
-
class User < ActiveRecord::Base
|
141
|
-
self.schema = 'internal'
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
Internal::User.all
|
146
|
-
|
147
|
-
{Learn more}[link:classes/Torque/PostgreSQL/Adapter/DatabaseStatements.html]
|
148
131
|
|
149
132
|
== Download and installation
|
150
133
|
|
@@ -12,26 +12,6 @@ module Torque
|
|
12
12
|
@_dump_mode = !!!@_dump_mode
|
13
13
|
end
|
14
14
|
|
15
|
-
# List of schemas blocked by the application in the current connection
|
16
|
-
def schemas_blacklist
|
17
|
-
@schemas_blacklist ||= Torque::PostgreSQL.config.schemas.blacklist +
|
18
|
-
(@config.dig(:schemas, 'blacklist') || [])
|
19
|
-
end
|
20
|
-
|
21
|
-
# List of schemas used by the application in the current connection
|
22
|
-
def schemas_whitelist
|
23
|
-
@schemas_whitelist ||= Torque::PostgreSQL.config.schemas.whitelist +
|
24
|
-
(@config.dig(:schemas, 'whitelist') || [])
|
25
|
-
end
|
26
|
-
|
27
|
-
# A list of schemas on the search path sanitized
|
28
|
-
def schemas_search_path_sanitized
|
29
|
-
@schemas_search_path_sanitized ||= begin
|
30
|
-
db_user = @config[:username] || ENV['USER'] || ENV['USERNAME']
|
31
|
-
schema_search_path.split(',').map { |item| item.strip.sub('"$user"', db_user) }
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
15
|
# Check if a given type is valid.
|
36
16
|
def valid_type?(type)
|
37
17
|
super || extended_types.include?(type)
|
@@ -42,17 +22,6 @@ module Torque
|
|
42
22
|
EXTENDED_DATABASE_TYPES
|
43
23
|
end
|
44
24
|
|
45
|
-
# Checks if a given schema exists in the database. If +filtered+ is
|
46
|
-
# given as false, then it will check regardless of whitelist and
|
47
|
-
# blacklist
|
48
|
-
def schema_exists?(name, filtered: true)
|
49
|
-
return user_defined_schemas.include?(name.to_s) if filtered
|
50
|
-
|
51
|
-
query_value(<<-SQL) == 1
|
52
|
-
SELECT 1 FROM pg_catalog.pg_namespace WHERE nspname = '#{name}'
|
53
|
-
SQL
|
54
|
-
end
|
55
|
-
|
56
25
|
# Returns true if type exists.
|
57
26
|
def type_exists?(name)
|
58
27
|
user_defined_types.key? name.to_s
|
@@ -65,6 +34,15 @@ module Torque
|
|
65
34
|
execute("SET SESSION IntervalStyle TO 'iso_8601'", 'SCHEMA')
|
66
35
|
end
|
67
36
|
|
37
|
+
# Since enums create new types, type map needs to be rebooted to include
|
38
|
+
# the new ones, both normal and array one
|
39
|
+
def create_enum(name, *)
|
40
|
+
super
|
41
|
+
|
42
|
+
oid = query_value("SELECT #{quote(name)}::regtype::oid", "SCHEMA").to_i
|
43
|
+
load_additional_types([oid])
|
44
|
+
end
|
45
|
+
|
68
46
|
# Change some of the types being mapped
|
69
47
|
def initialize_type_map(m = type_map)
|
70
48
|
super
|
@@ -85,7 +63,7 @@ module Torque
|
|
85
63
|
|
86
64
|
# Add the composite types to be loaded too.
|
87
65
|
def torque_load_additional_types(oids = nil)
|
88
|
-
filter = "AND a.typelem::integer IN (%s)" % oids.join(
|
66
|
+
filter = ("AND a.typelem::integer IN (%s)" % oids.join(', ')) if oids
|
89
67
|
|
90
68
|
query = <<-SQL
|
91
69
|
SELECT a.typelem AS oid, t.typname, t.typelem,
|
@@ -146,59 +124,39 @@ module Torque
|
|
146
124
|
# Get the list of inherited tables associated with their parent tables
|
147
125
|
def inherited_tables
|
148
126
|
tables = query(<<-SQL, 'SCHEMA')
|
149
|
-
SELECT
|
150
|
-
|
127
|
+
SELECT child.relname AS table_name,
|
128
|
+
array_agg(parent.relname) AS inheritances
|
151
129
|
FROM pg_inherits
|
152
130
|
JOIN pg_class parent ON pg_inherits.inhparent = parent.oid
|
153
131
|
JOIN pg_class child ON pg_inherits.inhrelid = child.oid
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
tables.each_with_object({}) do |(child, parent), result|
|
158
|
-
(result[child] ||= []) << parent
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
# Get the list of schemas that were created by the user
|
163
|
-
def user_defined_schemas
|
164
|
-
query_values(user_defined_schemas_sql, 'SCHEMA')
|
165
|
-
end
|
166
|
-
|
167
|
-
# Build the query for allowed schemas
|
168
|
-
def user_defined_schemas_sql
|
169
|
-
conditions = []
|
170
|
-
conditions << <<-SQL if schemas_blacklist.any?
|
171
|
-
nspname NOT LIKE ANY (ARRAY['#{schemas_blacklist.join("', '")}'])
|
132
|
+
GROUP BY child.relname, pg_inherits.inhrelid
|
133
|
+
ORDER BY pg_inherits.inhrelid
|
172
134
|
SQL
|
173
135
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
<<-SQL.squish
|
179
|
-
SELECT nspname
|
180
|
-
FROM pg_catalog.pg_namespace
|
181
|
-
WHERE 1=1 AND #{conditions.join(' AND ')}
|
182
|
-
ORDER BY oid
|
183
|
-
SQL
|
136
|
+
tables.map do |(table, refs)|
|
137
|
+
[table, PG::TextDecoder::Array.new.decode(refs)]
|
138
|
+
end.to_h
|
184
139
|
end
|
185
140
|
|
186
141
|
# Get the list of columns, and their definition, but only from the
|
187
142
|
# actual table, does not include columns that comes from inherited table
|
188
|
-
def column_definitions(table_name)
|
189
|
-
|
143
|
+
def column_definitions(table_name) # :nodoc:
|
144
|
+
# Only affects inheritance
|
145
|
+
local_condition = 'AND a.attislocal IS TRUE' if @_dump_mode
|
190
146
|
|
191
147
|
query(<<-SQL, 'SCHEMA')
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
148
|
+
SELECT a.attname, format_type(a.atttypid, a.atttypmod),
|
149
|
+
pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
|
150
|
+
(SELECT c.collname FROM pg_collation c, pg_type t
|
151
|
+
WHERE c.oid = a.attcollation AND t.oid = a.atttypid AND a.attcollation <> t.typcollation),
|
152
|
+
col_description(a.attrelid, a.attnum) AS comment
|
153
|
+
FROM pg_attribute a
|
154
|
+
LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
|
155
|
+
WHERE a.attrelid = '#{quote_table_name(table_name)}'::regclass
|
156
|
+
AND a.attnum > 0
|
157
|
+
AND a.attisdropped IS FALSE
|
158
|
+
#{local_condition}
|
159
|
+
ORDER BY a.attnum
|
202
160
|
SQL
|
203
161
|
end
|
204
162
|
|
@@ -19,9 +19,6 @@ module Torque
|
|
19
19
|
ActiveRecord::Type.register(:enum_set, OID::EnumSet, adapter: :postgresql)
|
20
20
|
ActiveRecord::Type.register(:line, OID::Line, adapter: :postgresql)
|
21
21
|
ActiveRecord::Type.register(:segment, OID::Segment, adapter: :postgresql)
|
22
|
-
|
23
|
-
ActiveRecord::Type.register(:interval, OID::Interval, adapter: :postgresql) \
|
24
|
-
unless PostgreSQL::AR610
|
25
22
|
end
|
26
23
|
end
|
27
24
|
end
|
@@ -22,27 +22,19 @@ module Torque
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def quote_default_expression(value, column)
|
25
|
-
return super unless value.class <= Array
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
return super unless value.class <= Array || value.class <= Set
|
26
|
+
|
27
|
+
type =
|
28
|
+
if column.is_a?(ColumnDefinition) && column.options.try(:[], :array)
|
29
|
+
# This is the general way
|
30
|
+
lookup_cast_type(column.sql_type)
|
31
|
+
elsif column.is_a?(Column) && column.array?
|
32
|
+
# When using +change_column_default+
|
33
|
+
lookup_cast_type_from_column(column)
|
34
|
+
end
|
35
|
+
|
36
|
+
type.nil? ? super : quote(type.serialize(value.to_a))
|
31
37
|
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def _quote(value)
|
36
|
-
return super unless value.is_a?(Array)
|
37
|
-
|
38
|
-
values = value.map(&method(:quote))
|
39
|
-
"ARRAY[#{values.join(','.freeze)}]"
|
40
|
-
end
|
41
|
-
|
42
|
-
def _type_cast(value)
|
43
|
-
return super unless value.is_a?(Array)
|
44
|
-
value.map(&method(:quote)).join(','.freeze)
|
45
|
-
end
|
46
38
|
end
|
47
39
|
end
|
48
40
|
end
|
@@ -33,8 +33,7 @@ module Torque
|
|
33
33
|
create_sql << "(#{statements.join(', ')})" \
|
34
34
|
if statements.present? || o.inherits.present?
|
35
35
|
|
36
|
-
|
37
|
-
add_table_options!(create_sql, options)
|
36
|
+
add_table_options!(create_sql, o)
|
38
37
|
|
39
38
|
if o.inherits.present?
|
40
39
|
tables = o.inherits.map(&method(:quote_table_name))
|
@@ -3,35 +3,7 @@
|
|
3
3
|
module Torque
|
4
4
|
module PostgreSQL
|
5
5
|
module Adapter
|
6
|
-
module ColumnMethods
|
7
|
-
|
8
|
-
# Creates a column with an interval type, allowing span of times and
|
9
|
-
# dates to be stored without having to store a seconds-based integer
|
10
|
-
# or any sort of other approach
|
11
|
-
def interval(*args, **options)
|
12
|
-
args.each { |name| column(name, :interval, **options) }
|
13
|
-
end
|
14
|
-
|
15
|
-
# Creates a column with an enum type, needing to specify the enum_type,
|
16
|
-
# which is basically the name of the type defined prior creating the
|
17
|
-
# column
|
18
|
-
def enum(*args, **options)
|
19
|
-
enum_type = [options.delete(:subtype), options.delete(:enum_type)].compact.first
|
20
|
-
args.each { |name| column(name, (enum_type || name), **options) }
|
21
|
-
end
|
22
|
-
|
23
|
-
# Creates a column with an enum array type, needing to specify the
|
24
|
-
# enum_type, which is basically the name of the type defined prior
|
25
|
-
# creating the column
|
26
|
-
def enum_set(*args, **options)
|
27
|
-
super(*args, **options.merge(array: true))
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
6
|
module TableDefinition
|
33
|
-
include ColumnMethods
|
34
|
-
|
35
7
|
attr_reader :inherits
|
36
8
|
|
37
9
|
def initialize(*args, **options)
|
@@ -42,16 +14,7 @@ module Torque
|
|
42
14
|
end
|
43
15
|
end
|
44
16
|
|
45
|
-
ActiveRecord::ConnectionAdapters::PostgreSQL::Table.include ColumnMethods
|
46
17
|
ActiveRecord::ConnectionAdapters::PostgreSQL::TableDefinition.include TableDefinition
|
47
|
-
|
48
|
-
if ActiveRecord::ConnectionAdapters::PostgreSQL.const_defined?('ColumnDefinition')
|
49
|
-
module ColumnDefinition
|
50
|
-
attr_accessor :subtype, :enum_type
|
51
|
-
end
|
52
|
-
|
53
|
-
ActiveRecord::ConnectionAdapters::PostgreSQL::ColumnDefinition.include ColumnDefinition
|
54
|
-
end
|
55
18
|
end
|
56
19
|
end
|
57
20
|
end
|
@@ -12,39 +12,16 @@ module Torque
|
|
12
12
|
stream
|
13
13
|
end
|
14
14
|
|
15
|
-
def extensions(stream) # :nodoc:
|
16
|
-
super
|
17
|
-
user_defined_schemas(stream)
|
18
|
-
user_defined_types(stream)
|
19
|
-
end
|
20
|
-
|
21
15
|
# Translate +:enum_set+ into +:enum+
|
22
16
|
def schema_type(column)
|
23
17
|
column.type == :enum_set ? :enum : super
|
24
18
|
end
|
25
19
|
|
26
|
-
# Adds +:enum_type+ option to the default set
|
27
|
-
def prepare_column_options(column)
|
28
|
-
spec = super
|
29
|
-
|
30
|
-
if enum_type = schema_enum_type(column)
|
31
|
-
spec[:enum_type] = enum_type
|
32
|
-
end
|
33
|
-
|
34
|
-
spec
|
35
|
-
end
|
36
|
-
|
37
20
|
private
|
38
21
|
|
39
|
-
def schema_enum_type(column)
|
40
|
-
column.sql_type.to_sym.inspect if column.type == :enum || column.type == :enum_set
|
41
|
-
end
|
42
|
-
|
43
22
|
def tables(stream) # :nodoc:
|
44
23
|
inherited_tables = @connection.inherited_tables
|
45
|
-
sorted_tables =
|
46
|
-
table_name.split(/(?:public)?\./).reverse
|
47
|
-
end
|
24
|
+
sorted_tables = @connection.tables.sort - @connection.views
|
48
25
|
|
49
26
|
stream.puts " # These are the common tables"
|
50
27
|
(sorted_tables - inherited_tables.keys).each do |table_name|
|
@@ -61,7 +38,7 @@ module Torque
|
|
61
38
|
|
62
39
|
# Add the inherits setting
|
63
40
|
sub_stream.rewind
|
64
|
-
inherits.map!
|
41
|
+
inherits.map!(&:to_sym)
|
65
42
|
inherits = inherits.first if inherits.size === 1
|
66
43
|
inherits = ", inherits: #{inherits.inspect} do |t|"
|
67
44
|
table_dump = sub_stream.read.gsub(/ do \|t\|$/, inherits)
|
@@ -86,41 +63,6 @@ module Torque
|
|
86
63
|
functions(stream) if defined?(::Fx::SchemaDumper::Function)
|
87
64
|
triggers(stream) if defined?(::Fx::SchemaDumper::Trigger)
|
88
65
|
end
|
89
|
-
|
90
|
-
# Make sure to remove the schema from the table name
|
91
|
-
def remove_prefix_and_suffix(table)
|
92
|
-
super(table.sub(/\A[a-z0-9_]*\./, ''))
|
93
|
-
end
|
94
|
-
|
95
|
-
# Dump user defined schemas
|
96
|
-
def user_defined_schemas(stream)
|
97
|
-
return if (list = (@connection.user_defined_schemas - ['public'])).empty?
|
98
|
-
|
99
|
-
stream.puts " # Custom schemas defined in this database."
|
100
|
-
list.each { |name| stream.puts " create_schema \"#{name}\", force: :cascade" }
|
101
|
-
stream.puts
|
102
|
-
end
|
103
|
-
|
104
|
-
# Dump user defined types like enum
|
105
|
-
def user_defined_types(stream)
|
106
|
-
types = @connection.user_defined_types('e')
|
107
|
-
return unless types.any?
|
108
|
-
|
109
|
-
stream.puts " # Custom types defined in this database."
|
110
|
-
stream.puts " # Note that some types may not work with other database engines. Be careful if changing database."
|
111
|
-
types.sort_by(&:first).each { |(name, type)| send(type.to_sym, name, stream) }
|
112
|
-
stream.puts
|
113
|
-
rescue => e
|
114
|
-
stream.puts "# Could not dump user-defined types because of following #{e.class}"
|
115
|
-
stream.puts "# #{e.message}"
|
116
|
-
stream.puts
|
117
|
-
end
|
118
|
-
|
119
|
-
# Dump enum custom type
|
120
|
-
def enum(name, stream)
|
121
|
-
values = @connection.enum_values(name).map { |v| "\"#{v}\"" }
|
122
|
-
stream.puts " create_enum \"#{name}\", [#{values.join(', ')}], force: :cascade"
|
123
|
-
end
|
124
66
|
end
|
125
67
|
|
126
68
|
ActiveRecord::ConnectionAdapters::PostgreSQL::SchemaDumper.prepend SchemaDumper
|
@@ -7,21 +7,6 @@ module Torque
|
|
7
7
|
|
8
8
|
TableDefinition = ActiveRecord::ConnectionAdapters::PostgreSQL::TableDefinition
|
9
9
|
|
10
|
-
# Create a new schema
|
11
|
-
def create_schema(name, options = {})
|
12
|
-
drop_schema(name, options) if options[:force]
|
13
|
-
|
14
|
-
check = 'IF NOT EXISTS' if options.fetch(:check, true)
|
15
|
-
execute("CREATE SCHEMA #{check} #{quote_schema_name(name.to_s)}")
|
16
|
-
end
|
17
|
-
|
18
|
-
# Drop an existing schema
|
19
|
-
def drop_schema(name, options = {})
|
20
|
-
force = options.fetch(:force, '').upcase
|
21
|
-
check = 'IF EXISTS' if options.fetch(:check, true)
|
22
|
-
execute("DROP SCHEMA #{check} #{quote_schema_name(name.to_s)} #{force}")
|
23
|
-
end
|
24
|
-
|
25
10
|
# Drops a type.
|
26
11
|
def drop_type(name, options = {})
|
27
12
|
force = options.fetch(:force, '').upcase
|
@@ -33,28 +18,13 @@ module Torque
|
|
33
18
|
end
|
34
19
|
|
35
20
|
# Renames a type.
|
36
|
-
def rename_type(type_name, new_name
|
21
|
+
def rename_type(type_name, new_name)
|
37
22
|
execute <<-SQL.squish
|
38
|
-
ALTER TYPE #{quote_type_name(type_name
|
23
|
+
ALTER TYPE #{quote_type_name(type_name)}
|
39
24
|
RENAME TO #{Quoting::Name.new(nil, new_name.to_s).quoted}
|
40
25
|
SQL
|
41
26
|
end
|
42
27
|
|
43
|
-
# Creates a new PostgreSQL enumerator type
|
44
|
-
#
|
45
|
-
# Example:
|
46
|
-
# create_enum 'status', ['foo', 'bar']
|
47
|
-
# create_enum 'status', ['foo', 'bar'], prefix: true
|
48
|
-
# create_enum 'status', ['foo', 'bar'], suffix: 'test'
|
49
|
-
# create_enum 'status', ['foo', 'bar'], force: true
|
50
|
-
def create_enum(name, values, options = {})
|
51
|
-
drop_type(name, options) if options[:force]
|
52
|
-
execute <<-SQL.squish
|
53
|
-
CREATE TYPE #{quote_type_name(name, options[:schema])} AS ENUM
|
54
|
-
(#{quote_enum_values(name, values, options).join(', ')})
|
55
|
-
SQL
|
56
|
-
end
|
57
|
-
|
58
28
|
# Changes the enumerator by adding new values
|
59
29
|
#
|
60
30
|
# Example:
|
@@ -94,56 +64,14 @@ module Torque
|
|
94
64
|
|
95
65
|
# Rewrite the method that creates tables to easily accept extra options
|
96
66
|
def create_table(table_name, **options, &block)
|
97
|
-
table_name = "#{options[:schema]}.#{table_name}" if options[:schema].present?
|
98
|
-
|
99
67
|
options[:id] = false if options[:inherits].present? &&
|
100
68
|
options[:primary_key].blank? && options[:id].blank?
|
101
69
|
|
102
70
|
super table_name, **options, &block
|
103
71
|
end
|
104
72
|
|
105
|
-
# Simply add the schema to the table name when changing a table
|
106
|
-
def change_table(table_name, **options)
|
107
|
-
table_name = "#{options[:schema]}.#{table_name}" if options[:schema].present?
|
108
|
-
super table_name, **options
|
109
|
-
end
|
110
|
-
|
111
|
-
# Simply add the schema to the table name when dropping a table
|
112
|
-
def drop_table(table_name, **options)
|
113
|
-
table_name = "#{options[:schema]}.#{table_name}" if options[:schema].present?
|
114
|
-
super table_name, **options
|
115
|
-
end
|
116
|
-
|
117
|
-
# Add the schema option when extracting table options
|
118
|
-
def table_options(table_name)
|
119
|
-
parts = table_name.split('.').reverse
|
120
|
-
return super unless parts.size == 2 && parts[1] != 'public'
|
121
|
-
|
122
|
-
(super || {}).merge(schema: parts[1])
|
123
|
-
end
|
124
|
-
|
125
|
-
# When dumping the schema we need to add all schemas, not only those
|
126
|
-
# active for the current +schema_search_path+
|
127
|
-
def quoted_scope(name = nil, type: nil)
|
128
|
-
return super unless name.nil?
|
129
|
-
|
130
|
-
super.merge(schema: "ANY ('{#{user_defined_schemas.join(',')}}')")
|
131
|
-
end
|
132
|
-
|
133
|
-
# Fix the query to include the schema on tables names when dumping
|
134
|
-
def data_source_sql(name = nil, type: nil)
|
135
|
-
return super unless name.nil?
|
136
|
-
|
137
|
-
super.sub('SELECT c.relname FROM', "SELECT n.nspname || '.' || c.relname FROM")
|
138
|
-
end
|
139
|
-
|
140
73
|
private
|
141
74
|
|
142
|
-
# Remove the schema from the sequence name
|
143
|
-
def sequence_name_from_parts(table_name, column_name, suffix)
|
144
|
-
super(table_name.split('.').last, column_name, suffix)
|
145
|
-
end
|
146
|
-
|
147
75
|
def quote_enum_values(name, values, options)
|
148
76
|
prefix = options[:prefix]
|
149
77
|
prefix = name if prefix === true
|
@@ -31,9 +31,9 @@ module Torque
|
|
31
31
|
)
|
32
32
|
end
|
33
33
|
|
34
|
-
# Add `inherits`
|
34
|
+
# Add `inherits` to the list of extracted table options
|
35
35
|
def extract_table_options!(options)
|
36
|
-
super.merge(options.extract!(:inherits
|
36
|
+
super.merge(options.extract!(:inherits))
|
37
37
|
end
|
38
38
|
|
39
39
|
# Allow filtered bulk insert by adding the where clause. This method is
|
@@ -49,15 +49,6 @@ module Torque
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
end
|
52
|
-
|
53
|
-
# Extend the extract default value to support array
|
54
|
-
def extract_value_from_default(default)
|
55
|
-
return super unless Torque::PostgreSQL.config.use_extended_defaults
|
56
|
-
return super unless default&.match(/ARRAY\[(.*?)\](?:::"?([\w. ]+)"?(?:\[\])+)?$/)
|
57
|
-
|
58
|
-
arr = $1.split(/(?!\B\[[^\]]*), ?(?![^\[]*\]\B)/)
|
59
|
-
DeduplicatableArray.new(arr.map(&method(:extract_value_from_default)))
|
60
|
-
end
|
61
52
|
end
|
62
53
|
|
63
54
|
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend Adapter
|
@@ -12,9 +12,9 @@ module Torque
|
|
12
12
|
## CUSTOM
|
13
13
|
def ids_reader
|
14
14
|
if loaded?
|
15
|
-
target.pluck(reflection.
|
15
|
+
target.pluck(reflection.association_primary_key)
|
16
16
|
elsif !target.empty?
|
17
|
-
load_target.pluck(reflection.
|
17
|
+
load_target.pluck(reflection.association_primary_key)
|
18
18
|
else
|
19
19
|
stale_state || column_default_value
|
20
20
|
end
|
@@ -53,8 +53,8 @@ module Torque
|
|
53
53
|
|
54
54
|
def load_target
|
55
55
|
if stale_target? || find_target?
|
56
|
-
|
57
|
-
@target = merge_target_lists(
|
56
|
+
persisted_records = (find_target || []) + target.extract!(&:persisted?)
|
57
|
+
@target = merge_target_lists(persisted_records, target)
|
58
58
|
end
|
59
59
|
|
60
60
|
loaded!
|
@@ -228,8 +228,9 @@ module Torque
|
|
228
228
|
end
|
229
229
|
|
230
230
|
def invertible_for?(record)
|
231
|
-
inverse = inverse_reflection_for(record)
|
232
|
-
|
231
|
+
return unless (inverse = inverse_reflection_for(record))
|
232
|
+
collection_class = ::ActiveRecord::Associations::HasManyAssociation
|
233
|
+
inverse.is_a?(collection_class) && inverse.connected_through_array?
|
233
234
|
end
|
234
235
|
|
235
236
|
def stale_state
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module Torque
|
4
4
|
module PostgreSQL
|
5
5
|
module Associations
|
6
|
-
module
|
6
|
+
module ForeignAssociation
|
7
7
|
|
8
8
|
# There is no problem of adding temporary items on target because
|
9
9
|
# CollectionProxy will handle memory and persisted relationship
|
@@ -33,9 +33,6 @@ module Torque
|
|
33
33
|
end
|
34
34
|
|
35
35
|
end
|
36
|
-
|
37
|
-
::ActiveRecord::Associations::Association.prepend(Association)
|
38
|
-
::ActiveRecord::Associations::HasManyAssociation.prepend(Association)
|
39
36
|
end
|
40
37
|
end
|
41
38
|
end
|