torque-postgresql 2.4.4 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|