activerecord 7.1.0.beta1 → 7.1.0.rc2
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 +85 -4
- data/lib/active_record/associations/collection_association.rb +1 -3
- data/lib/active_record/associations/collection_proxy.rb +1 -1
- data/lib/active_record/associations.rb +110 -110
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +20 -1
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/transaction.rb +12 -9
- data/lib/active_record/connection_adapters/abstract_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +7 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +1 -1
- data/lib/active_record/connection_adapters/pool_manager.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +0 -16
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +5 -5
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -24
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +19 -8
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +25 -29
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -6
- data/lib/active_record/connection_adapters/schema_cache.rb +2 -2
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +4 -4
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +49 -4
- data/lib/active_record/core.rb +7 -9
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +1 -1
- data/lib/active_record/errors.rb +19 -0
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/migration/command_recorder.rb +8 -8
- data/lib/active_record/nested_attributes.rb +0 -5
- data/lib/active_record/normalization.rb +2 -1
- data/lib/active_record/persistence.rb +1 -1
- data/lib/active_record/querying.rb +2 -2
- data/lib/active_record/railtie.rb +1 -1
- data/lib/active_record/reflection.rb +10 -16
- data/lib/active_record/relation/calculations.rb +8 -8
- data/lib/active_record/relation/finder_methods.rb +3 -12
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -6
- data/lib/active_record/schema_dumper.rb +9 -4
- data/lib/active_record/tasks/sqlite_database_tasks.rb +1 -0
- metadata +9 -9
@@ -16,7 +16,7 @@ module ActiveRecord
|
|
16
16
|
delegate :quote_column_name, :quote_table_name, :quote_default_expression, :type_to_sql,
|
17
17
|
:options_include_default?, :supports_indexes_in_create?, :use_foreign_keys?,
|
18
18
|
:quoted_columns_for_index, :supports_partial_index?, :supports_check_constraints?,
|
19
|
-
:supports_index_include?, :supports_exclusion_constraints?, :
|
19
|
+
:supports_index_include?, :supports_exclusion_constraints?, :supports_unique_constraints?,
|
20
20
|
:supports_nulls_not_distinct?,
|
21
21
|
to: :@conn, private: true
|
22
22
|
|
@@ -65,8 +65,8 @@ module ActiveRecord
|
|
65
65
|
statements.concat(o.exclusion_constraints.map { |exc| accept exc })
|
66
66
|
end
|
67
67
|
|
68
|
-
if
|
69
|
-
statements.concat(o.
|
68
|
+
if supports_unique_constraints?
|
69
|
+
statements.concat(o.unique_constraints.map { |exc| accept exc })
|
70
70
|
end
|
71
71
|
|
72
72
|
create_sql << "(#{statements.join(', ')})" if statements.present?
|
@@ -78,21 +78,24 @@ module ActiveRecord
|
|
78
78
|
def initialize(payload = {})
|
79
79
|
@handle = nil
|
80
80
|
@started = false
|
81
|
-
@payload =
|
81
|
+
@payload = nil
|
82
|
+
@base_payload = payload
|
82
83
|
end
|
83
84
|
|
84
85
|
def start
|
85
86
|
return if @started
|
86
87
|
@started = true
|
87
88
|
|
89
|
+
@payload = @base_payload.dup
|
88
90
|
@handle = ActiveSupport::Notifications.instrumenter.build_handle("transaction.active_record", @payload)
|
89
91
|
@handle.start
|
90
92
|
end
|
91
93
|
|
92
|
-
def finish
|
94
|
+
def finish(outcome)
|
93
95
|
return unless @started
|
94
96
|
@started = false
|
95
97
|
|
98
|
+
@payload[:outcome] = outcome
|
96
99
|
@handle.finish
|
97
100
|
end
|
98
101
|
end
|
@@ -163,7 +166,7 @@ module ActiveRecord
|
|
163
166
|
end
|
164
167
|
|
165
168
|
def incomplete!
|
166
|
-
@instrumenter.finish
|
169
|
+
@instrumenter.finish(:incomplete)
|
167
170
|
end
|
168
171
|
|
169
172
|
def materialize!
|
@@ -334,7 +337,7 @@ module ActiveRecord
|
|
334
337
|
def restart
|
335
338
|
return unless materialized?
|
336
339
|
|
337
|
-
@instrumenter.finish
|
340
|
+
@instrumenter.finish(:restart)
|
338
341
|
@instrumenter.start
|
339
342
|
|
340
343
|
connection.rollback_to_savepoint(savepoint_name)
|
@@ -345,13 +348,13 @@ module ActiveRecord
|
|
345
348
|
connection.rollback_to_savepoint(savepoint_name) if materialized?
|
346
349
|
end
|
347
350
|
@state.rollback!
|
348
|
-
@instrumenter.finish
|
351
|
+
@instrumenter.finish(:rollback)
|
349
352
|
end
|
350
353
|
|
351
354
|
def commit
|
352
355
|
connection.release_savepoint(savepoint_name) if materialized?
|
353
356
|
@state.commit!
|
354
|
-
@instrumenter.finish
|
357
|
+
@instrumenter.finish(:commit)
|
355
358
|
end
|
356
359
|
|
357
360
|
def full_rollback?; false; end
|
@@ -372,7 +375,7 @@ module ActiveRecord
|
|
372
375
|
def restart
|
373
376
|
return unless materialized?
|
374
377
|
|
375
|
-
@instrumenter.finish
|
378
|
+
@instrumenter.finish(:restart)
|
376
379
|
|
377
380
|
if connection.supports_restart_db_transaction?
|
378
381
|
@instrumenter.start
|
@@ -386,13 +389,13 @@ module ActiveRecord
|
|
386
389
|
def rollback
|
387
390
|
connection.rollback_db_transaction if materialized?
|
388
391
|
@state.full_rollback!
|
389
|
-
@instrumenter.finish
|
392
|
+
@instrumenter.finish(:rollback)
|
390
393
|
end
|
391
394
|
|
392
395
|
def commit
|
393
396
|
connection.commit_db_transaction if materialized?
|
394
397
|
@state.full_commit!
|
395
|
-
@instrumenter.finish
|
398
|
+
@instrumenter.finish(:commit)
|
396
399
|
end
|
397
400
|
end
|
398
401
|
|
@@ -531,6 +531,13 @@ module ActiveRecord
|
|
531
531
|
expression = row["expression"]
|
532
532
|
expression = expression[1..-2] if expression.start_with?("(") && expression.end_with?(")")
|
533
533
|
expression = strip_whitespace_characters(expression)
|
534
|
+
|
535
|
+
unless mariadb?
|
536
|
+
# MySQL returns check constraints expression in an already escaped form.
|
537
|
+
# This leads to duplicate escaping later (e.g. when the expression is used in the SchemaDumper).
|
538
|
+
expression = expression.gsub("\\'", "'")
|
539
|
+
end
|
540
|
+
|
534
541
|
CheckConstraintDefinition.new(table_name, expression, options)
|
535
542
|
end
|
536
543
|
else
|
@@ -36,7 +36,7 @@ module ActiveRecord
|
|
36
36
|
end
|
37
37
|
|
38
38
|
if row[:Expression]
|
39
|
-
expression = row[:Expression]
|
39
|
+
expression = row[:Expression].gsub("\\'", "'")
|
40
40
|
expression = +"(#{expression})" unless expression.start_with?("(")
|
41
41
|
indexes.last[-2] << expression
|
42
42
|
indexes.last[-1][:expressions] ||= {}
|
@@ -75,22 +75,6 @@ module ActiveRecord
|
|
75
75
|
end
|
76
76
|
alias :exec_update :exec_delete
|
77
77
|
|
78
|
-
def sql_for_insert(sql, pk, binds, returning) # :nodoc:
|
79
|
-
if pk.nil?
|
80
|
-
# Extract the table from the insert sql. Yuck.
|
81
|
-
table_ref = extract_table_ref_from_insert_sql(sql)
|
82
|
-
pk = primary_key(table_ref) if table_ref
|
83
|
-
end
|
84
|
-
|
85
|
-
returning_columns = returning || Array(pk)
|
86
|
-
|
87
|
-
returning_columns_statement = returning_columns.map { |c| quote_column_name(c) }.join(", ")
|
88
|
-
sql = "#{sql} RETURNING #{returning_columns_statement}" if returning_columns.any?
|
89
|
-
|
90
|
-
super
|
91
|
-
end
|
92
|
-
private :sql_for_insert
|
93
|
-
|
94
78
|
def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil, returning: nil) # :nodoc:
|
95
79
|
if use_insert_returning? || pk == false
|
96
80
|
super
|
@@ -12,8 +12,8 @@ module ActiveRecord
|
|
12
12
|
sql << o.constraint_validations.map { |fk| visit_ValidateConstraint fk }.join(" ")
|
13
13
|
sql << o.exclusion_constraint_adds.map { |con| visit_AddExclusionConstraint con }.join(" ")
|
14
14
|
sql << o.exclusion_constraint_drops.map { |con| visit_DropExclusionConstraint con }.join(" ")
|
15
|
-
sql << o.
|
16
|
-
sql << o.
|
15
|
+
sql << o.unique_constraint_adds.map { |con| visit_AddUniqueConstraint con }.join(" ")
|
16
|
+
sql << o.unique_constraint_drops.map { |con| visit_DropUniqueConstraint con }.join(" ")
|
17
17
|
end
|
18
18
|
|
19
19
|
def visit_AddForeignKey(o)
|
@@ -49,7 +49,7 @@ module ActiveRecord
|
|
49
49
|
sql.join(" ")
|
50
50
|
end
|
51
51
|
|
52
|
-
def
|
52
|
+
def visit_UniqueConstraintDefinition(o)
|
53
53
|
column_name = Array(o.column).map { |column| quote_column_name(column) }.join(", ")
|
54
54
|
|
55
55
|
sql = ["CONSTRAINT"]
|
@@ -77,11 +77,11 @@ module ActiveRecord
|
|
77
77
|
"DROP CONSTRAINT #{quote_column_name(name)}"
|
78
78
|
end
|
79
79
|
|
80
|
-
def
|
80
|
+
def visit_AddUniqueConstraint(o)
|
81
81
|
"ADD #{accept(o)}"
|
82
82
|
end
|
83
83
|
|
84
|
-
def
|
84
|
+
def visit_DropUniqueConstraint(name)
|
85
85
|
"DROP CONSTRAINT #{quote_column_name(name)}"
|
86
86
|
end
|
87
87
|
|
@@ -211,7 +211,7 @@ module ActiveRecord
|
|
211
211
|
end
|
212
212
|
end
|
213
213
|
|
214
|
-
|
214
|
+
UniqueConstraintDefinition = Struct.new(:table_name, :column, :options) do
|
215
215
|
def name
|
216
216
|
options[:name]
|
217
217
|
end
|
@@ -239,12 +239,12 @@ module ActiveRecord
|
|
239
239
|
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
240
240
|
include ColumnMethods
|
241
241
|
|
242
|
-
attr_reader :exclusion_constraints, :
|
242
|
+
attr_reader :exclusion_constraints, :unique_constraints, :unlogged
|
243
243
|
|
244
244
|
def initialize(*, **)
|
245
245
|
super
|
246
246
|
@exclusion_constraints = []
|
247
|
-
@
|
247
|
+
@unique_constraints = []
|
248
248
|
@unlogged = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.create_unlogged_tables
|
249
249
|
end
|
250
250
|
|
@@ -252,8 +252,8 @@ module ActiveRecord
|
|
252
252
|
exclusion_constraints << new_exclusion_constraint_definition(expression, options)
|
253
253
|
end
|
254
254
|
|
255
|
-
def
|
256
|
-
|
255
|
+
def unique_constraint(column_name, **options)
|
256
|
+
unique_constraints << new_unique_constraint_definition(column_name, options)
|
257
257
|
end
|
258
258
|
|
259
259
|
def new_exclusion_constraint_definition(expression, options) # :nodoc:
|
@@ -261,9 +261,9 @@ module ActiveRecord
|
|
261
261
|
ExclusionConstraintDefinition.new(name, expression, options)
|
262
262
|
end
|
263
263
|
|
264
|
-
def
|
265
|
-
options = @conn.
|
266
|
-
|
264
|
+
def new_unique_constraint_definition(column_name, options) # :nodoc:
|
265
|
+
options = @conn.unique_constraint_options(name, column_name, options)
|
266
|
+
UniqueConstraintDefinition.new(name, column_name, options)
|
267
267
|
end
|
268
268
|
|
269
269
|
def new_column_definition(name, type, **options) # :nodoc:
|
@@ -315,36 +315,36 @@ module ActiveRecord
|
|
315
315
|
@base.remove_exclusion_constraint(name, *args)
|
316
316
|
end
|
317
317
|
|
318
|
-
# Adds
|
318
|
+
# Adds a unique constraint.
|
319
319
|
#
|
320
|
-
# t.
|
320
|
+
# t.unique_constraint(:position, name: 'unique_position', deferrable: :deferred)
|
321
321
|
#
|
322
|
-
# See {connection.
|
323
|
-
def
|
324
|
-
@base.
|
322
|
+
# See {connection.add_unique_constraint}[rdoc-ref:SchemaStatements#add_unique_constraint]
|
323
|
+
def unique_constraint(*args)
|
324
|
+
@base.add_unique_constraint(name, *args)
|
325
325
|
end
|
326
326
|
|
327
327
|
# Removes the given unique constraint from the table.
|
328
328
|
#
|
329
|
-
# t.
|
329
|
+
# t.remove_unique_constraint(name: "unique_position")
|
330
330
|
#
|
331
|
-
# See {connection.
|
332
|
-
def
|
333
|
-
@base.
|
331
|
+
# See {connection.remove_unique_constraint}[rdoc-ref:SchemaStatements#remove_unique_constraint]
|
332
|
+
def remove_unique_constraint(*args)
|
333
|
+
@base.remove_unique_constraint(name, *args)
|
334
334
|
end
|
335
335
|
end
|
336
336
|
|
337
337
|
# = Active Record PostgreSQL Adapter Alter \Table
|
338
338
|
class AlterTable < ActiveRecord::ConnectionAdapters::AlterTable
|
339
|
-
attr_reader :constraint_validations, :exclusion_constraint_adds, :exclusion_constraint_drops, :
|
339
|
+
attr_reader :constraint_validations, :exclusion_constraint_adds, :exclusion_constraint_drops, :unique_constraint_adds, :unique_constraint_drops
|
340
340
|
|
341
341
|
def initialize(td)
|
342
342
|
super
|
343
343
|
@constraint_validations = []
|
344
344
|
@exclusion_constraint_adds = []
|
345
345
|
@exclusion_constraint_drops = []
|
346
|
-
@
|
347
|
-
@
|
346
|
+
@unique_constraint_adds = []
|
347
|
+
@unique_constraint_drops = []
|
348
348
|
end
|
349
349
|
|
350
350
|
def validate_constraint(name)
|
@@ -359,12 +359,12 @@ module ActiveRecord
|
|
359
359
|
@exclusion_constraint_drops << constraint_name
|
360
360
|
end
|
361
361
|
|
362
|
-
def
|
363
|
-
@
|
362
|
+
def add_unique_constraint(column_name, options)
|
363
|
+
@unique_constraint_adds << @td.new_unique_constraint_definition(column_name, options)
|
364
364
|
end
|
365
365
|
|
366
|
-
def
|
367
|
-
@
|
366
|
+
def drop_unique_constraint(unique_constraint_name)
|
367
|
+
@unique_constraint_drops << unique_constraint_name
|
368
368
|
end
|
369
369
|
end
|
370
370
|
end
|
@@ -28,6 +28,17 @@ module ActiveRecord
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
+
def schemas(stream)
|
32
|
+
schema_names = @connection.schema_names - ["public"]
|
33
|
+
|
34
|
+
if schema_names.any?
|
35
|
+
schema_names.sort.each do |name|
|
36
|
+
stream.puts " create_schema #{name.inspect}"
|
37
|
+
end
|
38
|
+
stream.puts
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
31
42
|
def exclusion_constraints_in_create(table, stream)
|
32
43
|
if (exclusion_constraints = @connection.exclusion_constraints(table)).any?
|
33
44
|
add_exclusion_constraint_statements = exclusion_constraints.map do |exclusion_constraint|
|
@@ -50,23 +61,23 @@ module ActiveRecord
|
|
50
61
|
end
|
51
62
|
end
|
52
63
|
|
53
|
-
def
|
54
|
-
if (
|
55
|
-
|
64
|
+
def unique_constraints_in_create(table, stream)
|
65
|
+
if (unique_constraints = @connection.unique_constraints(table)).any?
|
66
|
+
add_unique_constraint_statements = unique_constraints.map do |unique_constraint|
|
56
67
|
parts = [
|
57
|
-
"t.
|
68
|
+
"t.unique_constraint #{unique_constraint.column.inspect}"
|
58
69
|
]
|
59
70
|
|
60
|
-
parts << "deferrable: #{
|
71
|
+
parts << "deferrable: #{unique_constraint.deferrable.inspect}" if unique_constraint.deferrable
|
61
72
|
|
62
|
-
if
|
63
|
-
parts << "name: #{
|
73
|
+
if unique_constraint.export_name_on_schema_dump?
|
74
|
+
parts << "name: #{unique_constraint.name.inspect}"
|
64
75
|
end
|
65
76
|
|
66
77
|
" #{parts.join(', ')}"
|
67
78
|
end
|
68
79
|
|
69
|
-
stream.puts
|
80
|
+
stream.puts add_unique_constraint_statements.sort.join("\n")
|
70
81
|
end
|
71
82
|
end
|
72
83
|
|
@@ -640,12 +640,12 @@ module ActiveRecord
|
|
640
640
|
end
|
641
641
|
|
642
642
|
# Returns an array of unique constraints for the given table.
|
643
|
-
# The unique constraints are represented as
|
644
|
-
def
|
643
|
+
# The unique constraints are represented as UniqueConstraintDefinition objects.
|
644
|
+
def unique_constraints(table_name)
|
645
645
|
scope = quoted_scope(table_name)
|
646
646
|
|
647
647
|
unique_info = internal_exec_query(<<~SQL, "SCHEMA", allow_retry: true, materialize_transactions: false)
|
648
|
-
SELECT c.conname, c.
|
648
|
+
SELECT c.conname, c.conrelid, c.conkey, c.condeferrable, c.condeferred
|
649
649
|
FROM pg_constraint c
|
650
650
|
JOIN pg_class t ON c.conrelid = t.oid
|
651
651
|
JOIN pg_namespace n ON n.oid = c.connamespace
|
@@ -655,21 +655,17 @@ module ActiveRecord
|
|
655
655
|
SQL
|
656
656
|
|
657
657
|
unique_info.map do |row|
|
658
|
-
|
658
|
+
conkey = row["conkey"].delete("{}").split(",").map(&:to_i)
|
659
|
+
columns = column_names_from_column_numbers(row["conrelid"], conkey)
|
659
660
|
|
660
|
-
|
661
|
-
SELECT a.attname
|
662
|
-
FROM pg_attribute a
|
663
|
-
WHERE a.attrelid = #{row['conindid']}
|
664
|
-
ORDER BY a.attnum
|
665
|
-
SQL
|
661
|
+
deferrable = extract_constraint_deferrable(row["condeferrable"], row["condeferred"])
|
666
662
|
|
667
663
|
options = {
|
668
664
|
name: row["conname"],
|
669
665
|
deferrable: deferrable
|
670
666
|
}
|
671
667
|
|
672
|
-
|
668
|
+
UniqueConstraintDefinition.new(table_name, columns, options)
|
673
669
|
end
|
674
670
|
end
|
675
671
|
|
@@ -721,7 +717,7 @@ module ActiveRecord
|
|
721
717
|
|
722
718
|
# Adds a new unique constraint to the table.
|
723
719
|
#
|
724
|
-
#
|
720
|
+
# add_unique_constraint :sections, [:position], deferrable: :deferred, name: "unique_position"
|
725
721
|
#
|
726
722
|
# generates:
|
727
723
|
#
|
@@ -729,7 +725,7 @@ module ActiveRecord
|
|
729
725
|
#
|
730
726
|
# If you want to change an existing unique index to deferrable, you can use :using_index to create deferrable unique constraints.
|
731
727
|
#
|
732
|
-
#
|
728
|
+
# add_unique_constraint :sections, deferrable: :deferred, name: "unique_position", using_index: "index_sections_on_position"
|
733
729
|
#
|
734
730
|
# The +options+ hash can include the following keys:
|
735
731
|
# [<tt>:name</tt>]
|
@@ -738,15 +734,15 @@ module ActiveRecord
|
|
738
734
|
# Specify whether or not the unique constraint should be deferrable. Valid values are +false+ or +:immediate+ or +:deferred+ to specify the default behavior. Defaults to +false+.
|
739
735
|
# [<tt>:using_index</tt>]
|
740
736
|
# To specify an existing unique index name. Defaults to +nil+.
|
741
|
-
def
|
742
|
-
options =
|
737
|
+
def add_unique_constraint(table_name, column_name = nil, **options)
|
738
|
+
options = unique_constraint_options(table_name, column_name, options)
|
743
739
|
at = create_alter_table(table_name)
|
744
|
-
at.
|
740
|
+
at.add_unique_constraint(column_name, options)
|
745
741
|
|
746
742
|
execute schema_creation.accept(at)
|
747
743
|
end
|
748
744
|
|
749
|
-
def
|
745
|
+
def unique_constraint_options(table_name, column_name, options) # :nodoc:
|
750
746
|
assert_valid_deferrable(options[:deferrable])
|
751
747
|
|
752
748
|
if column_name && options[:using_index]
|
@@ -754,22 +750,22 @@ module ActiveRecord
|
|
754
750
|
end
|
755
751
|
|
756
752
|
options = options.dup
|
757
|
-
options[:name] ||=
|
753
|
+
options[:name] ||= unique_constraint_name(table_name, column: column_name, **options)
|
758
754
|
options
|
759
755
|
end
|
760
756
|
|
761
757
|
# Removes the given unique constraint from the table.
|
762
758
|
#
|
763
|
-
#
|
759
|
+
# remove_unique_constraint :sections, name: "unique_position"
|
764
760
|
#
|
765
761
|
# The +column_name+ parameter will be ignored if present. It can be helpful
|
766
762
|
# to provide this in a migration's +change+ method so it can be reverted.
|
767
|
-
# In that case, +column_name+ will be used by #
|
768
|
-
def
|
769
|
-
unique_name_to_delete =
|
763
|
+
# In that case, +column_name+ will be used by #add_unique_constraint.
|
764
|
+
def remove_unique_constraint(table_name, column_name = nil, **options)
|
765
|
+
unique_name_to_delete = unique_constraint_for!(table_name, column: column_name, **options).name
|
770
766
|
|
771
767
|
at = create_alter_table(table_name)
|
772
|
-
at.
|
768
|
+
at.drop_unique_constraint(unique_name_to_delete)
|
773
769
|
|
774
770
|
execute schema_creation.accept(at)
|
775
771
|
end
|
@@ -1042,7 +1038,7 @@ module ActiveRecord
|
|
1042
1038
|
raise(ArgumentError, "Table '#{table_name}' has no exclusion constraint for #{expression || options}")
|
1043
1039
|
end
|
1044
1040
|
|
1045
|
-
def
|
1041
|
+
def unique_constraint_name(table_name, **options)
|
1046
1042
|
options.fetch(:name) do
|
1047
1043
|
column_or_index = Array(options[:column] || options[:using_index]).map(&:to_s)
|
1048
1044
|
identifier = "#{table_name}_#{column_or_index * '_and_'}_unique"
|
@@ -1052,13 +1048,13 @@ module ActiveRecord
|
|
1052
1048
|
end
|
1053
1049
|
end
|
1054
1050
|
|
1055
|
-
def
|
1056
|
-
name =
|
1057
|
-
|
1051
|
+
def unique_constraint_for(table_name, **options)
|
1052
|
+
name = unique_constraint_name(table_name, **options) unless options.key?(:column)
|
1053
|
+
unique_constraints(table_name).detect { |unique_constraint| unique_constraint.defined_for?(name: name, **options) }
|
1058
1054
|
end
|
1059
1055
|
|
1060
|
-
def
|
1061
|
-
|
1056
|
+
def unique_constraint_for!(table_name, column: nil, **options)
|
1057
|
+
unique_constraint_for(table_name, column: column, **options) ||
|
1062
1058
|
raise(ArgumentError, "Table '#{table_name}' has no unique constraint for #{column || options}")
|
1063
1059
|
end
|
1064
1060
|
|
@@ -226,7 +226,7 @@ module ActiveRecord
|
|
226
226
|
true
|
227
227
|
end
|
228
228
|
|
229
|
-
def
|
229
|
+
def supports_unique_constraints?
|
230
230
|
true
|
231
231
|
end
|
232
232
|
|
@@ -1089,11 +1089,6 @@ module ActiveRecord
|
|
1089
1089
|
SQL
|
1090
1090
|
end
|
1091
1091
|
|
1092
|
-
def extract_table_ref_from_insert_sql(sql)
|
1093
|
-
sql[/into\s("[A-Za-z0-9_."\[\]\s]+"|[A-Za-z0-9_."\[\]]+)\s*/im]
|
1094
|
-
$1.strip if $1
|
1095
|
-
end
|
1096
|
-
|
1097
1092
|
def arel_visitor
|
1098
1093
|
Arel::Visitors::PostgreSQL.new(self)
|
1099
1094
|
end
|
@@ -66,7 +66,7 @@ module ActiveRecord
|
|
66
66
|
cache(connection).indexes(connection, table_name)
|
67
67
|
end
|
68
68
|
|
69
|
-
def database_version(connection)
|
69
|
+
def database_version(connection) # :nodoc:
|
70
70
|
cache(connection).database_version(connection)
|
71
71
|
end
|
72
72
|
|
@@ -196,7 +196,7 @@ module ActiveRecord
|
|
196
196
|
@schema_reflection.indexes(@connection, table_name)
|
197
197
|
end
|
198
198
|
|
199
|
-
def database_version
|
199
|
+
def database_version # :nodoc:
|
200
200
|
@schema_reflection.database_version(@connection)
|
201
201
|
end
|
202
202
|
|
@@ -138,10 +138,6 @@ module ActiveRecord
|
|
138
138
|
end
|
139
139
|
end
|
140
140
|
|
141
|
-
def last_inserted_id(result)
|
142
|
-
@raw_connection.last_insert_row_id
|
143
|
-
end
|
144
|
-
|
145
141
|
def build_fixture_statements(fixture_set)
|
146
142
|
fixture_set.flat_map do |table_name, fixtures|
|
147
143
|
next if fixtures.empty?
|
@@ -152,6 +148,10 @@ module ActiveRecord
|
|
152
148
|
def build_truncate_statement(table_name)
|
153
149
|
"DELETE FROM #{quote_table_name(table_name)}"
|
154
150
|
end
|
151
|
+
|
152
|
+
def returning_column_values(result)
|
153
|
+
result.rows.first
|
154
|
+
end
|
155
155
|
end
|
156
156
|
end
|
157
157
|
end
|