activerecord 6.0.0.rc1 → 6.0.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +39 -0
- data/lib/active_record/associations/builder/collection_association.rb +2 -2
- data/lib/active_record/associations/collection_proxy.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_association.rb +11 -2
- data/lib/active_record/associations/preloader/association.rb +3 -1
- data/lib/active_record/attribute_methods.rb +0 -51
- data/lib/active_record/attribute_methods/dirty.rb +6 -1
- data/lib/active_record/autosave_association.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +93 -11
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/quoting.rb +53 -0
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +8 -7
- data/lib/active_record/connection_adapters/abstract/transaction.rb +12 -4
- data/lib/active_record/connection_adapters/abstract_adapter.rb +40 -20
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +3 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +10 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +39 -2
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +8 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +38 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +12 -2
- data/lib/active_record/connection_handling.rb +6 -2
- data/lib/active_record/database_configurations.rb +6 -6
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/middleware/database_selector.rb +3 -3
- data/lib/active_record/middleware/database_selector/resolver.rb +2 -2
- data/lib/active_record/migration.rb +26 -23
- data/lib/active_record/railtie.rb +0 -1
- data/lib/active_record/railties/databases.rake +57 -23
- data/lib/active_record/reflection.rb +1 -1
- data/lib/active_record/relation/calculations.rb +1 -1
- data/lib/active_record/relation/finder_methods.rb +4 -2
- data/lib/active_record/relation/merger.rb +6 -2
- data/lib/active_record/relation/query_methods.rb +32 -32
- data/lib/active_record/sanitization.rb +30 -2
- data/lib/active_record/schema.rb +1 -1
- data/lib/active_record/schema_dumper.rb +5 -1
- data/lib/active_record/table_metadata.rb +6 -10
- data/lib/active_record/tasks/database_tasks.rb +41 -8
- data/lib/active_record/tasks/mysql_database_tasks.rb +3 -1
- data/lib/active_record/timestamp.rb +26 -16
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +9 -10
- data/lib/active_record/type_caster/connection.rb +16 -10
- data/lib/arel/visitors/depth_first.rb +1 -1
- data/lib/arel/visitors/to_sql.rb +23 -26
- data/lib/arel/visitors/visitor.rb +9 -5
- metadata +8 -8
@@ -33,17 +33,17 @@ module ActiveRecord
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def enable_query_cache!
|
36
|
-
@query_cache_enabled[connection_cache_key(
|
36
|
+
@query_cache_enabled[connection_cache_key(current_thread)] = true
|
37
37
|
connection.enable_query_cache! if active_connection?
|
38
38
|
end
|
39
39
|
|
40
40
|
def disable_query_cache!
|
41
|
-
@query_cache_enabled.delete connection_cache_key(
|
41
|
+
@query_cache_enabled.delete connection_cache_key(current_thread)
|
42
42
|
connection.disable_query_cache! if active_connection?
|
43
43
|
end
|
44
44
|
|
45
45
|
def query_cache_enabled
|
46
|
-
@query_cache_enabled[connection_cache_key(
|
46
|
+
@query_cache_enabled[connection_cache_key(current_thread)]
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
@@ -142,6 +142,59 @@ module ActiveRecord
|
|
142
142
|
value.to_s.gsub(%r{ (/ (?: | \g<1>) \*) \+? \s* | \s* (\* (?: | \g<2>) /) }x, "")
|
143
143
|
end
|
144
144
|
|
145
|
+
def column_name_matcher # :nodoc:
|
146
|
+
COLUMN_NAME
|
147
|
+
end
|
148
|
+
|
149
|
+
def column_name_with_order_matcher # :nodoc:
|
150
|
+
COLUMN_NAME_WITH_ORDER
|
151
|
+
end
|
152
|
+
|
153
|
+
# Regexp for column names (with or without a table name prefix).
|
154
|
+
# Matches the following:
|
155
|
+
#
|
156
|
+
# "#{table_name}.#{column_name}"
|
157
|
+
# "#{column_name}"
|
158
|
+
COLUMN_NAME = /
|
159
|
+
\A
|
160
|
+
(
|
161
|
+
(?:
|
162
|
+
# table_name.column_name | function(one or no argument)
|
163
|
+
((?:\w+\.)?\w+) | \w+\((?:|\g<2>)\)
|
164
|
+
)
|
165
|
+
(?:\s+AS\s+\w+)?
|
166
|
+
)
|
167
|
+
(?:\s*,\s*\g<1>)*
|
168
|
+
\z
|
169
|
+
/ix
|
170
|
+
|
171
|
+
# Regexp for column names with order (with or without a table name prefix,
|
172
|
+
# with or without various order modifiers). Matches the following:
|
173
|
+
#
|
174
|
+
# "#{table_name}.#{column_name}"
|
175
|
+
# "#{table_name}.#{column_name} #{direction}"
|
176
|
+
# "#{table_name}.#{column_name} #{direction} NULLS FIRST"
|
177
|
+
# "#{table_name}.#{column_name} NULLS LAST"
|
178
|
+
# "#{column_name}"
|
179
|
+
# "#{column_name} #{direction}"
|
180
|
+
# "#{column_name} #{direction} NULLS FIRST"
|
181
|
+
# "#{column_name} NULLS LAST"
|
182
|
+
COLUMN_NAME_WITH_ORDER = /
|
183
|
+
\A
|
184
|
+
(
|
185
|
+
(?:
|
186
|
+
# table_name.column_name | function(one or no argument)
|
187
|
+
((?:\w+\.)?\w+) | \w+\((?:|\g<2>)\)
|
188
|
+
)
|
189
|
+
(?:\s+ASC|\s+DESC)?
|
190
|
+
(?:\s+NULLS\s+(?:FIRST|LAST))?
|
191
|
+
)
|
192
|
+
(?:\s*,\s*\g<1>)*
|
193
|
+
\z
|
194
|
+
/ix
|
195
|
+
|
196
|
+
private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
|
197
|
+
|
145
198
|
private
|
146
199
|
def type_casted_binds(binds)
|
147
200
|
if binds.first.is_a?(Array)
|
@@ -15,7 +15,7 @@ module ActiveRecord
|
|
15
15
|
def column_spec_for_primary_key(column)
|
16
16
|
return {} if default_primary_key?(column)
|
17
17
|
spec = { id: schema_type(column).inspect }
|
18
|
-
spec.merge!(prepare_column_options(column).except!(:null))
|
18
|
+
spec.merge!(prepare_column_options(column).except!(:null, :comment))
|
19
19
|
spec[:default] ||= "nil" if explicit_primary_key_default?(column)
|
20
20
|
spec
|
21
21
|
end
|
@@ -302,7 +302,7 @@ module ActiveRecord
|
|
302
302
|
if pk.is_a?(Array)
|
303
303
|
td.primary_keys pk
|
304
304
|
else
|
305
|
-
td.primary_key pk, options.fetch(:id, :primary_key), options
|
305
|
+
td.primary_key pk, options.fetch(:id, :primary_key), options.except(:comment)
|
306
306
|
end
|
307
307
|
end
|
308
308
|
|
@@ -518,14 +518,15 @@ module ActiveRecord
|
|
518
518
|
# Available options are (none of these exists by default):
|
519
519
|
# * <tt>:limit</tt> -
|
520
520
|
# Requests a maximum column length. This is the number of characters for a <tt>:string</tt> column
|
521
|
-
# and number of bytes for <tt>:text</tt>, <tt>:binary</tt
|
521
|
+
# and number of bytes for <tt>:text</tt>, <tt>:binary</tt>, and <tt>:integer</tt> columns.
|
522
522
|
# This option is ignored by some backends.
|
523
523
|
# * <tt>:default</tt> -
|
524
524
|
# The column's default value. Use +nil+ for +NULL+.
|
525
525
|
# * <tt>:null</tt> -
|
526
526
|
# Allows or disallows +NULL+ values in the column.
|
527
527
|
# * <tt>:precision</tt> -
|
528
|
-
# Specifies the precision for the <tt>:decimal</tt
|
528
|
+
# Specifies the precision for the <tt>:decimal</tt>, <tt>:numeric</tt>,
|
529
|
+
# <tt>:datetime</tt>, and <tt>:time</tt> columns.
|
529
530
|
# * <tt>:scale</tt> -
|
530
531
|
# Specifies the scale for the <tt>:decimal</tt> and <tt>:numeric</tt> columns.
|
531
532
|
# * <tt>:collation</tt> -
|
@@ -1060,8 +1061,8 @@ module ActiveRecord
|
|
1060
1061
|
options
|
1061
1062
|
end
|
1062
1063
|
|
1063
|
-
def dump_schema_information
|
1064
|
-
versions =
|
1064
|
+
def dump_schema_information # :nodoc:
|
1065
|
+
versions = schema_migration.all_versions
|
1065
1066
|
insert_versions_sql(versions) if versions.any?
|
1066
1067
|
end
|
1067
1068
|
|
@@ -1077,7 +1078,7 @@ module ActiveRecord
|
|
1077
1078
|
end
|
1078
1079
|
|
1079
1080
|
version = version.to_i
|
1080
|
-
sm_table = quote_table_name(
|
1081
|
+
sm_table = quote_table_name(schema_migration.table_name)
|
1081
1082
|
|
1082
1083
|
migrated = migration_context.get_all_versions
|
1083
1084
|
versions = migration_context.migrations.map(&:version)
|
@@ -1450,7 +1451,7 @@ module ActiveRecord
|
|
1450
1451
|
end
|
1451
1452
|
|
1452
1453
|
def insert_versions_sql(versions)
|
1453
|
-
sm_table = quote_table_name(
|
1454
|
+
sm_table = quote_table_name(schema_migration.table_name)
|
1454
1455
|
|
1455
1456
|
if versions.is_a?(Array)
|
1456
1457
|
sql = +"INSERT INTO #{sm_table} (version) VALUES\n"
|
@@ -98,9 +98,13 @@ module ActiveRecord
|
|
98
98
|
end
|
99
99
|
|
100
100
|
def rollback_records
|
101
|
-
ite = records.uniq
|
101
|
+
ite = records.uniq(&:object_id)
|
102
|
+
already_run_callbacks = {}
|
102
103
|
while record = ite.shift
|
103
|
-
record.
|
104
|
+
trigger_callbacks = record.trigger_transactional_callbacks?
|
105
|
+
should_run_callbacks = !already_run_callbacks[record] && trigger_callbacks
|
106
|
+
already_run_callbacks[record] ||= trigger_callbacks
|
107
|
+
record.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: should_run_callbacks)
|
104
108
|
end
|
105
109
|
ensure
|
106
110
|
ite.each do |i|
|
@@ -113,10 +117,14 @@ module ActiveRecord
|
|
113
117
|
end
|
114
118
|
|
115
119
|
def commit_records
|
116
|
-
ite = records.uniq
|
120
|
+
ite = records.uniq(&:object_id)
|
121
|
+
already_run_callbacks = {}
|
117
122
|
while record = ite.shift
|
118
123
|
if @run_commit_callbacks
|
119
|
-
record.
|
124
|
+
trigger_callbacks = record.trigger_transactional_callbacks?
|
125
|
+
should_run_callbacks = !already_run_callbacks[record] && trigger_callbacks
|
126
|
+
already_run_callbacks[record] ||= trigger_callbacks
|
127
|
+
record.committed!(should_run_callbacks: should_run_callbacks)
|
120
128
|
else
|
121
129
|
# if not running callbacks, only adds the record to the parent transaction
|
122
130
|
connection.add_transaction_record(record)
|
@@ -78,7 +78,7 @@ module ActiveRecord
|
|
78
78
|
SIMPLE_INT = /\A\d+\z/
|
79
79
|
|
80
80
|
attr_accessor :pool
|
81
|
-
attr_reader :
|
81
|
+
attr_reader :visitor, :owner, :logger, :lock, :prepared_statements
|
82
82
|
alias :in_use? :owner
|
83
83
|
|
84
84
|
set_callback :checkin, :after, :enable_lazy_transactions!
|
@@ -106,6 +106,14 @@ module ActiveRecord
|
|
106
106
|
Regexp.union(*parts)
|
107
107
|
end
|
108
108
|
|
109
|
+
def self.quoted_column_names # :nodoc:
|
110
|
+
@quoted_column_names ||= {}
|
111
|
+
end
|
112
|
+
|
113
|
+
def self.quoted_table_names # :nodoc:
|
114
|
+
@quoted_table_names ||= {}
|
115
|
+
end
|
116
|
+
|
109
117
|
def initialize(connection, logger = nil, config = {}) # :nodoc:
|
110
118
|
super()
|
111
119
|
|
@@ -114,11 +122,8 @@ module ActiveRecord
|
|
114
122
|
@instrumenter = ActiveSupport::Notifications.instrumenter
|
115
123
|
@logger = logger
|
116
124
|
@config = config
|
117
|
-
@pool =
|
125
|
+
@pool = ActiveRecord::ConnectionAdapters::NullPool.new
|
118
126
|
@idle_since = Concurrent.monotonic_time
|
119
|
-
@schema_cache = SchemaCache.new self
|
120
|
-
@quoted_column_names, @quoted_table_names = {}, {}
|
121
|
-
@prevent_writes = false
|
122
127
|
@visitor = arel_visitor
|
123
128
|
@statements = build_statement_pool
|
124
129
|
@lock = ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
|
@@ -144,19 +149,7 @@ module ActiveRecord
|
|
144
149
|
# Returns true if the connection is a replica, or if +prevent_writes+
|
145
150
|
# is set to true.
|
146
151
|
def preventing_writes?
|
147
|
-
replica? || prevent_writes
|
148
|
-
end
|
149
|
-
|
150
|
-
# Prevent writing to the database regardless of role.
|
151
|
-
#
|
152
|
-
# In some cases you may want to prevent writes to the database
|
153
|
-
# even if you are on a database that can write. `while_preventing_writes`
|
154
|
-
# will prevent writes to the database for the duration of the block.
|
155
|
-
def while_preventing_writes
|
156
|
-
original, @prevent_writes = @prevent_writes, true
|
157
|
-
yield
|
158
|
-
ensure
|
159
|
-
@prevent_writes = original
|
152
|
+
replica? || ActiveRecord::Base.connection_handler.prevent_writes
|
160
153
|
end
|
161
154
|
|
162
155
|
def migrations_paths # :nodoc:
|
@@ -164,7 +157,22 @@ module ActiveRecord
|
|
164
157
|
end
|
165
158
|
|
166
159
|
def migration_context # :nodoc:
|
167
|
-
MigrationContext.new(migrations_paths)
|
160
|
+
MigrationContext.new(migrations_paths, schema_migration)
|
161
|
+
end
|
162
|
+
|
163
|
+
def schema_migration # :nodoc:
|
164
|
+
@schema_migration ||= begin
|
165
|
+
conn = self
|
166
|
+
spec_name = conn.pool.spec.name
|
167
|
+
name = "#{spec_name}::SchemaMigration"
|
168
|
+
|
169
|
+
Class.new(ActiveRecord::SchemaMigration) do
|
170
|
+
define_singleton_method(:name) { name }
|
171
|
+
define_singleton_method(:to_s) { name }
|
172
|
+
|
173
|
+
self.connection_specification_name = spec_name
|
174
|
+
end
|
175
|
+
end
|
168
176
|
end
|
169
177
|
|
170
178
|
class Version
|
@@ -206,9 +214,13 @@ module ActiveRecord
|
|
206
214
|
@owner = Thread.current
|
207
215
|
end
|
208
216
|
|
217
|
+
def schema_cache
|
218
|
+
@pool.get_schema_cache(self)
|
219
|
+
end
|
220
|
+
|
209
221
|
def schema_cache=(cache)
|
210
222
|
cache.connection = self
|
211
|
-
@
|
223
|
+
@pool.set_schema_cache(cache)
|
212
224
|
end
|
213
225
|
|
214
226
|
# this method must only be called while holding connection pool's mutex
|
@@ -259,6 +271,11 @@ module ActiveRecord
|
|
259
271
|
self.class::ADAPTER_NAME
|
260
272
|
end
|
261
273
|
|
274
|
+
# Does the database for this adapter exist?
|
275
|
+
def self.database_exists?(config)
|
276
|
+
raise NotImplementedError
|
277
|
+
end
|
278
|
+
|
262
279
|
# Does this adapter support DDL rollbacks in transactions? That is, would
|
263
280
|
# CREATE TABLE or ALTER TABLE get rolled back by a transaction?
|
264
281
|
def supports_ddl_transactions?
|
@@ -487,6 +504,9 @@ module ActiveRecord
|
|
487
504
|
#
|
488
505
|
# Prevent @connection's finalizer from touching the socket, or
|
489
506
|
# otherwise communicating with its server, when it is collected.
|
507
|
+
if schema_cache.connection == self
|
508
|
+
schema_cache.connection = nil
|
509
|
+
end
|
490
510
|
end
|
491
511
|
|
492
512
|
# Reset the state of this connection, directing the DBMS to clear
|
@@ -5,7 +5,7 @@ module ActiveRecord
|
|
5
5
|
module DetermineIfPreparableVisitor
|
6
6
|
attr_accessor :preparable
|
7
7
|
|
8
|
-
def accept(
|
8
|
+
def accept(object, collector)
|
9
9
|
@preparable = true
|
10
10
|
super
|
11
11
|
end
|
@@ -20,7 +20,7 @@ module ActiveRecord
|
|
20
20
|
super
|
21
21
|
end
|
22
22
|
|
23
|
-
def visit_Arel_Nodes_SqlLiteral(
|
23
|
+
def visit_Arel_Nodes_SqlLiteral(o, collector)
|
24
24
|
@preparable = false
|
25
25
|
super
|
26
26
|
end
|
@@ -5,11 +5,11 @@ module ActiveRecord
|
|
5
5
|
module MySQL
|
6
6
|
module Quoting # :nodoc:
|
7
7
|
def quote_column_name(name)
|
8
|
-
|
8
|
+
self.class.quoted_column_names[name] ||= "`#{super.gsub('`', '``')}`"
|
9
9
|
end
|
10
10
|
|
11
11
|
def quote_table_name(name)
|
12
|
-
|
12
|
+
self.class.quoted_table_names[name] ||= super.gsub(".", "`.`").freeze
|
13
13
|
end
|
14
14
|
|
15
15
|
def unquoted_true
|
@@ -32,12 +32,49 @@ module ActiveRecord
|
|
32
32
|
"x'#{value.hex}'"
|
33
33
|
end
|
34
34
|
|
35
|
-
def
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
def column_name_matcher
|
36
|
+
COLUMN_NAME
|
37
|
+
end
|
38
|
+
|
39
|
+
def column_name_with_order_matcher
|
40
|
+
COLUMN_NAME_WITH_ORDER
|
40
41
|
end
|
42
|
+
|
43
|
+
COLUMN_NAME = /
|
44
|
+
\A
|
45
|
+
(
|
46
|
+
(?:
|
47
|
+
# `table_name`.`column_name` | function(one or no argument)
|
48
|
+
((?:\w+\.|`\w+`\.)?(?:\w+|`\w+`)) | \w+\((?:|\g<2>)\)
|
49
|
+
)
|
50
|
+
(?:\s+AS\s+(?:\w+|`\w+`))?
|
51
|
+
)
|
52
|
+
(?:\s*,\s*\g<1>)*
|
53
|
+
\z
|
54
|
+
/ix
|
55
|
+
|
56
|
+
COLUMN_NAME_WITH_ORDER = /
|
57
|
+
\A
|
58
|
+
(
|
59
|
+
(?:
|
60
|
+
# `table_name`.`column_name` | function(one or no argument)
|
61
|
+
((?:\w+\.|`\w+`\.)?(?:\w+|`\w+`)) | \w+\((?:|\g<2>)\)
|
62
|
+
)
|
63
|
+
(?:\s+ASC|\s+DESC)?
|
64
|
+
)
|
65
|
+
(?:\s*,\s*\g<1>)*
|
66
|
+
\z
|
67
|
+
/ix
|
68
|
+
|
69
|
+
private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
|
70
|
+
|
71
|
+
private
|
72
|
+
def _type_cast(value)
|
73
|
+
case value
|
74
|
+
when Date, Time then value
|
75
|
+
else super
|
76
|
+
end
|
77
|
+
end
|
41
78
|
end
|
42
79
|
end
|
43
80
|
end
|
@@ -41,13 +41,15 @@ module ActiveRecord
|
|
41
41
|
case column.sql_type
|
42
42
|
when /\Atimestamp\b/
|
43
43
|
:timestamp
|
44
|
+
when /\A(?:enum|set)\b/
|
45
|
+
column.sql_type
|
44
46
|
else
|
45
47
|
super
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
49
51
|
def schema_limit(column)
|
50
|
-
super unless /\A(?:tiny|medium|long)?(?:text|blob)/.match?(column.sql_type)
|
52
|
+
super unless /\A(?:enum|set|(?:tiny|medium|long)?(?:text|blob))\b/.match?(column.sql_type)
|
51
53
|
end
|
52
54
|
|
53
55
|
def schema_precision(column)
|
@@ -8,6 +8,8 @@ require "mysql2"
|
|
8
8
|
|
9
9
|
module ActiveRecord
|
10
10
|
module ConnectionHandling # :nodoc:
|
11
|
+
ER_BAD_DB_ERROR = 1049
|
12
|
+
|
11
13
|
# Establishes a connection to the database that's used by all Active Record objects.
|
12
14
|
def mysql2_connection(config)
|
13
15
|
config = config.symbolize_keys
|
@@ -22,7 +24,7 @@ module ActiveRecord
|
|
22
24
|
client = Mysql2::Client.new(config)
|
23
25
|
ConnectionAdapters::Mysql2Adapter.new(client, logger, nil, config)
|
24
26
|
rescue Mysql2::Error => error
|
25
|
-
if error.
|
27
|
+
if error.error_number == ER_BAD_DB_ERROR
|
26
28
|
raise ActiveRecord::NoDatabaseError
|
27
29
|
else
|
28
30
|
raise
|
@@ -42,6 +44,12 @@ module ActiveRecord
|
|
42
44
|
configure_connection
|
43
45
|
end
|
44
46
|
|
47
|
+
def self.database_exists?(config)
|
48
|
+
!!ActiveRecord::Base.mysql2_connection(config)
|
49
|
+
rescue ActiveRecord::NoDatabaseError
|
50
|
+
false
|
51
|
+
end
|
52
|
+
|
45
53
|
def supports_json?
|
46
54
|
!mariadb? && database_version >= "5.7.8"
|
47
55
|
end
|
@@ -109,6 +117,7 @@ module ActiveRecord
|
|
109
117
|
end
|
110
118
|
|
111
119
|
def discard! # :nodoc:
|
120
|
+
super
|
112
121
|
@connection.automatic_close = false
|
113
122
|
@connection = nil
|
114
123
|
end
|
@@ -30,7 +30,7 @@ module ActiveRecord
|
|
30
30
|
# - "schema.name".table_name
|
31
31
|
# - "schema.name"."table.name"
|
32
32
|
def quote_table_name(name) # :nodoc:
|
33
|
-
|
33
|
+
self.class.quoted_table_names[name] ||= Utils.extract_schema_qualified_name(name.to_s).quoted.freeze
|
34
34
|
end
|
35
35
|
|
36
36
|
# Quotes schema names for use in SQL queries.
|
@@ -44,7 +44,7 @@ module ActiveRecord
|
|
44
44
|
|
45
45
|
# Quotes column names for use in SQL queries.
|
46
46
|
def quote_column_name(name) # :nodoc:
|
47
|
-
|
47
|
+
self.class.quoted_column_names[name] ||= PG::Connection.quote_ident(super).freeze
|
48
48
|
end
|
49
49
|
|
50
50
|
# Quote date/time values for use in SQL input.
|
@@ -78,6 +78,43 @@ module ActiveRecord
|
|
78
78
|
type_map.lookup(column.oid, column.fmod, column.sql_type)
|
79
79
|
end
|
80
80
|
|
81
|
+
def column_name_matcher
|
82
|
+
COLUMN_NAME
|
83
|
+
end
|
84
|
+
|
85
|
+
def column_name_with_order_matcher
|
86
|
+
COLUMN_NAME_WITH_ORDER
|
87
|
+
end
|
88
|
+
|
89
|
+
COLUMN_NAME = /
|
90
|
+
\A
|
91
|
+
(
|
92
|
+
(?:
|
93
|
+
# "table_name"."column_name"::type_name | function(one or no argument)::type_name
|
94
|
+
((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")(?:::\w+)?) | \w+\((?:|\g<2>)\)(?:::\w+)?
|
95
|
+
)
|
96
|
+
(?:\s+AS\s+(?:\w+|"\w+"))?
|
97
|
+
)
|
98
|
+
(?:\s*,\s*\g<1>)*
|
99
|
+
\z
|
100
|
+
/ix
|
101
|
+
|
102
|
+
COLUMN_NAME_WITH_ORDER = /
|
103
|
+
\A
|
104
|
+
(
|
105
|
+
(?:
|
106
|
+
# "table_name"."column_name"::type_name | function(one or no argument)::type_name
|
107
|
+
((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")(?:::\w+)?) | \w+\((?:|\g<2>)\)(?:::\w+)?
|
108
|
+
)
|
109
|
+
(?:\s+ASC|\s+DESC)?
|
110
|
+
(?:\s+NULLS\s+(?:FIRST|LAST))?
|
111
|
+
)
|
112
|
+
(?:\s*,\s*\g<1>)*
|
113
|
+
\z
|
114
|
+
/ix
|
115
|
+
|
116
|
+
private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
|
117
|
+
|
81
118
|
private
|
82
119
|
def lookup_cast_type(sql_type)
|
83
120
|
super(query_value("SELECT #{quote(sql_type)}::regtype::oid", "SCHEMA").to_i)
|