activerecord 7.2.2.1 → 8.1.2
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/CHANGELOG.md +564 -753
- data/README.rdoc +2 -2
- data/lib/active_record/association_relation.rb +2 -1
- data/lib/active_record/associations/alias_tracker.rb +6 -4
- data/lib/active_record/associations/association.rb +35 -11
- data/lib/active_record/associations/belongs_to_association.rb +18 -2
- data/lib/active_record/associations/builder/association.rb +23 -11
- data/lib/active_record/associations/builder/belongs_to.rb +17 -4
- data/lib/active_record/associations/builder/collection_association.rb +7 -3
- data/lib/active_record/associations/builder/has_one.rb +1 -1
- data/lib/active_record/associations/builder/singular_association.rb +33 -5
- data/lib/active_record/associations/collection_association.rb +10 -8
- data/lib/active_record/associations/collection_proxy.rb +22 -4
- data/lib/active_record/associations/deprecation.rb +88 -0
- data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
- data/lib/active_record/associations/errors.rb +3 -0
- data/lib/active_record/associations/has_many_through_association.rb +3 -2
- data/lib/active_record/associations/join_dependency/join_association.rb +25 -27
- data/lib/active_record/associations/join_dependency.rb +4 -2
- data/lib/active_record/associations/preloader/association.rb +2 -2
- data/lib/active_record/associations/preloader/batch.rb +7 -1
- data/lib/active_record/associations/preloader/branch.rb +1 -0
- data/lib/active_record/associations/singular_association.rb +8 -3
- data/lib/active_record/associations.rb +192 -24
- data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
- data/lib/active_record/attribute_methods/primary_key.rb +4 -8
- data/lib/active_record/attribute_methods/query.rb +34 -0
- data/lib/active_record/attribute_methods/serialization.rb +17 -4
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -14
- data/lib/active_record/attribute_methods.rb +24 -19
- data/lib/active_record/attributes.rb +40 -26
- data/lib/active_record/autosave_association.rb +91 -39
- data/lib/active_record/base.rb +3 -4
- data/lib/active_record/coders/json.rb +14 -5
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +35 -28
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +16 -4
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +51 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +458 -117
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +136 -74
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +44 -11
- data/lib/active_record/connection_adapters/abstract/quoting.rb +16 -25
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +11 -7
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +37 -36
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +122 -29
- data/lib/active_record/connection_adapters/abstract/transaction.rb +40 -8
- data/lib/active_record/connection_adapters/abstract_adapter.rb +175 -87
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +77 -58
- data/lib/active_record/connection_adapters/column.rb +17 -4
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -4
- data/lib/active_record/connection_adapters/mysql/quoting.rb +7 -9
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +41 -10
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +73 -46
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +89 -94
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +10 -11
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +4 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +76 -45
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +21 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +9 -17
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +28 -45
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +69 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +140 -64
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +83 -105
- data/lib/active_record/connection_adapters/schema_cache.rb +3 -5
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +90 -98
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +13 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +27 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +13 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +112 -42
- data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +38 -67
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +2 -19
- data/lib/active_record/connection_adapters.rb +1 -56
- data/lib/active_record/connection_handling.rb +37 -10
- data/lib/active_record/core.rb +61 -25
- data/lib/active_record/counter_cache.rb +34 -9
- data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -1
- data/lib/active_record/database_configurations/database_config.rb +9 -1
- data/lib/active_record/database_configurations/hash_config.rb +67 -9
- data/lib/active_record/database_configurations/url_config.rb +13 -3
- data/lib/active_record/database_configurations.rb +7 -3
- data/lib/active_record/delegated_type.rb +19 -19
- data/lib/active_record/dynamic_matchers.rb +54 -69
- data/lib/active_record/encryption/config.rb +3 -1
- data/lib/active_record/encryption/encryptable_record.rb +9 -9
- data/lib/active_record/encryption/encrypted_attribute_type.rb +12 -3
- data/lib/active_record/encryption/encryptor.rb +49 -28
- data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
- data/lib/active_record/encryption/scheme.rb +9 -2
- data/lib/active_record/enum.rb +46 -42
- data/lib/active_record/errors.rb +36 -12
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/explain_registry.rb +51 -2
- data/lib/active_record/filter_attribute_handler.rb +73 -0
- data/lib/active_record/fixture_set/table_row.rb +19 -2
- data/lib/active_record/fixtures.rb +2 -4
- data/lib/active_record/future_result.rb +13 -9
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +1 -1
- data/lib/active_record/insert_all.rb +12 -7
- data/lib/active_record/locking/optimistic.rb +8 -1
- data/lib/active_record/locking/pessimistic.rb +5 -0
- data/lib/active_record/log_subscriber.rb +3 -13
- data/lib/active_record/middleware/shard_selector.rb +34 -17
- data/lib/active_record/migration/command_recorder.rb +44 -11
- data/lib/active_record/migration/compatibility.rb +37 -24
- data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
- data/lib/active_record/migration.rb +50 -43
- data/lib/active_record/model_schema.rb +38 -13
- data/lib/active_record/nested_attributes.rb +6 -6
- data/lib/active_record/persistence.rb +162 -133
- data/lib/active_record/query_cache.rb +22 -15
- data/lib/active_record/query_logs.rb +104 -52
- data/lib/active_record/query_logs_formatter.rb +17 -28
- data/lib/active_record/querying.rb +12 -12
- data/lib/active_record/railtie.rb +37 -32
- data/lib/active_record/railties/controller_runtime.rb +11 -6
- data/lib/active_record/railties/databases.rake +26 -37
- data/lib/active_record/railties/job_checkpoints.rb +15 -0
- data/lib/active_record/railties/job_runtime.rb +10 -11
- data/lib/active_record/reflection.rb +53 -21
- data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
- data/lib/active_record/relation/batches.rb +147 -73
- data/lib/active_record/relation/calculations.rb +80 -63
- data/lib/active_record/relation/delegation.rb +25 -15
- data/lib/active_record/relation/finder_methods.rb +54 -37
- data/lib/active_record/relation/merger.rb +8 -8
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +11 -9
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +8 -8
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder.rb +22 -7
- data/lib/active_record/relation/query_attribute.rb +4 -2
- data/lib/active_record/relation/query_methods.rb +156 -95
- data/lib/active_record/relation/spawn_methods.rb +7 -7
- data/lib/active_record/relation/where_clause.rb +10 -11
- data/lib/active_record/relation.rb +122 -80
- data/lib/active_record/result.rb +109 -24
- data/lib/active_record/runtime_registry.rb +42 -58
- data/lib/active_record/sanitization.rb +9 -6
- data/lib/active_record/schema_dumper.rb +47 -22
- data/lib/active_record/schema_migration.rb +2 -1
- data/lib/active_record/scoping/named.rb +5 -2
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/secure_token.rb +3 -3
- data/lib/active_record/signed_id.rb +47 -18
- data/lib/active_record/statement_cache.rb +24 -20
- data/lib/active_record/store.rb +51 -22
- data/lib/active_record/structured_event_subscriber.rb +85 -0
- data/lib/active_record/table_metadata.rb +6 -23
- data/lib/active_record/tasks/abstract_tasks.rb +76 -0
- data/lib/active_record/tasks/database_tasks.rb +85 -85
- data/lib/active_record/tasks/mysql_database_tasks.rb +3 -42
- data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -40
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -28
- data/lib/active_record/test_databases.rb +14 -4
- data/lib/active_record/test_fixtures.rb +39 -2
- data/lib/active_record/testing/query_assertions.rb +8 -2
- data/lib/active_record/timestamp.rb +4 -2
- data/lib/active_record/token_for.rb +1 -1
- data/lib/active_record/transaction.rb +2 -5
- data/lib/active_record/transactions.rb +39 -16
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -1
- data/lib/active_record/type/internal/timezone.rb +7 -0
- data/lib/active_record/type/json.rb +15 -2
- data/lib/active_record/type/serialized.rb +11 -4
- data/lib/active_record/type/type_map.rb +1 -1
- data/lib/active_record/type_caster/connection.rb +2 -1
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/uniqueness.rb +8 -8
- data/lib/active_record.rb +85 -50
- data/lib/arel/alias_predication.rb +2 -0
- data/lib/arel/collectors/bind.rb +2 -2
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +2 -2
- data/lib/arel/crud.rb +8 -11
- data/lib/arel/delete_manager.rb +5 -0
- data/lib/arel/nodes/binary.rb +1 -1
- data/lib/arel/nodes/count.rb +2 -2
- data/lib/arel/nodes/delete_statement.rb +4 -2
- data/lib/arel/nodes/function.rb +4 -10
- data/lib/arel/nodes/named_function.rb +2 -2
- data/lib/arel/nodes/node.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +1 -1
- data/lib/arel/nodes/update_statement.rb +4 -2
- data/lib/arel/nodes.rb +0 -2
- data/lib/arel/select_manager.rb +13 -4
- data/lib/arel/table.rb +3 -7
- data/lib/arel/update_manager.rb +5 -0
- data/lib/arel/visitors/dot.rb +2 -3
- data/lib/arel/visitors/postgresql.rb +55 -0
- data/lib/arel/visitors/sqlite.rb +55 -8
- data/lib/arel/visitors/to_sql.rb +6 -22
- data/lib/arel.rb +3 -1
- data/lib/rails/generators/active_record/application_record/USAGE +1 -1
- metadata +17 -17
- data/lib/active_record/explain_subscriber.rb +0 -34
- data/lib/active_record/normalization.rb +0 -163
- data/lib/active_record/relation/record_fetch_warning.rb +0 -52
|
@@ -25,7 +25,7 @@ module ActiveRecord
|
|
|
25
25
|
#
|
|
26
26
|
# The PostgreSQL adapter works with the native C (https://github.com/ged/ruby-pg) driver.
|
|
27
27
|
#
|
|
28
|
-
# Options
|
|
28
|
+
# ==== Options
|
|
29
29
|
#
|
|
30
30
|
# * <tt>:host</tt> - Defaults to a Unix-domain socket in /tmp. On machines without Unix-domain sockets,
|
|
31
31
|
# the default is to connect to localhost.
|
|
@@ -86,7 +86,7 @@ module ActiveRecord
|
|
|
86
86
|
"-c #{name}=#{value.to_s.gsub(/[ \\]/, '\\\\\0')}" unless value == ":default" || value == :default
|
|
87
87
|
end.join(" ")
|
|
88
88
|
end
|
|
89
|
-
find_cmd_and_exec(
|
|
89
|
+
find_cmd_and_exec(ActiveRecord.database_cli[:postgresql], config.database)
|
|
90
90
|
end
|
|
91
91
|
end
|
|
92
92
|
|
|
@@ -284,6 +284,20 @@ module ActiveRecord
|
|
|
284
284
|
database_version >= 15_00_00 # >= 15.0
|
|
285
285
|
end
|
|
286
286
|
|
|
287
|
+
def supports_native_partitioning? # :nodoc:
|
|
288
|
+
database_version >= 10_00_00 # >= 10.0
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
if PG::Connection.method_defined?(:close_prepared) # pg 1.6.0 & libpq 17
|
|
292
|
+
def supports_close_prepared? # :nodoc:
|
|
293
|
+
database_version >= 17_00_00
|
|
294
|
+
end
|
|
295
|
+
else
|
|
296
|
+
def supports_close_prepared? # :nodoc:
|
|
297
|
+
false
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
|
|
287
301
|
def index_algorithms
|
|
288
302
|
{ concurrently: "CONCURRENTLY" }
|
|
289
303
|
end
|
|
@@ -305,8 +319,12 @@ module ActiveRecord
|
|
|
305
319
|
# accessed while holding the connection's lock. (And we
|
|
306
320
|
# don't need the complication of with_raw_connection because
|
|
307
321
|
# a reconnect would invalidate the entire statement pool.)
|
|
308
|
-
if conn = @connection.instance_variable_get(:@raw_connection)
|
|
309
|
-
|
|
322
|
+
if (conn = @connection.instance_variable_get(:@raw_connection)) && conn.status == PG::CONNECTION_OK
|
|
323
|
+
if @connection.supports_close_prepared?
|
|
324
|
+
conn.close_prepared key
|
|
325
|
+
else
|
|
326
|
+
conn.query "DEALLOCATE #{key}"
|
|
327
|
+
end
|
|
310
328
|
end
|
|
311
329
|
rescue PG::Error
|
|
312
330
|
end
|
|
@@ -345,6 +363,7 @@ module ActiveRecord
|
|
|
345
363
|
@lock.synchronize do
|
|
346
364
|
return false unless @raw_connection
|
|
347
365
|
@raw_connection.query ";"
|
|
366
|
+
verified!
|
|
348
367
|
end
|
|
349
368
|
true
|
|
350
369
|
rescue PG::Error
|
|
@@ -376,6 +395,11 @@ module ActiveRecord
|
|
|
376
395
|
end
|
|
377
396
|
end
|
|
378
397
|
|
|
398
|
+
def clear_cache!(new_connection: false)
|
|
399
|
+
super
|
|
400
|
+
@schema_search_path = nil if new_connection
|
|
401
|
+
end
|
|
402
|
+
|
|
379
403
|
# Disconnects from the database if already connected. Otherwise, this
|
|
380
404
|
# method does nothing.
|
|
381
405
|
def disconnect!
|
|
@@ -392,10 +416,6 @@ module ActiveRecord
|
|
|
392
416
|
@raw_connection = nil
|
|
393
417
|
end
|
|
394
418
|
|
|
395
|
-
def native_database_types # :nodoc:
|
|
396
|
-
self.class.native_database_types
|
|
397
|
-
end
|
|
398
|
-
|
|
399
419
|
def self.native_database_types # :nodoc:
|
|
400
420
|
@native_database_types ||= begin
|
|
401
421
|
types = NATIVE_DATABASE_TYPES.dup
|
|
@@ -405,7 +425,7 @@ module ActiveRecord
|
|
|
405
425
|
end
|
|
406
426
|
|
|
407
427
|
def set_standard_conforming_strings
|
|
408
|
-
internal_execute("SET standard_conforming_strings = on")
|
|
428
|
+
internal_execute("SET standard_conforming_strings = on", "SCHEMA")
|
|
409
429
|
end
|
|
410
430
|
|
|
411
431
|
def supports_ddl_transactions?
|
|
@@ -479,6 +499,7 @@ module ActiveRecord
|
|
|
479
499
|
# Set to +:cascade+ to drop dependent objects as well.
|
|
480
500
|
# Defaults to false.
|
|
481
501
|
def disable_extension(name, force: false)
|
|
502
|
+
_schema, name = name.to_s.split(".").values_at(-2, -1)
|
|
482
503
|
internal_exec_query("DROP EXTENSION IF EXISTS \"#{name}\"#{' CASCADE' if force == :cascade}").tap {
|
|
483
504
|
reload_type_map
|
|
484
505
|
}
|
|
@@ -493,7 +514,19 @@ module ActiveRecord
|
|
|
493
514
|
end
|
|
494
515
|
|
|
495
516
|
def extensions
|
|
496
|
-
|
|
517
|
+
query = <<~SQL
|
|
518
|
+
SELECT
|
|
519
|
+
pg_extension.extname,
|
|
520
|
+
n.nspname AS schema
|
|
521
|
+
FROM pg_extension
|
|
522
|
+
JOIN pg_namespace n ON pg_extension.extnamespace = n.oid
|
|
523
|
+
SQL
|
|
524
|
+
|
|
525
|
+
internal_exec_query(query, "SCHEMA", allow_retry: true, materialize_transactions: false).cast_values.map do |row|
|
|
526
|
+
name, schema = row[0], row[1]
|
|
527
|
+
schema = nil if schema == current_schema
|
|
528
|
+
[schema, name].compact.join(".")
|
|
529
|
+
end
|
|
497
530
|
end
|
|
498
531
|
|
|
499
532
|
# Returns a list of defined enum types, and their values.
|
|
@@ -503,7 +536,7 @@ module ActiveRecord
|
|
|
503
536
|
type.typname AS name,
|
|
504
537
|
type.OID AS oid,
|
|
505
538
|
n.nspname AS schema,
|
|
506
|
-
|
|
539
|
+
array_agg(enum.enumlabel ORDER BY enum.enumsortorder) AS value
|
|
507
540
|
FROM pg_enum AS enum
|
|
508
541
|
JOIN pg_type AS type ON (type.oid = enum.enumtypid)
|
|
509
542
|
JOIN pg_namespace n ON type.typnamespace = n.oid
|
|
@@ -558,30 +591,34 @@ module ActiveRecord
|
|
|
558
591
|
end
|
|
559
592
|
|
|
560
593
|
# Rename an existing enum type to something else.
|
|
561
|
-
def rename_enum(name,
|
|
562
|
-
|
|
594
|
+
def rename_enum(name, new_name = nil, **options)
|
|
595
|
+
new_name ||= options.fetch(:to) do
|
|
596
|
+
raise ArgumentError, "rename_enum requires two from/to name positional arguments."
|
|
597
|
+
end
|
|
563
598
|
|
|
564
|
-
exec_query("ALTER TYPE #{quote_table_name(name)} RENAME TO #{
|
|
599
|
+
exec_query("ALTER TYPE #{quote_table_name(name)} RENAME TO #{quote_table_name(new_name)}").tap { reload_type_map }
|
|
565
600
|
end
|
|
566
601
|
|
|
567
602
|
# Add enum value to an existing enum type.
|
|
568
|
-
def add_enum_value(type_name, value, options
|
|
603
|
+
def add_enum_value(type_name, value, **options)
|
|
569
604
|
before, after = options.values_at(:before, :after)
|
|
570
|
-
sql = +"ALTER TYPE #{quote_table_name(type_name)} ADD VALUE
|
|
605
|
+
sql = +"ALTER TYPE #{quote_table_name(type_name)} ADD VALUE"
|
|
606
|
+
sql << " IF NOT EXISTS" if options[:if_not_exists]
|
|
607
|
+
sql << " #{quote(value)}"
|
|
571
608
|
|
|
572
609
|
if before && after
|
|
573
610
|
raise ArgumentError, "Cannot have both :before and :after at the same time"
|
|
574
611
|
elsif before
|
|
575
|
-
sql << " BEFORE
|
|
612
|
+
sql << " BEFORE #{quote(before)}"
|
|
576
613
|
elsif after
|
|
577
|
-
sql << " AFTER
|
|
614
|
+
sql << " AFTER #{quote(after)}"
|
|
578
615
|
end
|
|
579
616
|
|
|
580
617
|
execute(sql).tap { reload_type_map }
|
|
581
618
|
end
|
|
582
619
|
|
|
583
620
|
# Rename enum value on an existing enum type.
|
|
584
|
-
def rename_enum_value(type_name, options
|
|
621
|
+
def rename_enum_value(type_name, **options)
|
|
585
622
|
unless database_version >= 10_00_00 # >= 10.0
|
|
586
623
|
raise ArgumentError, "Renaming enum values is only supported in PostgreSQL 10 or later"
|
|
587
624
|
end
|
|
@@ -589,12 +626,12 @@ module ActiveRecord
|
|
|
589
626
|
from = options.fetch(:from) { raise ArgumentError, ":from is required" }
|
|
590
627
|
to = options.fetch(:to) { raise ArgumentError, ":to is required" }
|
|
591
628
|
|
|
592
|
-
execute("ALTER TYPE #{quote_table_name(type_name)} RENAME VALUE
|
|
629
|
+
execute("ALTER TYPE #{quote_table_name(type_name)} RENAME VALUE #{quote(from)} TO #{quote(to)}").tap {
|
|
593
630
|
reload_type_map
|
|
594
631
|
}
|
|
595
632
|
end
|
|
596
633
|
|
|
597
|
-
# Returns the configured supported identifier length supported by PostgreSQL
|
|
634
|
+
# Returns the configured maximum supported identifier length supported by PostgreSQL
|
|
598
635
|
def max_identifier_length
|
|
599
636
|
@max_identifier_length ||= query_value("SHOW max_identifier_length", "SCHEMA").to_i
|
|
600
637
|
end
|
|
@@ -612,7 +649,11 @@ module ActiveRecord
|
|
|
612
649
|
# Returns the version of the connected PostgreSQL server.
|
|
613
650
|
def get_database_version # :nodoc:
|
|
614
651
|
with_raw_connection do |conn|
|
|
615
|
-
conn.server_version
|
|
652
|
+
version = conn.server_version
|
|
653
|
+
if version == 0
|
|
654
|
+
raise ActiveRecord::ConnectionNotEstablished, "Could not determine PostgreSQL version"
|
|
655
|
+
end
|
|
656
|
+
version
|
|
616
657
|
end
|
|
617
658
|
end
|
|
618
659
|
alias :postgresql_version :database_version
|
|
@@ -766,6 +807,8 @@ module ActiveRecord
|
|
|
766
807
|
NOT_NULL_VIOLATION = "23502"
|
|
767
808
|
FOREIGN_KEY_VIOLATION = "23503"
|
|
768
809
|
UNIQUE_VIOLATION = "23505"
|
|
810
|
+
CHECK_VIOLATION = "23514"
|
|
811
|
+
EXCLUSION_VIOLATION = "23P01"
|
|
769
812
|
SERIALIZATION_FAILURE = "40001"
|
|
770
813
|
DEADLOCK_DETECTED = "40P01"
|
|
771
814
|
DUPLICATE_DATABASE = "42P04"
|
|
@@ -797,6 +840,10 @@ module ActiveRecord
|
|
|
797
840
|
RecordNotUnique.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
|
798
841
|
when FOREIGN_KEY_VIOLATION
|
|
799
842
|
InvalidForeignKey.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
|
843
|
+
when CHECK_VIOLATION
|
|
844
|
+
CheckViolation.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
|
845
|
+
when EXCLUSION_VIOLATION
|
|
846
|
+
ExclusionViolation.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
|
800
847
|
when VALUE_LIMIT_VIOLATION
|
|
801
848
|
ValueTooLong.new(message, sql: sql, binds: binds, connection_pool: @pool)
|
|
802
849
|
when NUMERIC_VALUE_OUT_OF_RANGE
|
|
@@ -841,9 +888,8 @@ module ActiveRecord
|
|
|
841
888
|
def load_additional_types(oids = nil)
|
|
842
889
|
initializer = OID::TypeMapInitializer.new(type_map)
|
|
843
890
|
load_types_queries(initializer, oids) do |query|
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
end
|
|
891
|
+
records = internal_execute(query, "SCHEMA", [], allow_retry: true, materialize_transactions: false)
|
|
892
|
+
initializer.run(records)
|
|
847
893
|
end
|
|
848
894
|
end
|
|
849
895
|
|
|
@@ -864,73 +910,6 @@ module ActiveRecord
|
|
|
864
910
|
|
|
865
911
|
FEATURE_NOT_SUPPORTED = "0A000" # :nodoc:
|
|
866
912
|
|
|
867
|
-
def execute_and_clear(sql, name, binds, prepare: false, async: false, allow_retry: false, materialize_transactions: true)
|
|
868
|
-
sql = transform_query(sql)
|
|
869
|
-
check_if_write_query(sql)
|
|
870
|
-
|
|
871
|
-
if !prepare || without_prepared_statement?(binds)
|
|
872
|
-
result = exec_no_cache(sql, name, binds, async: async, allow_retry: allow_retry, materialize_transactions: materialize_transactions)
|
|
873
|
-
else
|
|
874
|
-
result = exec_cache(sql, name, binds, async: async, allow_retry: allow_retry, materialize_transactions: materialize_transactions)
|
|
875
|
-
end
|
|
876
|
-
begin
|
|
877
|
-
ret = yield result
|
|
878
|
-
ensure
|
|
879
|
-
result.clear
|
|
880
|
-
end
|
|
881
|
-
ret
|
|
882
|
-
end
|
|
883
|
-
|
|
884
|
-
def exec_no_cache(sql, name, binds, async:, allow_retry:, materialize_transactions:)
|
|
885
|
-
mark_transaction_written_if_write(sql)
|
|
886
|
-
|
|
887
|
-
# make sure we carry over any changes to ActiveRecord.default_timezone that have been
|
|
888
|
-
# made since we established the connection
|
|
889
|
-
update_typemap_for_default_timezone
|
|
890
|
-
|
|
891
|
-
type_casted_binds = type_casted_binds(binds)
|
|
892
|
-
log(sql, name, binds, type_casted_binds, async: async) do |notification_payload|
|
|
893
|
-
with_raw_connection(allow_retry: allow_retry, materialize_transactions: materialize_transactions) do |conn|
|
|
894
|
-
result = conn.exec_params(sql, type_casted_binds)
|
|
895
|
-
verified!
|
|
896
|
-
notification_payload[:row_count] = result.count
|
|
897
|
-
result
|
|
898
|
-
end
|
|
899
|
-
end
|
|
900
|
-
end
|
|
901
|
-
|
|
902
|
-
def exec_cache(sql, name, binds, async:, allow_retry:, materialize_transactions:)
|
|
903
|
-
mark_transaction_written_if_write(sql)
|
|
904
|
-
|
|
905
|
-
update_typemap_for_default_timezone
|
|
906
|
-
|
|
907
|
-
with_raw_connection(allow_retry: allow_retry, materialize_transactions: materialize_transactions) do |conn|
|
|
908
|
-
stmt_key = prepare_statement(sql, binds, conn)
|
|
909
|
-
type_casted_binds = type_casted_binds(binds)
|
|
910
|
-
|
|
911
|
-
log(sql, name, binds, type_casted_binds, stmt_key, async: async) do |notification_payload|
|
|
912
|
-
result = conn.exec_prepared(stmt_key, type_casted_binds)
|
|
913
|
-
verified!
|
|
914
|
-
notification_payload[:row_count] = result.count
|
|
915
|
-
result
|
|
916
|
-
end
|
|
917
|
-
end
|
|
918
|
-
rescue ActiveRecord::StatementInvalid => e
|
|
919
|
-
raise unless is_cached_plan_failure?(e)
|
|
920
|
-
|
|
921
|
-
# Nothing we can do if we are in a transaction because all commands
|
|
922
|
-
# will raise InFailedSQLTransaction
|
|
923
|
-
if in_transaction?
|
|
924
|
-
raise ActiveRecord::PreparedStatementCacheExpired.new(e.cause.message, connection_pool: @pool)
|
|
925
|
-
else
|
|
926
|
-
@lock.synchronize do
|
|
927
|
-
# outside of transactions we can simply flush this query and retry
|
|
928
|
-
@statements.delete sql_key(sql)
|
|
929
|
-
end
|
|
930
|
-
retry
|
|
931
|
-
end
|
|
932
|
-
end
|
|
933
|
-
|
|
934
913
|
# Annoyingly, the code for prepared statements whose return value may
|
|
935
914
|
# have changed is FEATURE_NOT_SUPPORTED.
|
|
936
915
|
#
|
|
@@ -940,8 +919,7 @@ module ActiveRecord
|
|
|
940
919
|
#
|
|
941
920
|
# Check here for more details:
|
|
942
921
|
# https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/cache/plancache.c#l573
|
|
943
|
-
def is_cached_plan_failure?(
|
|
944
|
-
pgerror = e.cause
|
|
922
|
+
def is_cached_plan_failure?(pgerror)
|
|
945
923
|
pgerror.result.result_error_field(PG::PG_DIAG_SQLSTATE) == FEATURE_NOT_SUPPORTED &&
|
|
946
924
|
pgerror.result.result_error_field(PG::PG_DIAG_SOURCE_FUNCTION) == "RevalidateCachedQuery"
|
|
947
925
|
rescue
|
|
@@ -1020,22 +998,24 @@ module ActiveRecord
|
|
|
1020
998
|
variables = @config.fetch(:variables, {}).stringify_keys
|
|
1021
999
|
|
|
1022
1000
|
# Set interval output format to ISO 8601 for ease of parsing by ActiveSupport::Duration.parse
|
|
1023
|
-
internal_execute("SET intervalstyle = iso_8601")
|
|
1001
|
+
internal_execute("SET intervalstyle = iso_8601", "SCHEMA")
|
|
1024
1002
|
|
|
1025
1003
|
# SET statements from :variables config hash
|
|
1026
1004
|
# https://www.postgresql.org/docs/current/static/sql-set.html
|
|
1027
1005
|
variables.map do |k, v|
|
|
1028
1006
|
if v == ":default" || v == :default
|
|
1029
1007
|
# Sets the value to the global or compile default
|
|
1030
|
-
internal_execute("SET SESSION #{k} TO DEFAULT")
|
|
1008
|
+
internal_execute("SET SESSION #{k} TO DEFAULT", "SCHEMA")
|
|
1031
1009
|
elsif !v.nil?
|
|
1032
|
-
internal_execute("SET SESSION #{k} TO #{quote(v)}")
|
|
1010
|
+
internal_execute("SET SESSION #{k} TO #{quote(v)}", "SCHEMA")
|
|
1033
1011
|
end
|
|
1034
1012
|
end
|
|
1035
1013
|
|
|
1036
1014
|
add_pg_encoders
|
|
1037
1015
|
add_pg_decoders
|
|
1038
1016
|
|
|
1017
|
+
schema_search_path # populate cache
|
|
1018
|
+
|
|
1039
1019
|
reload_type_map
|
|
1040
1020
|
end
|
|
1041
1021
|
|
|
@@ -1050,9 +1030,9 @@ module ActiveRecord
|
|
|
1050
1030
|
# If using Active Record's time zone support configure the connection
|
|
1051
1031
|
# to return TIMESTAMP WITH ZONE types in UTC.
|
|
1052
1032
|
if default_timezone == :utc
|
|
1053
|
-
|
|
1033
|
+
raw_execute("SET SESSION timezone TO 'UTC'", "SCHEMA")
|
|
1054
1034
|
else
|
|
1055
|
-
|
|
1035
|
+
raw_execute("SET SESSION timezone TO DEFAULT", "SCHEMA")
|
|
1056
1036
|
end
|
|
1057
1037
|
end
|
|
1058
1038
|
|
|
@@ -1119,9 +1099,8 @@ module ActiveRecord
|
|
|
1119
1099
|
AND castsource = #{quote column.sql_type}::regtype
|
|
1120
1100
|
)
|
|
1121
1101
|
SQL
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
end
|
|
1102
|
+
result = internal_execute(sql, "SCHEMA", [], allow_retry: true, materialize_transactions: false)
|
|
1103
|
+
result.getvalue(0, 0)
|
|
1125
1104
|
end
|
|
1126
1105
|
end
|
|
1127
1106
|
end
|
|
@@ -1177,9 +1156,8 @@ module ActiveRecord
|
|
|
1177
1156
|
FROM pg_type as t
|
|
1178
1157
|
WHERE t.typname IN (%s)
|
|
1179
1158
|
SQL
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
end
|
|
1159
|
+
result = internal_execute(query, "SCHEMA", [], allow_retry: true, materialize_transactions: false)
|
|
1160
|
+
coders = result.filter_map { |row| construct_coder(row, coders_by_name[row["typname"]]) }
|
|
1183
1161
|
|
|
1184
1162
|
map = PG::TypeMapByOid.new
|
|
1185
1163
|
coders.each { |coder| map.add_coder(coder) }
|
|
@@ -271,10 +271,10 @@ module ActiveRecord
|
|
|
271
271
|
end
|
|
272
272
|
|
|
273
273
|
def encode_with(coder) # :nodoc:
|
|
274
|
-
coder["columns"] = @columns.sort.to_h
|
|
274
|
+
coder["columns"] = @columns.sort.to_h.transform_values { _1.sort_by(&:name) }
|
|
275
275
|
coder["primary_keys"] = @primary_keys.sort.to_h
|
|
276
276
|
coder["data_sources"] = @data_sources.sort.to_h
|
|
277
|
-
coder["indexes"] = @indexes.sort.to_h
|
|
277
|
+
coder["indexes"] = @indexes.sort.to_h.transform_values { _1.sort_by(&:name) }
|
|
278
278
|
coder["version"] = @version
|
|
279
279
|
end
|
|
280
280
|
|
|
@@ -434,9 +434,7 @@ module ActiveRecord
|
|
|
434
434
|
end
|
|
435
435
|
|
|
436
436
|
def ignored_table?(table_name)
|
|
437
|
-
ActiveRecord.
|
|
438
|
-
ignored === table_name
|
|
439
|
-
end
|
|
437
|
+
ActiveRecord.schema_cache_ignored_table?(table_name)
|
|
440
438
|
end
|
|
441
439
|
|
|
442
440
|
def derive_columns_hash_and_deduplicate_values
|
|
@@ -21,87 +21,24 @@ module ActiveRecord
|
|
|
21
21
|
SQLite3::ExplainPrettyPrinter.new.pp(result)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
def
|
|
25
|
-
|
|
26
|
-
check_if_write_query(sql)
|
|
27
|
-
|
|
28
|
-
mark_transaction_written_if_write(sql)
|
|
29
|
-
|
|
30
|
-
type_casted_binds = type_casted_binds(binds)
|
|
31
|
-
|
|
32
|
-
log(sql, name, binds, type_casted_binds, async: async) do |notification_payload|
|
|
33
|
-
with_raw_connection do |conn|
|
|
34
|
-
# Don't cache statements if they are not prepared
|
|
35
|
-
unless prepare
|
|
36
|
-
stmt = conn.prepare(sql)
|
|
37
|
-
begin
|
|
38
|
-
cols = stmt.columns
|
|
39
|
-
unless without_prepared_statement?(binds)
|
|
40
|
-
stmt.bind_params(type_casted_binds)
|
|
41
|
-
end
|
|
42
|
-
records = stmt.to_a
|
|
43
|
-
ensure
|
|
44
|
-
stmt.close
|
|
45
|
-
end
|
|
46
|
-
else
|
|
47
|
-
stmt = @statements[sql] ||= conn.prepare(sql)
|
|
48
|
-
cols = stmt.columns
|
|
49
|
-
stmt.reset!
|
|
50
|
-
stmt.bind_params(type_casted_binds)
|
|
51
|
-
records = stmt.to_a
|
|
52
|
-
end
|
|
53
|
-
verified!
|
|
54
|
-
|
|
55
|
-
result = build_result(columns: cols, rows: records)
|
|
56
|
-
notification_payload[:row_count] = result.length
|
|
57
|
-
result
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def exec_delete(sql, name = "SQL", binds = []) # :nodoc:
|
|
63
|
-
internal_exec_query(sql, name, binds)
|
|
64
|
-
@raw_connection.changes
|
|
24
|
+
def begin_deferred_transaction(isolation = nil) # :nodoc:
|
|
25
|
+
internal_begin_transaction(:deferred, isolation)
|
|
65
26
|
end
|
|
66
|
-
alias :exec_update :exec_delete
|
|
67
27
|
|
|
68
28
|
def begin_isolated_db_transaction(isolation) # :nodoc:
|
|
69
|
-
|
|
70
|
-
raise StandardError, "You need to enable the shared-cache mode in SQLite mode before attempting to change the transaction isolation level" unless shared_cache?
|
|
71
|
-
|
|
72
|
-
with_raw_connection(allow_retry: true, materialize_transactions: false) do |conn|
|
|
73
|
-
ActiveSupport::IsolatedExecutionState[:active_record_read_uncommitted] = conn.get_first_value("PRAGMA read_uncommitted")
|
|
74
|
-
conn.read_uncommitted = true
|
|
75
|
-
begin_db_transaction
|
|
76
|
-
end
|
|
29
|
+
internal_begin_transaction(:deferred, isolation)
|
|
77
30
|
end
|
|
78
31
|
|
|
79
32
|
def begin_db_transaction # :nodoc:
|
|
80
|
-
|
|
81
|
-
with_raw_connection(allow_retry: true, materialize_transactions: false) do |conn|
|
|
82
|
-
result = conn.transaction
|
|
83
|
-
verified!
|
|
84
|
-
result
|
|
85
|
-
end
|
|
86
|
-
end
|
|
33
|
+
internal_begin_transaction(:immediate, nil)
|
|
87
34
|
end
|
|
88
35
|
|
|
89
36
|
def commit_db_transaction # :nodoc:
|
|
90
|
-
|
|
91
|
-
with_raw_connection(allow_retry: true, materialize_transactions: false) do |conn|
|
|
92
|
-
conn.commit
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
reset_read_uncommitted
|
|
37
|
+
internal_execute("COMMIT TRANSACTION", "TRANSACTION", allow_retry: true, materialize_transactions: false)
|
|
96
38
|
end
|
|
97
39
|
|
|
98
40
|
def exec_rollback_db_transaction # :nodoc:
|
|
99
|
-
|
|
100
|
-
with_raw_connection(allow_retry: true, materialize_transactions: false) do |conn|
|
|
101
|
-
conn.rollback
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
reset_read_uncommitted
|
|
41
|
+
internal_execute("ROLLBACK TRANSACTION", "TRANSACTION", allow_retry: true, materialize_transactions: false)
|
|
105
42
|
end
|
|
106
43
|
|
|
107
44
|
# https://stackoverflow.com/questions/17574784
|
|
@@ -113,47 +50,102 @@ module ActiveRecord
|
|
|
113
50
|
HIGH_PRECISION_CURRENT_TIMESTAMP
|
|
114
51
|
end
|
|
115
52
|
|
|
53
|
+
def execute(...) # :nodoc:
|
|
54
|
+
# SQLite3Adapter was refactored to use ActiveRecord::Result internally
|
|
55
|
+
# but for backward compatibility we have to keep returning arrays of hashes here
|
|
56
|
+
super&.to_a
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def reset_isolation_level # :nodoc:
|
|
60
|
+
internal_execute("PRAGMA read_uncommitted=#{@previous_read_uncommitted}", "TRANSACTION", allow_retry: true, materialize_transactions: false)
|
|
61
|
+
@previous_read_uncommitted = nil
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def default_insert_value(column) # :nodoc:
|
|
65
|
+
if column.default_function
|
|
66
|
+
Arel.sql(column.default_function)
|
|
67
|
+
else
|
|
68
|
+
column.default
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
116
72
|
private
|
|
117
|
-
def
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
73
|
+
def internal_begin_transaction(mode, isolation)
|
|
74
|
+
if isolation
|
|
75
|
+
raise TransactionIsolationError, "SQLite3 only supports the `read_uncommitted` transaction isolation level" if isolation != :read_uncommitted
|
|
76
|
+
raise StandardError, "You need to enable the shared-cache mode in SQLite mode before attempting to change the transaction isolation level" unless shared_cache?
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
internal_execute("BEGIN #{mode} TRANSACTION", "TRANSACTION", allow_retry: true, materialize_transactions: false)
|
|
80
|
+
if isolation
|
|
81
|
+
@previous_read_uncommitted = query_value("PRAGMA read_uncommitted")
|
|
82
|
+
internal_execute("PRAGMA read_uncommitted=ON", "TRANSACTION", allow_retry: true, materialize_transactions: false)
|
|
125
83
|
end
|
|
126
84
|
end
|
|
127
85
|
|
|
128
|
-
def
|
|
129
|
-
|
|
130
|
-
|
|
86
|
+
def perform_query(raw_connection, sql, binds, type_casted_binds, prepare:, notification_payload:, batch: false)
|
|
87
|
+
total_changes_before_query = raw_connection.total_changes
|
|
88
|
+
affected_rows = nil
|
|
131
89
|
|
|
132
|
-
|
|
133
|
-
|
|
90
|
+
if batch
|
|
91
|
+
raw_connection.execute_batch2(sql)
|
|
92
|
+
else
|
|
93
|
+
stmt = if prepare
|
|
94
|
+
@statements[sql] ||= raw_connection.prepare(sql)
|
|
95
|
+
@statements[sql].reset!
|
|
96
|
+
else
|
|
97
|
+
# Don't cache statements if they are not prepared.
|
|
98
|
+
raw_connection.prepare(sql)
|
|
99
|
+
end
|
|
100
|
+
begin
|
|
101
|
+
unless binds.nil? || binds.empty?
|
|
102
|
+
stmt.bind_params(type_casted_binds)
|
|
103
|
+
end
|
|
104
|
+
result = if stmt.column_count.zero? # No return
|
|
105
|
+
stmt.step
|
|
134
106
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
107
|
+
affected_rows = if raw_connection.total_changes > total_changes_before_query
|
|
108
|
+
raw_connection.changes
|
|
109
|
+
else
|
|
110
|
+
0
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
ActiveRecord::Result.empty(affected_rows: affected_rows)
|
|
114
|
+
else
|
|
115
|
+
rows = stmt.to_a
|
|
138
116
|
|
|
139
|
-
|
|
140
|
-
|
|
117
|
+
affected_rows = if raw_connection.total_changes > total_changes_before_query
|
|
118
|
+
raw_connection.changes
|
|
119
|
+
else
|
|
120
|
+
0
|
|
121
|
+
end
|
|
141
122
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
notification_payload[:row_count] = result.length
|
|
147
|
-
result
|
|
123
|
+
ActiveRecord::Result.new(stmt.columns, rows, stmt.types.map { |t| type_map.lookup(t) }, affected_rows: affected_rows)
|
|
124
|
+
end
|
|
125
|
+
ensure
|
|
126
|
+
stmt.close unless prepare
|
|
148
127
|
end
|
|
149
128
|
end
|
|
129
|
+
verified!
|
|
130
|
+
|
|
131
|
+
notification_payload[:affected_rows] = affected_rows
|
|
132
|
+
notification_payload[:row_count] = result&.length || 0
|
|
133
|
+
result
|
|
150
134
|
end
|
|
151
135
|
|
|
152
|
-
def
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
136
|
+
def cast_result(result)
|
|
137
|
+
# Given that SQLite3 doesn't have a Result type, raw_execute already returns an ActiveRecord::Result
|
|
138
|
+
# so we have nothing to cast here.
|
|
139
|
+
result
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def affected_rows(result)
|
|
143
|
+
result.affected_rows
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def execute_batch(statements, name = nil, **kwargs)
|
|
147
|
+
sql = combine_multi_statements(statements)
|
|
148
|
+
raw_execute(sql, name, batch: true, **kwargs)
|
|
157
149
|
end
|
|
158
150
|
|
|
159
151
|
def build_truncate_statement(table_name)
|
|
@@ -50,6 +50,19 @@ module ActiveRecord
|
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
+
def quote(value) # :nodoc:
|
|
54
|
+
case value
|
|
55
|
+
when Numeric
|
|
56
|
+
if value.finite?
|
|
57
|
+
super
|
|
58
|
+
else
|
|
59
|
+
"'#{value}'"
|
|
60
|
+
end
|
|
61
|
+
else
|
|
62
|
+
super
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
53
66
|
def quote_string(s)
|
|
54
67
|
::SQLite3::Database.quote(s)
|
|
55
68
|
end
|
|
@@ -67,18 +80,10 @@ module ActiveRecord
|
|
|
67
80
|
"x'#{value.hex}'"
|
|
68
81
|
end
|
|
69
82
|
|
|
70
|
-
def quoted_true
|
|
71
|
-
"1"
|
|
72
|
-
end
|
|
73
|
-
|
|
74
83
|
def unquoted_true
|
|
75
84
|
1
|
|
76
85
|
end
|
|
77
86
|
|
|
78
|
-
def quoted_false
|
|
79
|
-
"0"
|
|
80
|
-
end
|
|
81
|
-
|
|
82
87
|
def unquoted_false
|
|
83
88
|
0
|
|
84
89
|
end
|
|
@@ -5,12 +5,6 @@ module ActiveRecord
|
|
|
5
5
|
module SQLite3
|
|
6
6
|
class SchemaCreation < SchemaCreation # :nodoc:
|
|
7
7
|
private
|
|
8
|
-
def visit_AddForeignKey(o)
|
|
9
|
-
super.dup.tap do |sql|
|
|
10
|
-
sql << " DEFERRABLE INITIALLY #{o.options[:deferrable].to_s.upcase}" if o.deferrable
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
8
|
def visit_ForeignKeyDefinition(o)
|
|
15
9
|
super.dup.tap do |sql|
|
|
16
10
|
sql << " DEFERRABLE INITIALLY #{o.deferrable.to_s.upcase}" if o.deferrable
|