activerecord 6.0.0.rc1 → 6.0.3.rc1
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 +251 -3
- data/README.rdoc +1 -1
- data/lib/active_record.rb +1 -0
- data/lib/active_record/advisory_lock_base.rb +18 -0
- data/lib/active_record/aggregations.rb +0 -1
- data/lib/active_record/association_relation.rb +10 -8
- data/lib/active_record/associations.rb +2 -2
- data/lib/active_record/associations/alias_tracker.rb +0 -1
- data/lib/active_record/associations/association.rb +5 -1
- data/lib/active_record/associations/builder/collection_association.rb +2 -2
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -3
- data/lib/active_record/associations/collection_association.rb +6 -2
- data/lib/active_record/associations/collection_proxy.rb +2 -3
- data/lib/active_record/associations/has_many_association.rb +0 -1
- data/lib/active_record/associations/join_dependency.rb +23 -9
- data/lib/active_record/associations/join_dependency/join_association.rb +12 -3
- data/lib/active_record/associations/preloader.rb +2 -3
- data/lib/active_record/associations/preloader/association.rb +3 -1
- data/lib/active_record/attribute_assignment.rb +0 -1
- data/lib/active_record/attribute_decorators.rb +0 -2
- data/lib/active_record/attribute_methods.rb +0 -51
- data/lib/active_record/attribute_methods/before_type_cast.rb +0 -1
- data/lib/active_record/attribute_methods/dirty.rb +8 -3
- data/lib/active_record/attribute_methods/primary_key.rb +0 -2
- data/lib/active_record/attribute_methods/read.rb +0 -1
- data/lib/active_record/attribute_methods/serialization.rb +0 -1
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +0 -2
- data/lib/active_record/attribute_methods/write.rb +0 -1
- data/lib/active_record/attributes.rb +0 -1
- data/lib/active_record/autosave_association.rb +11 -7
- data/lib/active_record/callbacks.rb +1 -2
- data/lib/active_record/coders/yaml_column.rb +0 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +107 -13
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +21 -15
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +5 -5
- data/lib/active_record/connection_adapters/abstract/quoting.rb +53 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +1 -2
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +27 -27
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +55 -37
- data/lib/active_record/connection_adapters/abstract/transaction.rb +14 -7
- data/lib/active_record/connection_adapters/abstract_adapter.rb +62 -25
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +25 -32
- data/lib/active_record/connection_adapters/connection_specification.rb +3 -4
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -2
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +8 -12
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +0 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +3 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +8 -8
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -4
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +9 -3
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +39 -2
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +15 -29
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +17 -3
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +8 -7
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +38 -3
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +3 -3
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +23 -8
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_handling.rb +17 -22
- data/lib/active_record/core.rb +8 -6
- data/lib/active_record/counter_cache.rb +4 -1
- data/lib/active_record/database_configurations.rb +60 -31
- data/lib/active_record/database_configurations/url_config.rb +0 -1
- data/lib/active_record/dynamic_matchers.rb +2 -3
- data/lib/active_record/enum.rb +9 -0
- data/lib/active_record/explain.rb +0 -1
- data/lib/active_record/fixture_set/table_row.rb +0 -1
- data/lib/active_record/fixture_set/table_rows.rb +0 -1
- data/lib/active_record/fixtures.rb +11 -9
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/inheritance.rb +0 -3
- data/lib/active_record/insert_all.rb +5 -6
- data/lib/active_record/internal_metadata.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +0 -1
- data/lib/active_record/log_subscriber.rb +1 -1
- data/lib/active_record/middleware/database_selector.rb +3 -4
- data/lib/active_record/middleware/database_selector/resolver.rb +5 -8
- data/lib/active_record/migration.rb +43 -32
- data/lib/active_record/migration/command_recorder.rb +6 -18
- data/lib/active_record/migration/compatibility.rb +3 -3
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/model_schema.rb +3 -2
- data/lib/active_record/nested_attributes.rb +0 -2
- data/lib/active_record/no_touching.rb +2 -2
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +4 -5
- data/lib/active_record/querying.rb +1 -1
- data/lib/active_record/railtie.rb +1 -2
- data/lib/active_record/railties/collection_cache_association_loading.rb +1 -1
- data/lib/active_record/railties/databases.rake +63 -23
- data/lib/active_record/reflection.rb +9 -9
- data/lib/active_record/relation.rb +13 -1
- data/lib/active_record/relation/batches.rb +0 -1
- data/lib/active_record/relation/calculations.rb +3 -5
- data/lib/active_record/relation/delegation.rb +7 -6
- data/lib/active_record/relation/finder_methods.rb +14 -4
- data/lib/active_record/relation/from_clause.rb +4 -0
- data/lib/active_record/relation/merger.rb +6 -3
- data/lib/active_record/relation/predicate_builder.rb +1 -5
- data/lib/active_record/relation/query_methods.rb +94 -55
- data/lib/active_record/relation/spawn_methods.rb +0 -1
- data/lib/active_record/relation/where_clause.rb +0 -1
- data/lib/active_record/result.rb +0 -1
- 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/schema_migration.rb +1 -1
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/scoping/default.rb +0 -1
- data/lib/active_record/scoping/named.rb +3 -3
- data/lib/active_record/store.rb +1 -1
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +21 -10
- data/lib/active_record/tasks/database_tasks.rb +76 -8
- data/lib/active_record/tasks/mysql_database_tasks.rb +3 -2
- data/lib/active_record/tasks/postgresql_database_tasks.rb +0 -1
- data/lib/active_record/tasks/sqlite_database_tasks.rb +0 -1
- data/lib/active_record/test_databases.rb +1 -16
- data/lib/active_record/test_fixtures.rb +2 -1
- data/lib/active_record/timestamp.rb +26 -17
- data/lib/active_record/touch_later.rb +3 -2
- data/lib/active_record/transactions.rb +18 -19
- data/lib/active_record/type.rb +0 -1
- data/lib/active_record/type/adapter_specific_registry.rb +2 -5
- data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
- data/lib/active_record/type/serialized.rb +0 -1
- data/lib/active_record/type/type_map.rb +0 -1
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type_caster/connection.rb +16 -10
- data/lib/active_record/validations.rb +3 -3
- data/lib/active_record/validations/associated.rb +1 -2
- data/lib/arel.rb +17 -6
- data/lib/arel/predications.rb +5 -6
- data/lib/arel/visitors/depth_first.rb +1 -2
- data/lib/arel/visitors/dot.rb +0 -1
- data/lib/arel/visitors/mssql.rb +0 -1
- data/lib/arel/visitors/oracle.rb +1 -2
- data/lib/arel/visitors/oracle12.rb +0 -1
- data/lib/arel/visitors/postgresql.rb +0 -1
- data/lib/arel/visitors/sqlite.rb +0 -1
- data/lib/arel/visitors/to_sql.rb +23 -27
- data/lib/arel/visitors/visitor.rb +9 -6
- data/lib/arel/visitors/where_sql.rb +0 -1
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration.rb +0 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +0 -1
- metadata +13 -9
@@ -19,7 +19,7 @@ module ActiveRecord
|
|
19
19
|
|
20
20
|
def visit_ChangeColumnDefinition(o)
|
21
21
|
column = o.column
|
22
|
-
column.sql_type = type_to_sql(column.type, column.options)
|
22
|
+
column.sql_type = type_to_sql(column.type, **column.options)
|
23
23
|
quoted_column_name = quote_column_name(o.name)
|
24
24
|
|
25
25
|
change_column_sql = +"ALTER COLUMN #{quoted_column_name} TYPE #{column.sql_type}"
|
@@ -33,7 +33,7 @@ module ActiveRecord
|
|
33
33
|
if options[:using]
|
34
34
|
change_column_sql << " USING #{options[:using]}"
|
35
35
|
elsif options[:cast_as]
|
36
|
-
cast_as_type = type_to_sql(options[:cast_as], options)
|
36
|
+
cast_as_type = type_to_sql(options[:cast_as], **options)
|
37
37
|
change_column_sql << " USING CAST(#{quoted_column_name} AS #{cast_as_type})"
|
38
38
|
end
|
39
39
|
|
@@ -74,7 +74,7 @@ module ActiveRecord
|
|
74
74
|
INNER JOIN pg_index d ON t.oid = d.indrelid
|
75
75
|
INNER JOIN pg_class i ON d.indexrelid = i.oid
|
76
76
|
LEFT JOIN pg_namespace n ON n.oid = i.relnamespace
|
77
|
-
WHERE i.relkind
|
77
|
+
WHERE i.relkind IN ('i', 'I')
|
78
78
|
AND i.relname = #{index[:name]}
|
79
79
|
AND t.relname = #{table[:name]}
|
80
80
|
AND n.nspname = #{index[:schema]}
|
@@ -92,7 +92,7 @@ module ActiveRecord
|
|
92
92
|
INNER JOIN pg_index d ON t.oid = d.indrelid
|
93
93
|
INNER JOIN pg_class i ON d.indexrelid = i.oid
|
94
94
|
LEFT JOIN pg_namespace n ON n.oid = i.relnamespace
|
95
|
-
WHERE i.relkind
|
95
|
+
WHERE i.relkind IN ('i', 'I')
|
96
96
|
AND d.indisprimary = 'f'
|
97
97
|
AND t.relname = #{scope[:name]}
|
98
98
|
AND n.nspname = #{scope[:schema]}
|
@@ -390,7 +390,7 @@ module ActiveRecord
|
|
390
390
|
rename_table_indexes(table_name, new_name)
|
391
391
|
end
|
392
392
|
|
393
|
-
def add_column(table_name, column_name, type, options
|
393
|
+
def add_column(table_name, column_name, type, **options) #:nodoc:
|
394
394
|
clear_cache!
|
395
395
|
super
|
396
396
|
change_column_comment(table_name, column_name, options[:comment]) if options.key?(:comment)
|
@@ -439,7 +439,7 @@ module ActiveRecord
|
|
439
439
|
end
|
440
440
|
|
441
441
|
def add_index(table_name, column_name, options = {}) #:nodoc:
|
442
|
-
index_name, index_type, index_columns_and_opclasses, index_options, index_algorithm, index_using, comment = add_index_options(table_name, column_name, options)
|
442
|
+
index_name, index_type, index_columns_and_opclasses, index_options, index_algorithm, index_using, comment = add_index_options(table_name, column_name, **options)
|
443
443
|
execute("CREATE #{index_type} INDEX #{index_algorithm} #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} #{index_using} (#{index_columns_and_opclasses})#{index_options}").tap do
|
444
444
|
execute "COMMENT ON INDEX #{quote_column_name(index_name)} IS #{quote(comment)}" if comment
|
445
445
|
end
|
@@ -553,12 +553,12 @@ module ActiveRecord
|
|
553
553
|
# requires that the ORDER BY include the distinct column.
|
554
554
|
def columns_for_distinct(columns, orders) #:nodoc:
|
555
555
|
order_columns = orders.reject(&:blank?).map { |s|
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
556
|
+
# Convert Arel node to string
|
557
|
+
s = visitor.compile(s) unless s.is_a?(String)
|
558
|
+
# Remove any ASC/DESC modifiers
|
559
|
+
s.gsub(/\s+(?:ASC|DESC)\b/i, "")
|
560
|
+
.gsub(/\s+NULLS\s+(?:FIRST|LAST)\b/i, "")
|
561
|
+
}.reject(&:blank?).map.with_index { |column, i| "#{column} AS alias_#{i}" }
|
562
562
|
|
563
563
|
(order_columns << super).join(", ")
|
564
564
|
end
|
@@ -613,8 +613,8 @@ module ActiveRecord
|
|
613
613
|
PostgreSQL::SchemaCreation.new(self)
|
614
614
|
end
|
615
615
|
|
616
|
-
def create_table_definition(*args)
|
617
|
-
PostgreSQL::TableDefinition.new(self, *args)
|
616
|
+
def create_table_definition(*args, **options)
|
617
|
+
PostgreSQL::TableDefinition.new(self, *args, **options)
|
618
618
|
end
|
619
619
|
|
620
620
|
def create_alter_table(name)
|
@@ -679,14 +679,14 @@ module ActiveRecord
|
|
679
679
|
end
|
680
680
|
end
|
681
681
|
|
682
|
-
def add_column_for_alter(table_name, column_name, type, options
|
682
|
+
def add_column_for_alter(table_name, column_name, type, **options)
|
683
683
|
return super unless options.key?(:comment)
|
684
684
|
[super, Proc.new { change_column_comment(table_name, column_name, options[:comment]) }]
|
685
685
|
end
|
686
686
|
|
687
687
|
def change_column_for_alter(table_name, column_name, type, options = {})
|
688
688
|
td = create_table_definition(table_name)
|
689
|
-
cd = td.new_column_definition(column_name, type, options)
|
689
|
+
cd = td.new_column_definition(column_name, type, **options)
|
690
690
|
sqls = [schema_creation.accept(ChangeColumnDefinition.new(cd, column_name))]
|
691
691
|
sqls << Proc.new { change_column_comment(table_name, column_name, options[:comment]) } if options.key?(:comment)
|
692
692
|
sqls
|
@@ -711,20 +711,6 @@ module ActiveRecord
|
|
711
711
|
"ALTER COLUMN #{quote_column_name(column_name)} #{null ? 'DROP' : 'SET'} NOT NULL"
|
712
712
|
end
|
713
713
|
|
714
|
-
def add_timestamps_for_alter(table_name, options = {})
|
715
|
-
options[:null] = false if options[:null].nil?
|
716
|
-
|
717
|
-
if !options.key?(:precision) && supports_datetime_with_precision?
|
718
|
-
options[:precision] = 6
|
719
|
-
end
|
720
|
-
|
721
|
-
[add_column_for_alter(table_name, :created_at, :datetime, options), add_column_for_alter(table_name, :updated_at, :datetime, options)]
|
722
|
-
end
|
723
|
-
|
724
|
-
def remove_timestamps_for_alter(table_name, options = {})
|
725
|
-
[remove_column_for_alter(table_name, :updated_at), remove_column_for_alter(table_name, :created_at)]
|
726
|
-
end
|
727
|
-
|
728
714
|
def add_index_opclass(quoted_columns, **options)
|
729
715
|
opclasses = options_for_index_columns(options[:opclass])
|
730
716
|
quoted_columns.each do |name, column|
|
@@ -733,7 +719,7 @@ module ActiveRecord
|
|
733
719
|
end
|
734
720
|
|
735
721
|
def add_options_for_index_columns(quoted_columns, **options)
|
736
|
-
quoted_columns = add_index_opclass(quoted_columns, options)
|
722
|
+
quoted_columns = add_index_opclass(quoted_columns, **options)
|
737
723
|
super
|
738
724
|
end
|
739
725
|
|
@@ -46,7 +46,7 @@ module ActiveRecord
|
|
46
46
|
conn = PG.connect(conn_params)
|
47
47
|
ConnectionAdapters::PostgreSQLAdapter.new(conn, logger, conn_params, config)
|
48
48
|
rescue ::PG::Error => error
|
49
|
-
if error.message.include?(
|
49
|
+
if error.message.include?(conn_params[:dbname])
|
50
50
|
raise ActiveRecord::NoDatabaseError
|
51
51
|
else
|
52
52
|
raise
|
@@ -156,6 +156,10 @@ module ActiveRecord
|
|
156
156
|
true
|
157
157
|
end
|
158
158
|
|
159
|
+
def supports_partitioned_indexes?
|
160
|
+
database_version >= 110_000
|
161
|
+
end
|
162
|
+
|
159
163
|
def supports_partial_index?
|
160
164
|
true
|
161
165
|
end
|
@@ -259,6 +263,12 @@ module ActiveRecord
|
|
259
263
|
@use_insert_returning = @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
|
260
264
|
end
|
261
265
|
|
266
|
+
def self.database_exists?(config)
|
267
|
+
!!ActiveRecord::Base.postgresql_connection(config)
|
268
|
+
rescue ActiveRecord::NoDatabaseError
|
269
|
+
false
|
270
|
+
end
|
271
|
+
|
262
272
|
# Is this connection alive and ready for queries?
|
263
273
|
def active?
|
264
274
|
@lock.synchronize do
|
@@ -302,6 +312,7 @@ module ActiveRecord
|
|
302
312
|
end
|
303
313
|
|
304
314
|
def discard! # :nodoc:
|
315
|
+
super
|
305
316
|
@connection.socket_io.reopen(IO::NULL) rescue nil
|
306
317
|
@connection = nil
|
307
318
|
end
|
@@ -354,6 +365,10 @@ module ActiveRecord
|
|
354
365
|
@has_pg_hint_plan
|
355
366
|
end
|
356
367
|
|
368
|
+
def supports_common_table_expressions?
|
369
|
+
true
|
370
|
+
end
|
371
|
+
|
357
372
|
def supports_lazy_transactions?
|
358
373
|
true
|
359
374
|
end
|
@@ -452,7 +467,6 @@ module ActiveRecord
|
|
452
467
|
end
|
453
468
|
|
454
469
|
private
|
455
|
-
|
456
470
|
# See https://www.postgresql.org/docs/current/static/errcodes-appendix.html
|
457
471
|
VALUE_LIMIT_VIOLATION = "22001"
|
458
472
|
NUMERIC_VALUE_OUT_OF_RANGE = "22003"
|
@@ -619,7 +633,7 @@ module ActiveRecord
|
|
619
633
|
SQL
|
620
634
|
|
621
635
|
if oids
|
622
|
-
query += "WHERE t.oid
|
636
|
+
query += "WHERE t.oid IN (%s)" % oids.join(", ")
|
623
637
|
else
|
624
638
|
query += initializer.query_conditions_for_initial_load
|
625
639
|
end
|
@@ -4,7 +4,9 @@ module ActiveRecord
|
|
4
4
|
module ConnectionAdapters
|
5
5
|
module SQLite3
|
6
6
|
module DatabaseStatements
|
7
|
-
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
|
7
|
+
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
|
8
|
+
:begin, :commit, :explain, :select, :pragma, :release, :savepoint, :rollback, :with
|
9
|
+
) # :nodoc:
|
8
10
|
private_constant :READ_QUERY
|
9
11
|
|
10
12
|
def write_query?(sql) # :nodoc:
|
@@ -81,7 +83,9 @@ module ActiveRecord
|
|
81
83
|
|
82
84
|
|
83
85
|
private
|
84
|
-
def execute_batch(
|
86
|
+
def execute_batch(statements, name = nil)
|
87
|
+
sql = combine_multi_statements(statements)
|
88
|
+
|
85
89
|
if preventing_writes? && write_query?(sql)
|
86
90
|
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
87
91
|
end
|
@@ -106,11 +110,8 @@ module ActiveRecord
|
|
106
110
|
end.compact
|
107
111
|
end
|
108
112
|
|
109
|
-
def
|
110
|
-
|
111
|
-
"DELETE FROM #{quote_table_name(table_name)}"
|
112
|
-
end
|
113
|
-
combine_multi_statements(truncate_tables)
|
113
|
+
def build_truncate_statement(table_name)
|
114
|
+
"DELETE FROM #{quote_table_name(table_name)}"
|
114
115
|
end
|
115
116
|
end
|
116
117
|
end
|
@@ -13,11 +13,11 @@ module ActiveRecord
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def quote_table_name(name)
|
16
|
-
|
16
|
+
self.class.quoted_table_names[name] ||= super.gsub(".", "\".\"").freeze
|
17
17
|
end
|
18
18
|
|
19
19
|
def quote_column_name(name)
|
20
|
-
|
20
|
+
self.class.quoted_column_names[name] ||= %Q("#{super.gsub('"', '""')}")
|
21
21
|
end
|
22
22
|
|
23
23
|
def quoted_time(value)
|
@@ -45,8 +45,43 @@ module ActiveRecord
|
|
45
45
|
0
|
46
46
|
end
|
47
47
|
|
48
|
-
|
48
|
+
def column_name_matcher
|
49
|
+
COLUMN_NAME
|
50
|
+
end
|
51
|
+
|
52
|
+
def column_name_with_order_matcher
|
53
|
+
COLUMN_NAME_WITH_ORDER
|
54
|
+
end
|
49
55
|
|
56
|
+
COLUMN_NAME = /
|
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+AS\s+(?:\w+|"\w+"))?
|
64
|
+
)
|
65
|
+
(?:\s*,\s*\g<1>)*
|
66
|
+
\z
|
67
|
+
/ix
|
68
|
+
|
69
|
+
COLUMN_NAME_WITH_ORDER = /
|
70
|
+
\A
|
71
|
+
(
|
72
|
+
(?:
|
73
|
+
# "table_name"."column_name" | function(one or no argument)
|
74
|
+
((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")) | \w+\((?:|\g<2>)\)
|
75
|
+
)
|
76
|
+
(?:\s+ASC|\s+DESC)?
|
77
|
+
)
|
78
|
+
(?:\s*,\s*\g<1>)*
|
79
|
+
\z
|
80
|
+
/ix
|
81
|
+
|
82
|
+
private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
|
83
|
+
|
84
|
+
private
|
50
85
|
def _type_cast(value)
|
51
86
|
case value
|
52
87
|
when BigDecimal
|
@@ -55,7 +55,7 @@ module ActiveRecord
|
|
55
55
|
def add_foreign_key(from_table, to_table, **options)
|
56
56
|
alter_table(from_table) do |definition|
|
57
57
|
to_table = strip_table_name_prefix_and_suffix(to_table)
|
58
|
-
definition.foreign_key(to_table, options)
|
58
|
+
definition.foreign_key(to_table, **options)
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
@@ -87,8 +87,8 @@ module ActiveRecord
|
|
87
87
|
SQLite3::SchemaCreation.new(self)
|
88
88
|
end
|
89
89
|
|
90
|
-
def create_table_definition(*args)
|
91
|
-
SQLite3::TableDefinition.new(self, *args)
|
90
|
+
def create_table_definition(*args, **options)
|
91
|
+
SQLite3::TableDefinition.new(self, *args, **options)
|
92
92
|
end
|
93
93
|
|
94
94
|
def new_column_from_field(table_name, field)
|
@@ -98,6 +98,16 @@ module ActiveRecord
|
|
98
98
|
configure_connection
|
99
99
|
end
|
100
100
|
|
101
|
+
def self.database_exists?(config)
|
102
|
+
config = config.symbolize_keys
|
103
|
+
if config[:database] == ":memory:"
|
104
|
+
true
|
105
|
+
else
|
106
|
+
database_file = defined?(Rails.root) ? File.expand_path(config[:database], Rails.root) : config[:database]
|
107
|
+
File.exist?(database_file)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
101
111
|
def supports_ddl_transactions?
|
102
112
|
true
|
103
113
|
end
|
@@ -134,6 +144,10 @@ module ActiveRecord
|
|
134
144
|
true
|
135
145
|
end
|
136
146
|
|
147
|
+
def supports_common_table_expressions?
|
148
|
+
database_version >= "3.8.3"
|
149
|
+
end
|
150
|
+
|
137
151
|
def supports_insert_on_conflict?
|
138
152
|
database_version >= "3.24.0"
|
139
153
|
end
|
@@ -230,17 +244,17 @@ module ActiveRecord
|
|
230
244
|
rename_table_indexes(table_name, new_name)
|
231
245
|
end
|
232
246
|
|
233
|
-
def add_column(table_name, column_name, type, options
|
247
|
+
def add_column(table_name, column_name, type, **options) #:nodoc:
|
234
248
|
if invalid_alter_table_type?(type, options)
|
235
249
|
alter_table(table_name) do |definition|
|
236
|
-
definition.column(column_name, type, options)
|
250
|
+
definition.column(column_name, type, **options)
|
237
251
|
end
|
238
252
|
else
|
239
253
|
super
|
240
254
|
end
|
241
255
|
end
|
242
256
|
|
243
|
-
def remove_column(table_name, column_name, type = nil, options
|
257
|
+
def remove_column(table_name, column_name, type = nil, **options) #:nodoc:
|
244
258
|
alter_table(table_name) do |definition|
|
245
259
|
definition.remove_column column_name
|
246
260
|
definition.foreign_keys.delete_if do |_, fk_options|
|
@@ -349,7 +363,8 @@ module ActiveRecord
|
|
349
363
|
# See: https://www.sqlite.org/lang_altertable.html
|
350
364
|
# SQLite has an additional restriction on the ALTER TABLE statement
|
351
365
|
def invalid_alter_table_type?(type, options)
|
352
|
-
type.to_sym == :primary_key || options[:primary_key]
|
366
|
+
type.to_sym == :primary_key || options[:primary_key] ||
|
367
|
+
options[:null] == false && options[:default].nil?
|
353
368
|
end
|
354
369
|
|
355
370
|
def alter_table(table_name, foreign_keys = foreign_keys(table_name), **options)
|
@@ -362,7 +377,7 @@ module ActiveRecord
|
|
362
377
|
fk.options[:column] = column
|
363
378
|
end
|
364
379
|
to_table = strip_table_name_prefix_and_suffix(fk.to_table)
|
365
|
-
definition.foreign_key(to_table, fk.options)
|
380
|
+
definition.foreign_key(to_table, **fk.options)
|
366
381
|
end
|
367
382
|
|
368
383
|
yield definition if block_given?
|
@@ -384,7 +399,7 @@ module ActiveRecord
|
|
384
399
|
def copy_table(from, to, options = {})
|
385
400
|
from_primary_key = primary_key(from)
|
386
401
|
options[:id] = false
|
387
|
-
create_table(to, options) do |definition|
|
402
|
+
create_table(to, **options) do |definition|
|
388
403
|
@definition = definition
|
389
404
|
if from_primary_key.is_a?(Array)
|
390
405
|
@definition.primary_keys from_primary_key
|
@@ -485,9 +500,9 @@ module ActiveRecord
|
|
485
500
|
result = exec_query(sql, "SCHEMA").first
|
486
501
|
|
487
502
|
if result
|
488
|
-
# Splitting with left parentheses and
|
503
|
+
# Splitting with left parentheses and discarding the first part will return all
|
489
504
|
# columns separated with comma(,).
|
490
|
-
columns_string = result["sql"].split("(").last
|
505
|
+
columns_string = result["sql"].split("(", 2).last
|
491
506
|
|
492
507
|
columns_string.split(",").each do |column_string|
|
493
508
|
# This regex will match the column name and collation type and will save
|
@@ -96,25 +96,11 @@ module ActiveRecord
|
|
96
96
|
# # raises exception due to non-existent role
|
97
97
|
# end
|
98
98
|
#
|
99
|
-
#
|
100
|
-
# you can use +connected_to+ with a +database+ argument. The +database+ argument
|
101
|
-
# expects a symbol that corresponds to the database key in your config.
|
99
|
+
# The `database` kwarg is deprecated in 6.1 and will be removed in 6.2
|
102
100
|
#
|
103
|
-
#
|
104
|
-
#
|
105
|
-
|
106
|
-
#
|
107
|
-
# This will connect to a new database for the queries inside the block. By
|
108
|
-
# default the `:writing` role will be used since all connections must be assigned
|
109
|
-
# a role. If you would like to use a different role you can pass a hash to database:
|
110
|
-
#
|
111
|
-
# ActiveRecord::Base.connected_to(database: { readonly_slow: :animals_slow_replica }) do
|
112
|
-
# # runs a long query while connected to the +animals_slow_replica+ using the readonly_slow role.
|
113
|
-
# Dog.run_a_long_query
|
114
|
-
# end
|
115
|
-
#
|
116
|
-
# When using the database key a new connection will be established every time.
|
117
|
-
def connected_to(database: nil, role: nil, &blk)
|
101
|
+
# It is not recommended for use as it re-establishes a connection every
|
102
|
+
# time it is called.
|
103
|
+
def connected_to(database: nil, role: nil, prevent_writes: false, &blk)
|
118
104
|
if database && role
|
119
105
|
raise ArgumentError, "connected_to can only accept a `database` or a `role` argument, but not both arguments."
|
120
106
|
elsif database
|
@@ -130,7 +116,11 @@ module ActiveRecord
|
|
130
116
|
|
131
117
|
with_handler(role, &blk)
|
132
118
|
elsif role
|
133
|
-
|
119
|
+
prevent_writes = true if role == reading_role
|
120
|
+
|
121
|
+
with_handler(role.to_sym) do
|
122
|
+
connection_handler.while_preventing_writes(prevent_writes, &blk)
|
123
|
+
end
|
134
124
|
else
|
135
125
|
raise ArgumentError, "must provide a `database` or a `role`."
|
136
126
|
end
|
@@ -173,7 +163,7 @@ module ActiveRecord
|
|
173
163
|
raise "Anonymous class is not allowed." unless name
|
174
164
|
|
175
165
|
config_or_env ||= DEFAULT_ENV.call.to_sym
|
176
|
-
pool_name =
|
166
|
+
pool_name = primary_class? ? "primary" : name
|
177
167
|
self.connection_specification_name = pool_name
|
178
168
|
|
179
169
|
resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new(Base.configurations)
|
@@ -209,6 +199,10 @@ module ActiveRecord
|
|
209
199
|
@connection_specification_name
|
210
200
|
end
|
211
201
|
|
202
|
+
def primary_class? # :nodoc:
|
203
|
+
self == Base || defined?(ApplicationRecord) && self == ApplicationRecord
|
204
|
+
end
|
205
|
+
|
212
206
|
# Returns the configuration of the associated connection as a hash:
|
213
207
|
#
|
214
208
|
# ActiveRecord::Base.connection_config
|
@@ -252,10 +246,11 @@ module ActiveRecord
|
|
252
246
|
:clear_all_connections!, :flush_idle_connections!, to: :connection_handler
|
253
247
|
|
254
248
|
private
|
255
|
-
|
256
249
|
def swap_connection_handler(handler, &blk) # :nodoc:
|
257
250
|
old_handler, ActiveRecord::Base.connection_handler = ActiveRecord::Base.connection_handler, handler
|
258
|
-
yield
|
251
|
+
return_value = yield
|
252
|
+
return_value.load if return_value.is_a? ActiveRecord::Relation
|
253
|
+
return_value
|
259
254
|
ensure
|
260
255
|
ActiveRecord::Base.connection_handler = old_handler
|
261
256
|
end
|