activerecord 7.1.6 → 7.2.3

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.
Files changed (193) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +839 -2248
  3. data/README.rdoc +16 -16
  4. data/examples/performance.rb +2 -2
  5. data/lib/active_record/association_relation.rb +1 -1
  6. data/lib/active_record/associations/alias_tracker.rb +31 -23
  7. data/lib/active_record/associations/association.rb +15 -8
  8. data/lib/active_record/associations/belongs_to_association.rb +31 -8
  9. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
  10. data/lib/active_record/associations/builder/belongs_to.rb +1 -0
  11. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +2 -2
  12. data/lib/active_record/associations/builder/has_many.rb +3 -4
  13. data/lib/active_record/associations/builder/has_one.rb +3 -4
  14. data/lib/active_record/associations/collection_association.rb +16 -8
  15. data/lib/active_record/associations/collection_proxy.rb +14 -1
  16. data/lib/active_record/associations/errors.rb +265 -0
  17. data/lib/active_record/associations/has_many_association.rb +1 -1
  18. data/lib/active_record/associations/has_many_through_association.rb +7 -1
  19. data/lib/active_record/associations/join_dependency/join_association.rb +1 -1
  20. data/lib/active_record/associations/nested_error.rb +47 -0
  21. data/lib/active_record/associations/preloader/association.rb +2 -1
  22. data/lib/active_record/associations/preloader/branch.rb +7 -1
  23. data/lib/active_record/associations/preloader/through_association.rb +1 -3
  24. data/lib/active_record/associations/singular_association.rb +6 -0
  25. data/lib/active_record/associations/through_association.rb +1 -1
  26. data/lib/active_record/associations.rb +59 -292
  27. data/lib/active_record/attribute_assignment.rb +0 -2
  28. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  29. data/lib/active_record/attribute_methods/primary_key.rb +23 -55
  30. data/lib/active_record/attribute_methods/read.rb +1 -13
  31. data/lib/active_record/attribute_methods/serialization.rb +5 -25
  32. data/lib/active_record/attribute_methods/time_zone_conversion.rb +7 -6
  33. data/lib/active_record/attribute_methods.rb +51 -60
  34. data/lib/active_record/attributes.rb +93 -68
  35. data/lib/active_record/autosave_association.rb +25 -32
  36. data/lib/active_record/base.rb +4 -5
  37. data/lib/active_record/callbacks.rb +1 -1
  38. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +24 -107
  39. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +1 -0
  40. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +294 -72
  41. data/lib/active_record/connection_adapters/abstract/database_statements.rb +34 -17
  42. data/lib/active_record/connection_adapters/abstract/query_cache.rb +201 -75
  43. data/lib/active_record/connection_adapters/abstract/quoting.rb +65 -91
  44. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +6 -2
  45. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +18 -6
  46. data/lib/active_record/connection_adapters/abstract/transaction.rb +125 -62
  47. data/lib/active_record/connection_adapters/abstract_adapter.rb +46 -44
  48. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +53 -15
  49. data/lib/active_record/connection_adapters/mysql/database_statements.rb +9 -1
  50. data/lib/active_record/connection_adapters/mysql/quoting.rb +43 -48
  51. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +6 -0
  52. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +19 -18
  53. data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -23
  54. data/lib/active_record/connection_adapters/pool_config.rb +7 -6
  55. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +27 -4
  56. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
  57. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
  58. data/lib/active_record/connection_adapters/postgresql/quoting.rb +58 -58
  59. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +30 -8
  60. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +1 -1
  61. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +16 -12
  62. data/lib/active_record/connection_adapters/postgresql_adapter.rb +36 -26
  63. data/lib/active_record/connection_adapters/schema_cache.rb +123 -128
  64. data/lib/active_record/connection_adapters/sqlite3/column.rb +14 -1
  65. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +10 -6
  66. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +57 -46
  67. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  68. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +13 -0
  69. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
  70. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +26 -2
  71. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +133 -78
  72. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +15 -15
  73. data/lib/active_record/connection_adapters/trilogy_adapter.rb +19 -48
  74. data/lib/active_record/connection_adapters.rb +121 -0
  75. data/lib/active_record/connection_handling.rb +68 -49
  76. data/lib/active_record/core.rb +112 -44
  77. data/lib/active_record/counter_cache.rb +19 -10
  78. data/lib/active_record/database_configurations/connection_url_resolver.rb +9 -2
  79. data/lib/active_record/database_configurations/database_config.rb +19 -4
  80. data/lib/active_record/database_configurations/hash_config.rb +38 -34
  81. data/lib/active_record/database_configurations/url_config.rb +20 -1
  82. data/lib/active_record/database_configurations.rb +1 -1
  83. data/lib/active_record/delegated_type.rb +42 -18
  84. data/lib/active_record/dynamic_matchers.rb +2 -2
  85. data/lib/active_record/encryption/encryptable_record.rb +4 -4
  86. data/lib/active_record/encryption/encrypted_attribute_type.rb +25 -5
  87. data/lib/active_record/encryption/encryptor.rb +35 -19
  88. data/lib/active_record/encryption/key_provider.rb +1 -1
  89. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  90. data/lib/active_record/encryption/message_serializer.rb +4 -0
  91. data/lib/active_record/encryption/null_encryptor.rb +4 -0
  92. data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
  93. data/lib/active_record/enum.rb +31 -13
  94. data/lib/active_record/errors.rb +49 -23
  95. data/lib/active_record/explain.rb +13 -24
  96. data/lib/active_record/fixture_set/table_row.rb +19 -2
  97. data/lib/active_record/fixtures.rb +37 -31
  98. data/lib/active_record/future_result.rb +8 -4
  99. data/lib/active_record/gem_version.rb +2 -2
  100. data/lib/active_record/inheritance.rb +4 -2
  101. data/lib/active_record/insert_all.rb +18 -15
  102. data/lib/active_record/integration.rb +4 -1
  103. data/lib/active_record/internal_metadata.rb +48 -34
  104. data/lib/active_record/locking/optimistic.rb +7 -6
  105. data/lib/active_record/log_subscriber.rb +0 -21
  106. data/lib/active_record/message_pack.rb +1 -1
  107. data/lib/active_record/migration/command_recorder.rb +2 -3
  108. data/lib/active_record/migration/compatibility.rb +5 -3
  109. data/lib/active_record/migration/default_strategy.rb +4 -5
  110. data/lib/active_record/migration/pending_migration_connection.rb +2 -2
  111. data/lib/active_record/migration.rb +87 -77
  112. data/lib/active_record/model_schema.rb +31 -68
  113. data/lib/active_record/nested_attributes.rb +11 -3
  114. data/lib/active_record/normalization.rb +3 -7
  115. data/lib/active_record/persistence.rb +30 -352
  116. data/lib/active_record/query_cache.rb +19 -8
  117. data/lib/active_record/query_logs.rb +19 -0
  118. data/lib/active_record/querying.rb +25 -13
  119. data/lib/active_record/railtie.rb +39 -57
  120. data/lib/active_record/railties/controller_runtime.rb +13 -4
  121. data/lib/active_record/railties/databases.rake +42 -44
  122. data/lib/active_record/reflection.rb +98 -36
  123. data/lib/active_record/relation/batches/batch_enumerator.rb +15 -2
  124. data/lib/active_record/relation/batches.rb +14 -8
  125. data/lib/active_record/relation/calculations.rb +127 -89
  126. data/lib/active_record/relation/delegation.rb +8 -11
  127. data/lib/active_record/relation/finder_methods.rb +26 -12
  128. data/lib/active_record/relation/merger.rb +4 -6
  129. data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
  130. data/lib/active_record/relation/predicate_builder/association_query_value.rb +10 -2
  131. data/lib/active_record/relation/predicate_builder.rb +3 -3
  132. data/lib/active_record/relation/query_attribute.rb +1 -1
  133. data/lib/active_record/relation/query_methods.rb +238 -65
  134. data/lib/active_record/relation/record_fetch_warning.rb +3 -0
  135. data/lib/active_record/relation/spawn_methods.rb +2 -18
  136. data/lib/active_record/relation/where_clause.rb +15 -21
  137. data/lib/active_record/relation.rb +508 -74
  138. data/lib/active_record/result.rb +31 -44
  139. data/lib/active_record/runtime_registry.rb +39 -0
  140. data/lib/active_record/sanitization.rb +24 -19
  141. data/lib/active_record/schema.rb +8 -6
  142. data/lib/active_record/schema_dumper.rb +48 -20
  143. data/lib/active_record/schema_migration.rb +30 -14
  144. data/lib/active_record/scoping/named.rb +1 -0
  145. data/lib/active_record/secure_token.rb +3 -3
  146. data/lib/active_record/signed_id.rb +27 -7
  147. data/lib/active_record/statement_cache.rb +7 -7
  148. data/lib/active_record/table_metadata.rb +1 -10
  149. data/lib/active_record/tasks/database_tasks.rb +69 -41
  150. data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
  151. data/lib/active_record/tasks/postgresql_database_tasks.rb +8 -1
  152. data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -1
  153. data/lib/active_record/test_fixtures.rb +86 -89
  154. data/lib/active_record/testing/query_assertions.rb +121 -0
  155. data/lib/active_record/timestamp.rb +2 -2
  156. data/lib/active_record/token_for.rb +22 -12
  157. data/lib/active_record/touch_later.rb +1 -1
  158. data/lib/active_record/transaction.rb +132 -0
  159. data/lib/active_record/transactions.rb +73 -15
  160. data/lib/active_record/translation.rb +0 -2
  161. data/lib/active_record/type/serialized.rb +1 -3
  162. data/lib/active_record/type_caster/connection.rb +4 -4
  163. data/lib/active_record/validations/associated.rb +9 -3
  164. data/lib/active_record/validations/uniqueness.rb +15 -10
  165. data/lib/active_record/validations.rb +4 -1
  166. data/lib/active_record.rb +148 -39
  167. data/lib/arel/alias_predication.rb +1 -1
  168. data/lib/arel/collectors/bind.rb +3 -1
  169. data/lib/arel/collectors/composite.rb +7 -0
  170. data/lib/arel/collectors/sql_string.rb +1 -1
  171. data/lib/arel/collectors/substitute_binds.rb +1 -1
  172. data/lib/arel/crud.rb +2 -0
  173. data/lib/arel/delete_manager.rb +5 -0
  174. data/lib/arel/nodes/binary.rb +0 -6
  175. data/lib/arel/nodes/bound_sql_literal.rb +9 -5
  176. data/lib/arel/nodes/delete_statement.rb +4 -2
  177. data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
  178. data/lib/arel/nodes/node.rb +4 -3
  179. data/lib/arel/nodes/sql_literal.rb +7 -0
  180. data/lib/arel/nodes/update_statement.rb +4 -2
  181. data/lib/arel/nodes.rb +2 -2
  182. data/lib/arel/predications.rb +1 -1
  183. data/lib/arel/select_manager.rb +7 -3
  184. data/lib/arel/tree_manager.rb +3 -2
  185. data/lib/arel/update_manager.rb +7 -1
  186. data/lib/arel/visitors/dot.rb +3 -0
  187. data/lib/arel/visitors/mysql.rb +9 -4
  188. data/lib/arel/visitors/postgresql.rb +1 -12
  189. data/lib/arel/visitors/sqlite.rb +25 -0
  190. data/lib/arel/visitors/to_sql.rb +31 -16
  191. data/lib/arel.rb +7 -3
  192. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
  193. metadata +16 -10
