torque-postgresql 3.4.1 → 4.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/lib/generators/torque/function_generator.rb +13 -0
- data/lib/generators/torque/templates/function.sql.erb +4 -0
- data/lib/generators/torque/templates/type.sql.erb +2 -0
- data/lib/generators/torque/templates/view.sql.erb +3 -0
- data/lib/generators/torque/type_generator.rb +13 -0
- data/lib/generators/torque/view_generator.rb +16 -0
- data/lib/torque/postgresql/adapter/database_statements.rb +111 -94
- data/lib/torque/postgresql/adapter/oid/array.rb +17 -0
- data/lib/torque/postgresql/adapter/oid/line.rb +2 -6
- data/lib/torque/postgresql/adapter/oid/range.rb +4 -4
- data/lib/torque/postgresql/adapter/oid.rb +1 -23
- data/lib/torque/postgresql/adapter/quoting.rb +13 -7
- data/lib/torque/postgresql/adapter/schema_creation.rb +7 -28
- data/lib/torque/postgresql/adapter/schema_definitions.rb +58 -0
- data/lib/torque/postgresql/adapter/schema_dumper.rb +136 -34
- data/lib/torque/postgresql/adapter/schema_overrides.rb +45 -0
- data/lib/torque/postgresql/adapter/schema_statements.rb +109 -49
- data/lib/torque/postgresql/arel/infix_operation.rb +15 -28
- data/lib/torque/postgresql/arel/nodes.rb +16 -2
- data/lib/torque/postgresql/arel/operations.rb +7 -1
- data/lib/torque/postgresql/arel/visitors.rb +7 -9
- data/lib/torque/postgresql/associations/association_scope.rb +23 -31
- data/lib/torque/postgresql/associations/belongs_to_many_association.rb +25 -0
- data/lib/torque/postgresql/associations/builder/belongs_to_many.rb +16 -0
- data/lib/torque/postgresql/attributes/builder/enum.rb +12 -9
- data/lib/torque/postgresql/attributes/builder/full_text_search.rb +109 -0
- data/lib/torque/postgresql/attributes/builder/period.rb +21 -21
- data/lib/torque/postgresql/attributes/builder.rb +49 -11
- data/lib/torque/postgresql/attributes/enum.rb +7 -7
- data/lib/torque/postgresql/attributes/enum_set.rb +7 -7
- data/lib/torque/postgresql/attributes/full_text_search.rb +19 -0
- data/lib/torque/postgresql/attributes/period.rb +2 -2
- data/lib/torque/postgresql/attributes.rb +0 -4
- data/lib/torque/postgresql/auxiliary_statement/recursive.rb +3 -3
- data/lib/torque/postgresql/base.rb +5 -11
- data/lib/torque/postgresql/collector.rb +1 -1
- data/lib/torque/postgresql/config.rb +129 -5
- data/lib/torque/postgresql/function.rb +94 -0
- data/lib/torque/postgresql/inheritance.rb +52 -36
- data/lib/torque/postgresql/predicate_builder/arel_attribute_handler.rb +33 -0
- data/lib/torque/postgresql/predicate_builder/array_handler.rb +47 -0
- data/lib/torque/postgresql/predicate_builder/enumerator_lazy_handler.rb +37 -0
- data/lib/torque/postgresql/predicate_builder/regexp_handler.rb +21 -0
- data/lib/torque/postgresql/predicate_builder.rb +35 -0
- data/lib/torque/postgresql/railtie.rb +137 -30
- data/lib/torque/postgresql/reflection/abstract_reflection.rb +12 -44
- data/lib/torque/postgresql/reflection/belongs_to_many_reflection.rb +4 -0
- data/lib/torque/postgresql/reflection/has_many_reflection.rb +4 -0
- data/lib/torque/postgresql/reflection/runtime_reflection.rb +1 -1
- data/lib/torque/postgresql/relation/auxiliary_statement.rb +7 -2
- data/lib/torque/postgresql/relation/buckets.rb +124 -0
- data/lib/torque/postgresql/relation/distinct_on.rb +7 -2
- data/lib/torque/postgresql/relation/inheritance.rb +22 -15
- data/lib/torque/postgresql/relation/join_series.rb +112 -0
- data/lib/torque/postgresql/relation/merger.rb +17 -3
- data/lib/torque/postgresql/relation.rb +24 -38
- data/lib/torque/postgresql/schema_cache.rb +6 -12
- data/lib/torque/postgresql/version.rb +1 -1
- data/lib/torque/postgresql/versioned_commands/command_migration.rb +146 -0
- data/lib/torque/postgresql/versioned_commands/generator.rb +57 -0
- data/lib/torque/postgresql/versioned_commands/migration_context.rb +83 -0
- data/lib/torque/postgresql/versioned_commands/migrator.rb +39 -0
- data/lib/torque/postgresql/versioned_commands/schema_table.rb +101 -0
- data/lib/torque/postgresql/versioned_commands.rb +161 -0
- data/lib/torque/postgresql.rb +2 -1
- data/spec/fixtures/migrations/20250101000001_create_users.rb +0 -0
- data/spec/fixtures/migrations/20250101000002_create_function_count_users_v1.sql +0 -0
- data/spec/fixtures/migrations/20250101000003_create_internal_users.rb +0 -0
- data/spec/fixtures/migrations/20250101000004_update_function_count_users_v2.sql +0 -0
- data/spec/fixtures/migrations/20250101000005_create_view_all_users_v1.sql +0 -0
- data/spec/fixtures/migrations/20250101000006_create_type_user_id_v1.sql +0 -0
- data/spec/fixtures/migrations/20250101000007_remove_function_count_users_v2.sql +0 -0
- data/spec/initialize.rb +67 -0
- data/spec/mocks/cache_query.rb +21 -21
- data/spec/mocks/create_table.rb +6 -26
- data/spec/schema.rb +17 -12
- data/spec/spec_helper.rb +11 -2
- data/spec/tests/arel_spec.rb +32 -7
- data/spec/tests/auxiliary_statement_spec.rb +3 -3
- data/spec/tests/belongs_to_many_spec.rb +72 -5
- data/spec/tests/enum_set_spec.rb +12 -11
- data/spec/tests/enum_spec.rb +4 -2
- data/spec/tests/full_text_seach_test.rb +280 -0
- data/spec/tests/function_spec.rb +42 -0
- data/spec/tests/has_many_spec.rb +21 -8
- data/spec/tests/interval_spec.rb +1 -7
- data/spec/tests/period_spec.rb +61 -61
- data/spec/tests/predicate_builder_spec.rb +132 -0
- data/spec/tests/relation_spec.rb +229 -0
- data/spec/tests/schema_spec.rb +6 -9
- data/spec/tests/table_inheritance_spec.rb +25 -26
- data/spec/tests/versioned_commands_spec.rb +513 -0
- metadata +64 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d80bb198f5645c35915440f05a4ad083830221de27983c4c7b936c394e7bcbbb
|
4
|
+
data.tar.gz: a73a8de3a63b806e08f42109a3bb703e7ce19a20ae55a317c7fb763215612396
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 42a366f328d284ed37c601e0007a32f65b6615f69185b44fb82e0b943ab77a9e5b810189e00f2f200cf9e9b22e373bf33798c5496c76cfbfcd236bcc8bb923fe
|
7
|
+
data.tar.gz: 45385a880da9922eeb72c4d7e2adb29c26081865747c080973d409e61866a027cccd14a4276c8e0f95daf34d4d59c74a0a1c7cd7aecbb611763734cd12d3e064
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'torque/postgresql/versioned_commands/generator'
|
4
|
+
|
5
|
+
module Torque
|
6
|
+
module Generators
|
7
|
+
class FunctionGenerator < Rails::Generators::Base
|
8
|
+
include Torque::PostgreSQL::VersionedCommands::Generator
|
9
|
+
|
10
|
+
alias create_function_file create_migration_file
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'torque/postgresql/versioned_commands/generator'
|
4
|
+
|
5
|
+
module Torque
|
6
|
+
module Generators
|
7
|
+
class TypeGenerator < Rails::Generators::Base
|
8
|
+
include Torque::PostgreSQL::VersionedCommands::Generator
|
9
|
+
|
10
|
+
alias create_type_file create_migration_file
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'torque/postgresql/versioned_commands/generator'
|
4
|
+
|
5
|
+
module Torque
|
6
|
+
module Generators
|
7
|
+
class ViewGenerator < Rails::Generators::Base
|
8
|
+
include Torque::PostgreSQL::VersionedCommands::Generator
|
9
|
+
|
10
|
+
class_option :materialized, type: :boolean, aliases: %i(--m), default: false,
|
11
|
+
desc: 'Use materialized view instead of regular view'
|
12
|
+
|
13
|
+
alias create_view_file create_migration_file
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -5,7 +5,7 @@ module Torque
|
|
5
5
|
module Adapter
|
6
6
|
module DatabaseStatements
|
7
7
|
|
8
|
-
EXTENDED_DATABASE_TYPES = %i
|
8
|
+
EXTENDED_DATABASE_TYPES = %i[enum enum_set interval]
|
9
9
|
|
10
10
|
# Switch between dump mode or not
|
11
11
|
def dump_mode!
|
@@ -48,8 +48,8 @@ module Torque
|
|
48
48
|
def schema_exists?(name, filtered: true)
|
49
49
|
return user_defined_schemas.include?(name.to_s) if filtered
|
50
50
|
|
51
|
-
query_value(<<-SQL) == 1
|
52
|
-
SELECT 1 FROM pg_catalog.pg_namespace WHERE nspname =
|
51
|
+
query_value(<<-SQL, "SCHEMA") == 1
|
52
|
+
SELECT 1 FROM pg_catalog.pg_namespace WHERE nspname = #{quote(name)}
|
53
53
|
SQL
|
54
54
|
end
|
55
55
|
|
@@ -59,96 +59,75 @@ module Torque
|
|
59
59
|
end
|
60
60
|
alias data_type_exists? type_exists?
|
61
61
|
|
62
|
-
# Configure the interval format
|
63
|
-
def configure_connection
|
64
|
-
super
|
65
|
-
execute("SET SESSION IntervalStyle TO 'iso_8601'", 'SCHEMA')
|
66
|
-
end
|
67
|
-
|
68
|
-
# Since enums create new types, type map needs to be rebooted to include
|
69
|
-
# the new ones, both normal and array one
|
70
|
-
def create_enum(name, *)
|
71
|
-
super
|
72
|
-
|
73
|
-
oid = query_value("SELECT #{quote(name)}::regtype::oid", "SCHEMA").to_i
|
74
|
-
load_additional_types([oid])
|
75
|
-
end
|
76
|
-
|
77
62
|
# Change some of the types being mapped
|
78
63
|
def initialize_type_map(m = type_map)
|
79
64
|
super
|
80
|
-
m.register_type 'box', OID::Box.new
|
81
|
-
m.register_type 'circle', OID::Circle.new
|
82
|
-
m.register_type 'interval', OID::Interval.new
|
83
|
-
m.register_type 'line', OID::Line.new
|
84
|
-
m.register_type 'segment', OID::Segment.new
|
85
65
|
|
86
|
-
|
66
|
+
if PostgreSQL.config.geometry.enabled
|
67
|
+
m.register_type 'box', OID::Box.new
|
68
|
+
m.register_type 'circle', OID::Circle.new
|
69
|
+
m.register_type 'line', OID::Line.new
|
70
|
+
m.register_type 'segment', OID::Segment.new
|
71
|
+
end
|
72
|
+
|
73
|
+
if PostgreSQL.config.interval.enabled
|
74
|
+
m.register_type 'interval', OID::Interval.new
|
75
|
+
end
|
87
76
|
end
|
88
77
|
|
89
78
|
# :nodoc:
|
90
79
|
def load_additional_types(oids = nil)
|
80
|
+
type_map.alias_type 'regclass', 'varchar'
|
81
|
+
type_map.alias_type 'regconfig', 'varchar'
|
91
82
|
super
|
92
83
|
torque_load_additional_types(oids)
|
93
84
|
end
|
94
85
|
|
95
86
|
# Add the composite types to be loaded too.
|
96
87
|
def torque_load_additional_types(oids = nil)
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
AND NOT EXISTS(
|
110
|
-
SELECT 1 FROM pg_catalog.pg_type el
|
111
|
-
WHERE el.oid = t.typelem AND el.typarray = t.oid
|
112
|
-
)
|
113
|
-
AND (t.typrelid = 0 OR (
|
114
|
-
SELECT c.relkind = 'c' FROM pg_catalog.pg_class c
|
115
|
-
WHERE c.oid = t.typrelid
|
116
|
-
))
|
88
|
+
return unless torque_load_additional_types?
|
89
|
+
|
90
|
+
# Types: (b)ase, (c)omposite, (d)omain, (e)num, (p)seudotype, (r)ange
|
91
|
+
# (m)ultirange
|
92
|
+
|
93
|
+
query = <<~SQL
|
94
|
+
SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput,
|
95
|
+
r.rngsubtype, t.typtype, t.typbasetype, t.typarray
|
96
|
+
FROM pg_type as t
|
97
|
+
LEFT JOIN pg_range as r ON oid = rngtypid
|
98
|
+
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
|
99
|
+
WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
|
117
100
|
SQL
|
118
101
|
|
119
|
-
|
120
|
-
|
102
|
+
if oids
|
103
|
+
query += " AND t.oid IN (%s)" % oids.join(", ")
|
104
|
+
else
|
105
|
+
query += " AND t.typtype IN ('e')"
|
106
|
+
end
|
107
|
+
|
108
|
+
options = { allow_retry: true, materialize_transactions: false }
|
109
|
+
internal_execute(query, 'SCHEMA', **options).each do |row|
|
110
|
+
if row['typtype'] == 'e' && PostgreSQL.config.enum.enabled
|
111
|
+
OID::Enum.create(row, type_map)
|
112
|
+
end
|
121
113
|
end
|
122
114
|
end
|
123
115
|
|
116
|
+
def torque_load_additional_types?
|
117
|
+
PostgreSQL.config.enum.enabled
|
118
|
+
end
|
119
|
+
|
124
120
|
# Gets a list of user defined types.
|
125
121
|
# You can even choose the +category+ filter
|
126
122
|
def user_defined_types(*categories)
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
CASE t.typtype
|
134
|
-
WHEN 'e' THEN 'enum'
|
135
|
-
END AS type
|
136
|
-
FROM pg_type t
|
137
|
-
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
|
123
|
+
categories = categories.compact.presence || %w[c e p r m]
|
124
|
+
|
125
|
+
query(<<-SQL, 'SCHEMA').to_h
|
126
|
+
SELECT t.typname, t.typtype
|
127
|
+
FROM pg_type as t
|
128
|
+
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
|
138
129
|
WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
|
139
|
-
|
140
|
-
AND NOT EXISTS(
|
141
|
-
SELECT 1
|
142
|
-
FROM pg_catalog.pg_type el
|
143
|
-
WHERE el.oid = t.typelem
|
144
|
-
AND el.typarray = t.oid
|
145
|
-
)
|
146
|
-
AND (t.typrelid = 0 OR (
|
147
|
-
SELECT c.relkind = 'c'
|
148
|
-
FROM pg_catalog.pg_class c
|
149
|
-
WHERE c.oid = t.typrelid
|
150
|
-
))
|
151
|
-
ORDER BY t.typtype DESC
|
130
|
+
AND t.typtype IN ('#{categories.join("', '")}')
|
152
131
|
SQL
|
153
132
|
end
|
154
133
|
|
@@ -175,19 +154,10 @@ module Torque
|
|
175
154
|
|
176
155
|
# Build the query for allowed schemas
|
177
156
|
def user_defined_schemas_sql
|
178
|
-
conditions = []
|
179
|
-
conditions << <<-SQL.squish if schemas_blacklist.any?
|
180
|
-
nspname NOT LIKE ALL (ARRAY['#{schemas_blacklist.join("', '")}'])
|
181
|
-
SQL
|
182
|
-
|
183
|
-
conditions << <<-SQL.squish if schemas_whitelist.any?
|
184
|
-
nspname LIKE ANY (ARRAY['#{schemas_whitelist.join("', '")}'])
|
185
|
-
SQL
|
186
|
-
|
187
157
|
<<-SQL.squish
|
188
158
|
SELECT nspname
|
189
159
|
FROM pg_catalog.pg_namespace
|
190
|
-
WHERE 1=1 AND #{
|
160
|
+
WHERE 1=1 AND #{filter_by_schema.join(' AND ')}
|
191
161
|
ORDER BY oid
|
192
162
|
SQL
|
193
163
|
end
|
@@ -195,21 +165,68 @@ module Torque
|
|
195
165
|
# Get the list of columns, and their definition, but only from the
|
196
166
|
# actual table, does not include columns that comes from inherited table
|
197
167
|
def column_definitions(table_name)
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
168
|
+
query(<<~SQL, "SCHEMA")
|
169
|
+
SELECT a.attname, format_type(a.atttypid, a.atttypmod),
|
170
|
+
pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
|
171
|
+
c.collname, col_description(a.attrelid, a.attnum) AS comment,
|
172
|
+
#{supports_identity_columns? ? 'attidentity' : quote('')} AS identity,
|
173
|
+
#{supports_virtual_columns? ? 'attgenerated' : quote('')} as attgenerated
|
174
|
+
FROM pg_attribute a
|
175
|
+
LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
|
176
|
+
LEFT JOIN pg_type t ON a.atttypid = t.oid
|
177
|
+
LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation
|
178
|
+
WHERE a.attrelid = #{quote(quote_table_name(table_name))}::regclass
|
179
|
+
AND a.attnum > 0 AND NOT a.attisdropped
|
180
|
+
#{'AND a.attislocal' if @_dump_mode}
|
181
|
+
ORDER BY a.attnum
|
182
|
+
SQL
|
183
|
+
end
|
184
|
+
|
185
|
+
# Get all possible schema entries that can be created via versioned
|
186
|
+
# commands of the provided type. Mostly for covering removals and not
|
187
|
+
# dump them
|
188
|
+
def list_versioned_commands(type)
|
189
|
+
query =
|
190
|
+
case type
|
191
|
+
when :function
|
192
|
+
<<-SQL.squish
|
193
|
+
SELECT n.nspname AS schema, p.proname AS name
|
194
|
+
FROM pg_catalog.pg_proc p
|
195
|
+
INNER JOIN pg_namespace n ON n.oid = p.pronamespace
|
196
|
+
WHERE 1=1 AND #{filter_by_schema.join(' AND ')};
|
197
|
+
SQL
|
198
|
+
when :type
|
199
|
+
<<-SQL.squish
|
200
|
+
SELECT n.nspname AS schema, t.typname AS name
|
201
|
+
FROM pg_type t
|
202
|
+
INNER JOIN pg_namespace n ON n.oid = t.typnamespace
|
203
|
+
WHERE 1=1 AND t.typtype NOT IN ('e')
|
204
|
+
AND #{filter_by_schema.join(' AND ')};
|
205
|
+
SQL
|
206
|
+
when :view
|
207
|
+
<<-SQL.squish
|
208
|
+
SELECT n.nspname AS schema, c.relname AS name
|
209
|
+
FROM pg_class c
|
210
|
+
INNER JOIN pg_namespace n ON n.oid = c.relnamespace
|
211
|
+
WHERE 1=1 AND c.relkind IN ('v', 'm')
|
212
|
+
AND #{filter_by_schema.join(' AND ')};
|
213
|
+
SQL
|
214
|
+
end
|
215
|
+
|
216
|
+
select_rows(query, 'SCHEMA')
|
217
|
+
end
|
218
|
+
|
219
|
+
# Build the condition for filtering by schema
|
220
|
+
def filter_by_schema
|
221
|
+
conditions = []
|
222
|
+
conditions << <<-SQL.squish if schemas_blacklist.any?
|
223
|
+
nspname NOT LIKE ALL (ARRAY['#{schemas_blacklist.join("', '")}'])
|
224
|
+
SQL
|
225
|
+
|
226
|
+
conditions << <<-SQL.squish if schemas_whitelist.any?
|
227
|
+
nspname LIKE ANY (ARRAY['#{schemas_whitelist.join("', '")}'])
|
212
228
|
SQL
|
229
|
+
conditions
|
213
230
|
end
|
214
231
|
|
215
232
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Torque
|
4
|
+
module PostgreSQL
|
5
|
+
module Adapter
|
6
|
+
module OID
|
7
|
+
module Array
|
8
|
+
def force_equality?(value)
|
9
|
+
PostgreSQL.config.predicate_builder.handle_array_attributes ? false : super
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
::ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Array.prepend(Array)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -7,9 +7,7 @@ module Torque
|
|
7
7
|
alias c= intercept=
|
8
8
|
|
9
9
|
def a=(value)
|
10
|
-
self.slope = vertical?
|
11
|
-
? Float::INFINITY \
|
12
|
-
: Rational(value, b)
|
10
|
+
self.slope = vertical? ? Float::INFINITY : Rational(value, b)
|
13
11
|
end
|
14
12
|
|
15
13
|
def a
|
@@ -17,9 +15,7 @@ module Torque
|
|
17
15
|
end
|
18
16
|
|
19
17
|
def b=(value)
|
20
|
-
self.slope = value.zero?
|
21
|
-
? Float::INFINITY \
|
22
|
-
: Rational(a, value)
|
18
|
+
self.slope = value.zero? ? Float::INFINITY : Rational(a, value)
|
23
19
|
end
|
24
20
|
|
25
21
|
def b
|
@@ -7,7 +7,7 @@ module Torque
|
|
7
7
|
class Range < ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Range
|
8
8
|
HASH_PICK = %i[from start end to].freeze
|
9
9
|
|
10
|
-
module
|
10
|
+
module Comparison
|
11
11
|
def <=>(other)
|
12
12
|
return super unless other.acts_like?(:date) || other.acts_like?(:time)
|
13
13
|
other = other.to_time if other.acts_like?(:date)
|
@@ -17,9 +17,9 @@ module Torque
|
|
17
17
|
|
18
18
|
def cast_value(value)
|
19
19
|
case value
|
20
|
-
when Array
|
20
|
+
when ::Array
|
21
21
|
cast_custom(value[0], value[1])
|
22
|
-
when Hash
|
22
|
+
when ::Hash
|
23
23
|
pieces = value.with_indifferent_access.values_at(*HASH_PICK)
|
24
24
|
cast_custom(pieces[0] || pieces[1], pieces[2] || pieces[3])
|
25
25
|
else
|
@@ -54,7 +54,7 @@ module Torque
|
|
54
54
|
::ActiveRecord::ConnectionAdapters::PostgreSQL::OID.send(:remove_const, :Range)
|
55
55
|
::ActiveRecord::ConnectionAdapters::PostgreSQL::OID.const_set(:Range, Range)
|
56
56
|
|
57
|
-
::Float.prepend(Range::
|
57
|
+
::Float.prepend(Range::Comparison)
|
58
58
|
end
|
59
59
|
end
|
60
60
|
end
|
@@ -1,24 +1,2 @@
|
|
1
|
-
require_relative 'oid/
|
2
|
-
require_relative 'oid/circle'
|
3
|
-
require_relative 'oid/enum'
|
4
|
-
require_relative 'oid/enum_set'
|
5
|
-
require_relative 'oid/interval'
|
6
|
-
require_relative 'oid/line'
|
1
|
+
require_relative 'oid/array'
|
7
2
|
require_relative 'oid/range'
|
8
|
-
require_relative 'oid/segment'
|
9
|
-
|
10
|
-
module Torque
|
11
|
-
module PostgreSQL
|
12
|
-
module Adapter
|
13
|
-
module OID
|
14
|
-
end
|
15
|
-
|
16
|
-
ActiveRecord::Type.register(:box, OID::Box, adapter: :postgresql)
|
17
|
-
ActiveRecord::Type.register(:circle, OID::Circle, adapter: :postgresql)
|
18
|
-
ActiveRecord::Type.register(:enum, OID::Enum, adapter: :postgresql)
|
19
|
-
ActiveRecord::Type.register(:enum_set, OID::EnumSet, adapter: :postgresql)
|
20
|
-
ActiveRecord::Type.register(:line, OID::Line, adapter: :postgresql)
|
21
|
-
ActiveRecord::Type.register(:segment, OID::Segment, adapter: :postgresql)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -4,21 +4,27 @@ module Torque
|
|
4
4
|
module PostgreSQL
|
5
5
|
module Adapter
|
6
6
|
module Quoting
|
7
|
+
QUOTED_TYPE_NAMES = Concurrent::Map.new
|
7
8
|
|
8
9
|
Name = ActiveRecord::ConnectionAdapters::PostgreSQL::Name
|
9
10
|
Column = ActiveRecord::ConnectionAdapters::PostgreSQL::Column
|
10
11
|
ColumnDefinition = ActiveRecord::ConnectionAdapters::ColumnDefinition
|
12
|
+
Utils = ActiveRecord::ConnectionAdapters::PostgreSQL::Utils
|
11
13
|
|
12
14
|
# Quotes type names for use in SQL queries.
|
13
|
-
def quote_type_name(
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
def quote_type_name(name, *args)
|
16
|
+
QUOTED_TYPE_NAMES[args] ||= begin
|
17
|
+
name = name.to_s
|
18
|
+
args << 'public' if args.empty? && !name.include?('.')
|
19
|
+
quote_identifier_name(name, *args)
|
18
20
|
end
|
21
|
+
end
|
19
22
|
|
20
|
-
|
21
|
-
|
23
|
+
# Make sure to support all sorts of different compositions of names
|
24
|
+
def quote_identifier_name(name, schema = nil)
|
25
|
+
name = Utils.extract_schema_qualified_name(name.to_s) unless name.is_a?(Name)
|
26
|
+
name.instance_variable_set(:@schema, Utils.unquote_identifier(schema.to_s)) if schema
|
27
|
+
name.quoted.freeze
|
22
28
|
end
|
23
29
|
|
24
30
|
def quote_default_expression(value, column)
|
@@ -3,39 +3,18 @@ module Torque
|
|
3
3
|
module Adapter
|
4
4
|
module SchemaCreation
|
5
5
|
|
6
|
-
#
|
7
|
-
|
8
|
-
|
9
|
-
create_sql << "IF NOT EXISTS " if o.if_not_exists
|
10
|
-
create_sql << "#{quote_table_name(o.name)} "
|
11
|
-
|
12
|
-
statements = o.columns.map { |c| accept c }
|
13
|
-
statements << accept(o.primary_keys) if o.primary_keys
|
14
|
-
|
15
|
-
if supports_indexes_in_create?
|
16
|
-
statements.concat(o.indexes.map { |c, o| index_in_create(o.name, c, o) })
|
17
|
-
end
|
18
|
-
|
19
|
-
if @conn.supports_foreign_keys?
|
20
|
-
statements.concat(o.foreign_keys.map { |fk| accept fk })
|
21
|
-
end
|
22
|
-
|
23
|
-
if respond_to?(:supports_check_constraints?) && supports_check_constraints?
|
24
|
-
statements.concat(o.check_constraints.map { |chk| accept chk })
|
25
|
-
end
|
26
|
-
|
27
|
-
create_sql << "(#{statements.join(', ')})" \
|
28
|
-
if statements.present? || o.inherits.present?
|
29
|
-
|
30
|
-
add_table_options!(create_sql, o)
|
31
|
-
|
6
|
+
# Inherits are now setup via table options, but keep the implementation
|
7
|
+
# supported by this gem
|
8
|
+
def add_table_options!(create_sql, o)
|
32
9
|
if o.inherits.present?
|
10
|
+
# Make sure we always have parenthesis
|
11
|
+
create_sql << '()' unless create_sql[-1] == ')'
|
12
|
+
|
33
13
|
tables = o.inherits.map(&method(:quote_table_name))
|
34
14
|
create_sql << " INHERITS ( #{tables.join(' , ')} )"
|
35
15
|
end
|
36
16
|
|
37
|
-
create_sql
|
38
|
-
create_sql
|
17
|
+
super(create_sql, o)
|
39
18
|
end
|
40
19
|
end
|
41
20
|
|
@@ -3,7 +3,26 @@
|
|
3
3
|
module Torque
|
4
4
|
module PostgreSQL
|
5
5
|
module Adapter
|
6
|
+
module ColumnMethods
|
7
|
+
|
8
|
+
# Adds a search language column to the table. See +add_search_language+
|
9
|
+
def search_language(*names, **options)
|
10
|
+
raise ArgumentError, "Missing column name(s) for search_language" if names.empty?
|
11
|
+
names.each { |name| column(name, :regconfig, **options) }
|
12
|
+
end
|
13
|
+
|
14
|
+
# Add a search vector column to the table. See +add_search_vector+
|
15
|
+
def search_vector(*names, columns:, **options)
|
16
|
+
raise ArgumentError, "Missing column name(s) for search_vector" if names.empty?
|
17
|
+
options = Attributes::Builder.search_vector_options(columns: columns, **options)
|
18
|
+
names.each { |name| column(name, :virtual, **options) }
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
6
23
|
module TableDefinition
|
24
|
+
include ColumnMethods
|
25
|
+
|
7
26
|
attr_reader :inherits
|
8
27
|
|
9
28
|
def initialize(*args, **options)
|
@@ -12,8 +31,47 @@ module Torque
|
|
12
31
|
@inherits = Array.wrap(options.delete(:inherits)).flatten.compact \
|
13
32
|
if options.key?(:inherits)
|
14
33
|
end
|
34
|
+
|
35
|
+
def set_primary_key(tn, id, primary_key, *, **)
|
36
|
+
super unless @inherits.present? && primary_key.blank? && id == :primary_key
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def create_column_definition(name, type, options)
|
42
|
+
if type == :enum_set
|
43
|
+
type = :enum
|
44
|
+
options ||= {}
|
45
|
+
options[:array] = true
|
46
|
+
end
|
47
|
+
|
48
|
+
super(name, type, options)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Add exclusive support for versioned commands when importing from schema
|
53
|
+
# dump. This ensures that such methods are not available in regular
|
54
|
+
# migrations.
|
55
|
+
module Definition
|
56
|
+
|
57
|
+
def create_function(name, version:, dir: pool.migrations_paths)
|
58
|
+
return super unless VersionedCommands.valid_type?(:function)
|
59
|
+
execute VersionedCommands.fetch_command(dir, :function, name, version)
|
60
|
+
end
|
61
|
+
|
62
|
+
def create_type(name, version:, dir: pool.migrations_paths)
|
63
|
+
return super unless VersionedCommands.valid_type?(:type)
|
64
|
+
execute VersionedCommands.fetch_command(dir, :type, name, version)
|
65
|
+
end
|
66
|
+
|
67
|
+
def create_view(name, version:, dir: pool.migrations_paths)
|
68
|
+
return super unless VersionedCommands.valid_type?(:view)
|
69
|
+
execute VersionedCommands.fetch_command(dir, :view, name, version)
|
70
|
+
end
|
71
|
+
|
15
72
|
end
|
16
73
|
|
74
|
+
ActiveRecord::ConnectionAdapters::PostgreSQL::Table.include ColumnMethods
|
17
75
|
ActiveRecord::ConnectionAdapters::PostgreSQL::TableDefinition.include TableDefinition
|
18
76
|
end
|
19
77
|
end
|