@@ -52,8 +52,9 @@ module Arel # :nodoc: all
52
52
 
53
53
  def to_sql(engine = Table.engine)
54
54
  collector = Arel::Collectors::SQLString.new
55
- collector = engine.connection.visitor.accept @ast, collector
56
- collector.value
55
+ engine.with_connection do |connection|
56
+ connection.visitor.accept(@ast, collector).value
57
+ end
57
58
  end
58
59
 
59
60
  def initialize_copy(other)
@@ -16,7 +16,8 @@ module Arel # :nodoc: all
16
16
  end
17
17
 
18
18
  def set(values)
19
- if String === values
19
+ case values
20
+ when String, Nodes::BoundSqlLiteral
20
21
  @ast.values = [values]
21
22
  else
22
23
  @ast.values = values.map { |column, value|
@@ -44,5 +45,10 @@ module Arel # :nodoc: all
44
45
  @ast.havings << expr
45
46
  self
46
47
  end
48
+
49
+ def comment(value)
50
+ @ast.comment = value
51
+ self
52
+ end
47
53
  end
48
54
  end
@@ -153,6 +153,7 @@ module Arel # :nodoc: all
153
153
  visit_edge o, "orders"
154
154
  visit_edge o, "limit"
155
155
  visit_edge o, "offset"
156
+ visit_edge o, "comment"
156
157
  visit_edge o, "key"
157
158
  end
158
159
 
@@ -162,6 +163,7 @@ module Arel # :nodoc: all
162
163
  visit_edge o, "orders"
163
164
  visit_edge o, "limit"
164
165
  visit_edge o, "offset"
166
+ visit_edge o, "comment"
165
167
  visit_edge o, "key"
166
168
  end
167
169
 
@@ -191,6 +193,7 @@ module Arel # :nodoc: all
191
193
  end
192
194
  end
193
195
  alias :visit_Arel_Nodes_And :visit__children
196
+ alias :visit_Arel_Nodes_Or :visit__children
194
197
  alias :visit_Arel_Nodes_With :visit__children
195
198
 
196
199
  def visit_String(o)
@@ -27,7 +27,7 @@ module Arel # :nodoc: all
27
27
  end
28
28
 
29
29
  def visit_Arel_Nodes_SelectCore(o, collector)
30
- o.froms ||= Arel.sql("DUAL")
30
+ o.froms ||= Arel.sql("DUAL", retryable: true)
31
31
  super
32
32
  end
33
33
 
@@ -59,9 +59,14 @@ module Arel # :nodoc: all
59
59
  infix_value o, collector, " NOT REGEXP "
60
60
  end
61
61
 
62
- # no-op
63
62
  def visit_Arel_Nodes_NullsFirst(o, collector)
64
- visit o.expr, collector
63
+ visit(o.expr.expr, collector) << " IS NOT NULL, "
64
+ visit(o.expr, collector)
65
+ end
66
+
67
+ def visit_Arel_Nodes_NullsLast(o, collector)
68
+ visit(o.expr.expr, collector) << " IS NULL, "
69
+ visit(o.expr, collector)
65
70
  end
66
71
 
67
72
  def visit_Arel_Nodes_Cte(o, collector)
@@ -98,7 +103,7 @@ module Arel # :nodoc: all
98
103
  Nodes::SelectStatement.new.tap do |stmt|
99
104
  core = stmt.cores.last
100
105
  core.froms = Nodes::Grouping.new(subselect).as("__active_record_temp")
101
- core.projections = [Arel.sql(quote_column_name(key.name))]
106
+ core.projections = [Arel.sql(quote_column_name(key.name), retryable: true)]
102
107
  end
103
108
  end
104
109
  end
@@ -63,7 +63,7 @@ module Arel # :nodoc: all
63
63
 
64
64
  def visit_Arel_Nodes_Lateral(o, collector)
65
65
  collector << "LATERAL "
66
- grouping_parentheses o, collector
66
+ grouping_parentheses o.expr, collector
67
67
  end
68
68
 
69
69
  def visit_Arel_Nodes_IsNotDistinctFrom(o, collector)
@@ -83,17 +83,6 @@ module Arel # :nodoc: all
83
83
 
84
84
  def bind_block; BIND_BLOCK; end
85
85
 
86
- # Used by Lateral visitor to enclose select queries in parentheses
87
- def grouping_parentheses(o, collector)
88
- if o.expr.is_a? Nodes::SelectStatement
89
- collector << "("
90
- visit o.expr, collector
91
- collector << ")"
92
- else
93
- visit o.expr, collector
94
- end
95
- end
96
-
97
86
  # Utilized by GroupingSet, Cube & RollUp visitors to
98
87
  # handle grouping aggregation semantics
99
88
  def grouping_array_or_grouping_element(o, collector)
@@ -33,6 +33,31 @@ module Arel # :nodoc: all
33
33
  collector << " IS NOT "
34
34
  visit o.right, collector
35
35
  end
36
+
37
+ # Queries used in UNION should not be wrapped by parentheses,
38
+ # because it is an invalid syntax in SQLite.
39
+ def infix_value_with_paren(o, collector, value, suppress_parens = false)
40
+ collector << "( " unless suppress_parens
41
+
42
+ left = o.left.is_a?(Nodes::Grouping) ? o.left.expr : o.left
43
+ collector = if left.class == o.class
44
+ infix_value_with_paren(left, collector, value, true)
45
+ else
46
+ grouping_parentheses left, collector, false
47
+ end
48
+
49
+ collector << value
50
+
51
+ right = o.right.is_a?(Nodes::Grouping) ? o.right.expr : o.right
52
+ collector = if right.class == o.class
53
+ infix_value_with_paren(right, collector, value, true)
54
+ else
55
+ grouping_parentheses right, collector, false
56
+ end
57
+
58
+ collector << " )" unless suppress_parens
59
+ collector
60
+ end
36
61
  end
37
62
  end
38
63
  end
@@ -20,6 +20,7 @@ module Arel # :nodoc: all
20
20
 
21
21
  private
22
22
  def visit_Arel_Nodes_DeleteStatement(o, collector)
23
+ collector.retryable = false
23
24
  o = prepare_delete_statement(o)
24
25
 
25
26
  if has_join_sources?(o)
@@ -34,9 +35,11 @@ module Arel # :nodoc: all
34
35
  collect_nodes_for o.wheres, collector, " WHERE ", " AND "
35
36
  collect_nodes_for o.orders, collector, " ORDER BY "
36
37
  maybe_visit o.limit, collector
38
+ maybe_visit o.comment, collector
37
39
  end
38
40
 
39
41
  def visit_Arel_Nodes_UpdateStatement(o, collector)
42
+ collector.retryable = false
40
43
  o = prepare_update_statement(o)
41
44
 
42
45
  collector << "UPDATE "
@@ -46,9 +49,11 @@ module Arel # :nodoc: all
46
49
  collect_nodes_for o.wheres, collector, " WHERE ", " AND "
47
50
  collect_nodes_for o.orders, collector, " ORDER BY "
48
51
  maybe_visit o.limit, collector
52
+ maybe_visit o.comment, collector
49
53
  end
50
54
 
51
55
  def visit_Arel_Nodes_InsertStatement(o, collector)
56
+ collector.retryable = false
52
57
  collector << "INSERT INTO "
53
58
  collector = visit o.relation, collector
54
59
 
@@ -381,6 +386,7 @@ module Arel # :nodoc: all
381
386
  end
382
387
 
383
388
  def visit_Arel_Nodes_NamedFunction(o, collector)
389
+ collector.retryable = false
384
390
  collector << o.name
385
391
  collector << "("
386
392
  collector << "DISTINCT " if o.distinct
@@ -582,10 +588,11 @@ module Arel # :nodoc: all
582
588
  end
583
589
 
584
590
  def visit_Arel_Nodes_In(o, collector)
585
- collector.preparable = false
586
591
  attr, values = o.left, o.right
587
592
 
588
593
  if Array === values
594
+ collector.preparable = false
595
+
589
596
  unless values.empty?
590
597
  values.delete_if { |value| unboundable?(value) }
591
598
  end
@@ -598,10 +605,11 @@ module Arel # :nodoc: all
598
605
  end
599
606
 
600
607
  def visit_Arel_Nodes_NotIn(o, collector)
601
- collector.preparable = false
602
608
  attr, values = o.left, o.right
603
609
 
604
610
  if Array === values
611
+ collector.preparable = false
612
+
605
613
  unless values.empty?
606
614
  values.delete_if { |value| unboundable?(value) }
607
615
  end
@@ -618,18 +626,7 @@ module Arel # :nodoc: all
618
626
  end
619
627
 
620
628
  def visit_Arel_Nodes_Or(o, collector)
621
- stack = [o.right, o.left]
622
-
623
- while o = stack.pop
624
- if o.is_a?(Arel::Nodes::Or)
625
- stack.push o.right, o.left
626
- else
627
- visit o, collector
628
- collector << " OR " unless stack.empty?
629
- end
630
- end
631
-
632
- collector
629
+ inject_join o.children, collector, " OR "
633
630
  end
634
631
 
635
632
  def visit_Arel_Nodes_Assignment(o, collector)
@@ -768,10 +765,12 @@ module Arel # :nodoc: all
768
765
 
769
766
  def visit_Arel_Nodes_SqlLiteral(o, collector)
770
767
  collector.preparable = false
768
+ collector.retryable &&= o.retryable
771
769
  collector << o.to_s
772
770
  end
773
771
 
774
772
  def visit_Arel_Nodes_BoundSqlLiteral(o, collector)
773
+ collector.retryable = false
775
774
  bind_index = 0
776
775
 
777
776
  new_bind = lambda do |value|
@@ -968,18 +967,34 @@ module Arel # :nodoc: all
968
967
  collector = if o.left.class == o.class
969
968
  infix_value_with_paren(o.left, collector, value, true)
970
969
  else
971
- visit o.left, collector
970
+ grouping_parentheses o.left, collector, false
972
971
  end
973
972
  collector << value
974
973
  collector = if o.right.class == o.class
975
974
  infix_value_with_paren(o.right, collector, value, true)
976
975
  else
977
- visit o.right, collector
976
+ grouping_parentheses o.right, collector, false
978
977
  end
979
978
  collector << " )" unless suppress_parens
980
979
  collector
981
980
  end
982
981
 
982
+ # Used by some visitors to enclose select queries in parentheses
983
+ def grouping_parentheses(o, collector, always_wrap_selects = true)
984
+ if o.is_a?(Nodes::SelectStatement) && (always_wrap_selects || require_parentheses?(o))
985
+ collector << "("
986
+ visit o, collector
987
+ collector << ")"
988
+ collector
989
+ else
990
+ visit o, collector
991
+ end
992
+ end
993
+
994
+ def require_parentheses?(o)
995
+ !o.orders.empty? || o.limit || o.offset
996
+ end
997
+
983
998
  def aggregate(name, o, collector)
984
999
  collector << "#{name}("
985
1000
  if o.distinct
data/lib/arel.rb CHANGED
@@ -45,16 +45,20 @@ module Arel
45
45
  # that this behavior only applies when bind value parameters are
46
46
  # supplied in the call; without them, the placeholder tokens have no
47
47
  # special meaning, and will be passed through to the query as-is.
48
- def self.sql(sql_string, *positional_binds, **named_binds)
48
+ #
49
+ # The +:retryable+ option can be used to mark the SQL as safe to retry.
50
+ # Use this option only if the SQL is idempotent, as it could be executed
51
+ # more than once.
52
+ def self.sql(sql_string, *positional_binds, retryable: false, **named_binds)
49
53
  if positional_binds.empty? && named_binds.empty?
50
- Arel::Nodes::SqlLiteral.new sql_string
54
+ Arel::Nodes::SqlLiteral.new(sql_string, retryable: retryable)
51
55
  else
52
56
  Arel::Nodes::BoundSqlLiteral.new sql_string, positional_binds, named_binds
53
57
  end
54
58
  end
55
59
 
56
60
  def self.star # :nodoc:
57
- sql "*"
61
+ sql("*", retryable: true)
58
62
  end
59
63
 
60
64
  def self.arel_node?(value) # :nodoc:
@@ -12,7 +12,10 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
12
12
  t.<%= attribute.type %> :<%= attribute.name %><%= attribute.inject_options %>
13
13
  <% end -%>
14
14
  <% end -%>
15
- <% if options[:timestamps] %>
15
+ <% unless attributes.empty? -%>
16
+
17
+ <% end -%>
18
+ <% if options[:timestamps] -%>
16
19
  t.timestamps
17
20
  <% end -%>
18
21
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.1.6
4
+ version: 7.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
@@ -15,28 +15,28 @@ dependencies:
15
15
  requirements:
16
16
  - - '='
17
17
  - !ruby/object:Gem::Version
18
- version: 7.1.6
18
+ version: 7.2.3
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - '='
24
24
  - !ruby/object:Gem::Version
25
- version: 7.1.6
25
+ version: 7.2.3
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: activemodel
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - '='
31
31
  - !ruby/object:Gem::Version
32
- version: 7.1.6
32
+ version: 7.2.3
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - '='
38
38
  - !ruby/object:Gem::Version
39
- version: 7.1.6
39
+ version: 7.2.3
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: timeout
42
42
  requirement: !ruby/object:Gem::Requirement
@@ -84,6 +84,7 @@ files:
84
84
  - lib/active_record/associations/collection_association.rb
85
85
  - lib/active_record/associations/collection_proxy.rb
86
86
  - lib/active_record/associations/disable_joins_association_scope.rb
87
+ - lib/active_record/associations/errors.rb
87
88
  - lib/active_record/associations/foreign_association.rb
88
89
  - lib/active_record/associations/has_many_association.rb
89
90
  - lib/active_record/associations/has_many_through_association.rb
@@ -93,6 +94,7 @@ files:
93
94
  - lib/active_record/associations/join_dependency/join_association.rb
94
95
  - lib/active_record/associations/join_dependency/join_base.rb
95
96
  - lib/active_record/associations/join_dependency/join_part.rb
97
+ - lib/active_record/associations/nested_error.rb
96
98
  - lib/active_record/associations/preloader.rb
97
99
  - lib/active_record/associations/preloader/association.rb
98
100
  - lib/active_record/associations/preloader/batch.rb
@@ -104,6 +106,7 @@ files:
104
106
  - lib/active_record/attribute_assignment.rb
105
107
  - lib/active_record/attribute_methods.rb
106
108
  - lib/active_record/attribute_methods/before_type_cast.rb
109
+ - lib/active_record/attribute_methods/composite_primary_key.rb
107
110
  - lib/active_record/attribute_methods/dirty.rb
108
111
  - lib/active_record/attribute_methods/primary_key.rb
109
112
  - lib/active_record/attribute_methods/query.rb
@@ -239,6 +242,7 @@ files:
239
242
  - lib/active_record/encryption/key_generator.rb
240
243
  - lib/active_record/encryption/key_provider.rb
241
244
  - lib/active_record/encryption/message.rb
245
+ - lib/active_record/encryption/message_pack_message_serializer.rb
242
246
  - lib/active_record/encryption/message_serializer.rb
243
247
  - lib/active_record/encryption/null_encryptor.rb
244
248
  - lib/active_record/encryption/properties.rb
@@ -339,9 +343,11 @@ files:
339
343
  - lib/active_record/tasks/sqlite_database_tasks.rb
340
344
  - lib/active_record/test_databases.rb
341
345
  - lib/active_record/test_fixtures.rb
346
+ - lib/active_record/testing/query_assertions.rb
342
347
  - lib/active_record/timestamp.rb
343
348
  - lib/active_record/token_for.rb
344
349
  - lib/active_record/touch_later.rb
350
+ - lib/active_record/transaction.rb
345
351
  - lib/active_record/transactions.rb
346
352
  - lib/active_record/translation.rb
347
353
  - lib/active_record/type.rb
@@ -385,7 +391,6 @@ files:
385
391
  - lib/arel/insert_manager.rb
386
392
  - lib/arel/math.rb
387
393
  - lib/arel/nodes.rb
388
- - lib/arel/nodes/and.rb
389
394
  - lib/arel/nodes/ascending.rb
390
395
  - lib/arel/nodes/binary.rb
391
396
  - lib/arel/nodes/bind_param.rb
@@ -414,6 +419,7 @@ files:
414
419
  - lib/arel/nodes/leading_join.rb
415
420
  - lib/arel/nodes/matches.rb
416
421
  - lib/arel/nodes/named_function.rb
422
+ - lib/arel/nodes/nary.rb
417
423
  - lib/arel/nodes/node.rb
418
424
  - lib/arel/nodes/node_expression.rb
419
425
  - lib/arel/nodes/ordering.rb
@@ -469,10 +475,10 @@ licenses:
469
475
  - MIT
470
476
  metadata:
471
477
  bug_tracker_uri: https://github.com/rails/rails/issues
472
- changelog_uri: https://github.com/rails/rails/blob/v7.1.6/activerecord/CHANGELOG.md
473
- documentation_uri: https://api.rubyonrails.org/v7.1.6/
478
+ changelog_uri: https://github.com/rails/rails/blob/v7.2.3/activerecord/CHANGELOG.md
479
+ documentation_uri: https://api.rubyonrails.org/v7.2.3/
474
480
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
475
- source_code_uri: https://github.com/rails/rails/tree/v7.1.6/activerecord
481
+ source_code_uri: https://github.com/rails/rails/tree/v7.2.3/activerecord
476
482
  rubygems_mfa_required: 'true'
477
483
  rdoc_options:
478
484
  - "--main"
@@ -483,7 +489,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
483
489
  requirements:
484
490
  - - ">="
485
491
  - !ruby/object:Gem::Version
486
- version: 2.7.0
492
+ version: 3.1.0
487
493
  required_rubygems_version: !ruby/object:Gem::Requirement
488
494
  requirements:
489
495
  - - ">="