activerecord 5.1.0 → 5.2.0.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.

Files changed (260) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +410 -530
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -4
  5. data/examples/performance.rb +2 -0
  6. data/examples/simple.rb +2 -0
  7. data/lib/active_record/aggregations.rb +6 -5
  8. data/lib/active_record/association_relation.rb +4 -2
  9. data/lib/active_record/associations/alias_tracker.rb +23 -32
  10. data/lib/active_record/associations/association.rb +20 -21
  11. data/lib/active_record/associations/association_scope.rb +49 -49
  12. data/lib/active_record/associations/belongs_to_association.rb +12 -10
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +4 -7
  14. data/lib/active_record/associations/builder/association.rb +4 -7
  15. data/lib/active_record/associations/builder/belongs_to.rb +10 -6
  16. data/lib/active_record/associations/builder/collection_association.rb +1 -1
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
  18. data/lib/active_record/associations/builder/has_many.rb +2 -0
  19. data/lib/active_record/associations/builder/has_one.rb +2 -0
  20. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  21. data/lib/active_record/associations/collection_association.rb +50 -41
  22. data/lib/active_record/associations/collection_proxy.rb +22 -39
  23. data/lib/active_record/associations/foreign_association.rb +2 -0
  24. data/lib/active_record/associations/has_many_association.rb +4 -2
  25. data/lib/active_record/associations/has_many_through_association.rb +12 -18
  26. data/lib/active_record/associations/has_one_association.rb +5 -1
  27. data/lib/active_record/associations/has_one_through_association.rb +8 -7
  28. data/lib/active_record/associations/join_dependency/join_association.rb +17 -64
  29. data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
  30. data/lib/active_record/associations/join_dependency/join_part.rb +2 -9
  31. data/lib/active_record/associations/join_dependency.rb +27 -44
  32. data/lib/active_record/associations/preloader/association.rb +53 -92
  33. data/lib/active_record/associations/preloader/through_association.rb +72 -73
  34. data/lib/active_record/associations/preloader.rb +17 -37
  35. data/lib/active_record/associations/singular_association.rb +14 -10
  36. data/lib/active_record/associations/through_association.rb +26 -11
  37. data/lib/active_record/associations.rb +68 -76
  38. data/lib/active_record/attribute_assignment.rb +2 -0
  39. data/lib/active_record/attribute_decorators.rb +3 -2
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
  41. data/lib/active_record/attribute_methods/dirty.rb +24 -214
  42. data/lib/active_record/attribute_methods/primary_key.rb +10 -13
  43. data/lib/active_record/attribute_methods/query.rb +2 -0
  44. data/lib/active_record/attribute_methods/read.rb +8 -2
  45. data/lib/active_record/attribute_methods/serialization.rb +23 -0
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
  47. data/lib/active_record/attribute_methods/write.rb +22 -19
  48. data/lib/active_record/attribute_methods.rb +48 -12
  49. data/lib/active_record/attributes.rb +7 -6
  50. data/lib/active_record/autosave_association.rb +8 -11
  51. data/lib/active_record/base.rb +2 -0
  52. data/lib/active_record/callbacks.rb +8 -6
  53. data/lib/active_record/coders/json.rb +2 -0
  54. data/lib/active_record/coders/yaml_column.rb +2 -0
  55. data/lib/active_record/collection_cache_key.rb +14 -10
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +110 -35
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +175 -33
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +8 -2
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +13 -24
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -6
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +58 -3
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +165 -85
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +83 -97
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +118 -180
  69. data/lib/active_record/connection_adapters/column.rb +4 -2
  70. data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +11 -17
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -10
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -23
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +106 -1
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -32
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +2 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  96. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
  98. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +4 -2
  101. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
  103. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
  104. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -1
  107. data/lib/active_record/connection_adapters/postgresql/quoting.rb +22 -1
  108. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
  109. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
  111. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
  112. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +269 -126
  113. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
  114. data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -0
  115. data/lib/active_record/connection_adapters/postgresql_adapter.rb +64 -85
  116. data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
  117. data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
  118. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
  119. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +18 -0
  120. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
  121. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
  122. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
  123. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +71 -1
  124. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +92 -95
  125. data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
  126. data/lib/active_record/connection_handling.rb +4 -2
  127. data/lib/active_record/core.rb +39 -60
  128. data/lib/active_record/counter_cache.rb +3 -2
  129. data/lib/active_record/define_callbacks.rb +5 -3
  130. data/lib/active_record/dynamic_matchers.rb +9 -9
  131. data/lib/active_record/enum.rb +17 -13
  132. data/lib/active_record/errors.rb +42 -3
  133. data/lib/active_record/explain.rb +3 -1
  134. data/lib/active_record/explain_registry.rb +2 -0
  135. data/lib/active_record/explain_subscriber.rb +2 -0
  136. data/lib/active_record/fixture_set/file.rb +2 -0
  137. data/lib/active_record/fixtures.rb +67 -60
  138. data/lib/active_record/gem_version.rb +4 -2
  139. data/lib/active_record/inheritance.rb +9 -9
  140. data/lib/active_record/integration.rb +58 -19
  141. data/lib/active_record/internal_metadata.rb +2 -0
  142. data/lib/active_record/legacy_yaml_adapter.rb +3 -1
  143. data/lib/active_record/locking/optimistic.rb +8 -6
  144. data/lib/active_record/locking/pessimistic.rb +9 -6
  145. data/lib/active_record/log_subscriber.rb +46 -4
  146. data/lib/active_record/migration/command_recorder.rb +11 -9
  147. data/lib/active_record/migration/compatibility.rb +74 -22
  148. data/lib/active_record/migration/join_table.rb +2 -0
  149. data/lib/active_record/migration.rb +181 -137
  150. data/lib/active_record/model_schema.rb +73 -58
  151. data/lib/active_record/nested_attributes.rb +18 -6
  152. data/lib/active_record/no_touching.rb +3 -1
  153. data/lib/active_record/null_relation.rb +2 -0
  154. data/lib/active_record/persistence.rb +153 -18
  155. data/lib/active_record/query_cache.rb +17 -12
  156. data/lib/active_record/querying.rb +4 -2
  157. data/lib/active_record/railtie.rb +61 -3
  158. data/lib/active_record/railties/console_sandbox.rb +2 -0
  159. data/lib/active_record/railties/controller_runtime.rb +2 -0
  160. data/lib/active_record/railties/databases.rake +47 -37
  161. data/lib/active_record/readonly_attributes.rb +3 -2
  162. data/lib/active_record/reflection.rb +131 -204
  163. data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
  164. data/lib/active_record/relation/batches.rb +32 -17
  165. data/lib/active_record/relation/calculations.rb +58 -20
  166. data/lib/active_record/relation/delegation.rb +10 -29
  167. data/lib/active_record/relation/finder_methods.rb +74 -85
  168. data/lib/active_record/relation/from_clause.rb +2 -8
  169. data/lib/active_record/relation/merger.rb +51 -20
  170. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
  171. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  172. data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
  173. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
  174. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +54 -0
  175. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -6
  176. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  177. data/lib/active_record/relation/predicate_builder.rb +53 -78
  178. data/lib/active_record/relation/query_attribute.rb +9 -2
  179. data/lib/active_record/relation/query_methods.rb +101 -95
  180. data/lib/active_record/relation/record_fetch_warning.rb +2 -0
  181. data/lib/active_record/relation/spawn_methods.rb +3 -1
  182. data/lib/active_record/relation/where_clause.rb +65 -67
  183. data/lib/active_record/relation/where_clause_factory.rb +5 -48
  184. data/lib/active_record/relation.rb +99 -202
  185. data/lib/active_record/result.rb +2 -0
  186. data/lib/active_record/runtime_registry.rb +2 -0
  187. data/lib/active_record/sanitization.rb +129 -121
  188. data/lib/active_record/schema.rb +4 -2
  189. data/lib/active_record/schema_dumper.rb +36 -26
  190. data/lib/active_record/schema_migration.rb +2 -0
  191. data/lib/active_record/scoping/default.rb +10 -7
  192. data/lib/active_record/scoping/named.rb +38 -12
  193. data/lib/active_record/scoping.rb +12 -10
  194. data/lib/active_record/secure_token.rb +2 -0
  195. data/lib/active_record/serialization.rb +2 -0
  196. data/lib/active_record/statement_cache.rb +22 -12
  197. data/lib/active_record/store.rb +3 -1
  198. data/lib/active_record/suppressor.rb +2 -0
  199. data/lib/active_record/table_metadata.rb +12 -3
  200. data/lib/active_record/tasks/database_tasks.rb +37 -25
  201. data/lib/active_record/tasks/mysql_database_tasks.rb +11 -50
  202. data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -3
  203. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
  204. data/lib/active_record/timestamp.rb +5 -5
  205. data/lib/active_record/touch_later.rb +2 -0
  206. data/lib/active_record/transactions.rb +9 -7
  207. data/lib/active_record/translation.rb +2 -0
  208. data/lib/active_record/type/adapter_specific_registry.rb +2 -0
  209. data/lib/active_record/type/date.rb +2 -0
  210. data/lib/active_record/type/date_time.rb +2 -0
  211. data/lib/active_record/type/decimal_without_scale.rb +2 -0
  212. data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
  213. data/lib/active_record/type/internal/timezone.rb +2 -0
  214. data/lib/active_record/type/json.rb +30 -0
  215. data/lib/active_record/type/serialized.rb +2 -0
  216. data/lib/active_record/type/text.rb +2 -0
  217. data/lib/active_record/type/time.rb +2 -0
  218. data/lib/active_record/type/type_map.rb +2 -0
  219. data/lib/active_record/type/unsigned_integer.rb +2 -0
  220. data/lib/active_record/type.rb +4 -1
  221. data/lib/active_record/type_caster/connection.rb +2 -0
  222. data/lib/active_record/type_caster/map.rb +3 -1
  223. data/lib/active_record/type_caster.rb +2 -0
  224. data/lib/active_record/validations/absence.rb +2 -0
  225. data/lib/active_record/validations/associated.rb +2 -0
  226. data/lib/active_record/validations/length.rb +2 -0
  227. data/lib/active_record/validations/presence.rb +2 -0
  228. data/lib/active_record/validations/uniqueness.rb +35 -5
  229. data/lib/active_record/validations.rb +2 -0
  230. data/lib/active_record/version.rb +2 -0
  231. data/lib/active_record.rb +11 -4
  232. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  233. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  234. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
  235. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
  236. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
  237. data/lib/rails/generators/active_record/migration.rb +2 -0
  238. data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
  239. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
  240. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  241. data/lib/rails/generators/active_record.rb +3 -1
  242. metadata +25 -37
  243. data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
  244. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  245. data/lib/active_record/associations/preloader/has_many.rb +0 -15
  246. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  247. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  248. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  249. data/lib/active_record/associations/preloader/singular_association.rb +0 -18
  250. data/lib/active_record/attribute/user_provided_default.rb +0 -30
  251. data/lib/active_record/attribute.rb +0 -240
  252. data/lib/active_record/attribute_mutation_tracker.rb +0 -113
  253. data/lib/active_record/attribute_set/builder.rb +0 -124
  254. data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
  255. data/lib/active_record/attribute_set.rb +0 -113
  256. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
  257. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  258. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  259. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
  260. data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_record/connection_adapters/abstract_adapter"
2
4
  require "active_record/connection_adapters/statement_pool"
3
5
  require "active_record/connection_adapters/mysql/column"
@@ -15,21 +17,8 @@ module ActiveRecord
15
17
  module ConnectionAdapters
16
18
  class AbstractMysqlAdapter < AbstractAdapter
17
19
  include MySQL::Quoting
18
- include MySQL::ColumnDumper
19
20
  include MySQL::SchemaStatements
20
21
 
21
- def update_table_definition(table_name, base) # :nodoc:
22
- MySQL::Table.new(table_name, base)
23
- end
24
-
25
- def schema_creation # :nodoc:
26
- MySQL::SchemaCreation.new(self)
27
- end
28
-
29
- def arel_visitor # :nodoc:
30
- Arel::Visitors::MySQL.new(self)
31
- end
32
-
33
22
  ##
34
23
  # :singleton-method:
35
24
  # By default, the Mysql2Adapter will consider all columns of type <tt>tinyint(1)</tt>
@@ -37,15 +26,14 @@ module ActiveRecord
37
26
  # to your application.rb file:
38
27
  #
39
28
  # ActiveRecord::ConnectionAdapters::Mysql2Adapter.emulate_booleans = false
40
- class_attribute :emulate_booleans
41
- self.emulate_booleans = true
29
+ class_attribute :emulate_booleans, default: true
42
30
 
43
31
  NATIVE_DATABASE_TYPES = {
44
32
  primary_key: "bigint auto_increment PRIMARY KEY",
45
33
  string: { name: "varchar", limit: 255 },
46
34
  text: { name: "text", limit: 65535 },
47
35
  integer: { name: "int", limit: 4 },
48
- float: { name: "float" },
36
+ float: { name: "float", limit: 24 },
49
37
  decimal: { name: "decimal" },
50
38
  datetime: { name: "datetime" },
51
39
  timestamp: { name: "timestamp" },
@@ -56,10 +44,7 @@ module ActiveRecord
56
44
  json: { name: "json" },
57
45
  }
58
46
 
59
- INDEX_TYPES = [:fulltext, :spatial]
60
- INDEX_USINGS = [:btree, :hash]
61
-
62
- class StatementPool < ConnectionAdapters::StatementPool
47
+ class StatementPool < ConnectionAdapters::StatementPool # :nodoc:
63
48
  private def dealloc(stmt)
64
49
  stmt[:stmt].close
65
50
  end
@@ -71,12 +56,12 @@ module ActiveRecord
71
56
  @statements = StatementPool.new(self.class.type_cast_config_to_integer(config[:statement_limit]))
72
57
 
73
58
  if version < "5.1.10"
74
- raise "Your version of MySQL (#{full_version.match(/^\d+\.\d+\.\d+/)[0]}) is too old. Active Record supports MySQL >= 5.1.10."
59
+ raise "Your version of MySQL (#{version_string}) is too old. Active Record supports MySQL >= 5.1.10."
75
60
  end
76
61
  end
77
62
 
78
63
  def version #:nodoc:
79
- @version ||= Version.new(full_version.match(/^\d+\.\d+\.\d+/)[0])
64
+ @version ||= Version.new(version_string)
80
65
  end
81
66
 
82
67
  def mariadb? # :nodoc:
@@ -87,16 +72,8 @@ module ActiveRecord
87
72
  true
88
73
  end
89
74
 
90
- # Returns true, since this connection adapter supports prepared statement
91
- # caching.
92
- def supports_statement_cache?
93
- true
94
- end
95
-
96
- # Technically MySQL allows to create indexes with the sort order syntax
97
- # but at the moment (5.5) it doesn't yet implement them
98
75
  def supports_index_sort_order?
99
- true
76
+ !mariadb? && version >= "8.0.1"
100
77
  end
101
78
 
102
79
  def supports_transaction_isolation?
@@ -140,11 +117,11 @@ module ActiveRecord
140
117
  end
141
118
 
142
119
  def get_advisory_lock(lock_name, timeout = 0) # :nodoc:
143
- select_value("SELECT GET_LOCK(#{quote(lock_name)}, #{timeout})") == 1
120
+ query_value("SELECT GET_LOCK(#{quote(lock_name.to_s)}, #{timeout})") == 1
144
121
  end
145
122
 
146
123
  def release_advisory_lock(lock_name) # :nodoc:
147
- select_value("SELECT RELEASE_LOCK(#{quote(lock_name)})") == 1
124
+ query_value("SELECT RELEASE_LOCK(#{quote(lock_name.to_s)})") == 1
148
125
  end
149
126
 
150
127
  def native_database_types
@@ -152,7 +129,7 @@ module ActiveRecord
152
129
  end
153
130
 
154
131
  def index_algorithms
155
- { default: "ALGORITHM = DEFAULT", copy: "ALGORITHM = COPY", inplace: "ALGORITHM = INPLACE" }
132
+ { default: "ALGORITHM = DEFAULT".dup, copy: "ALGORITHM = COPY".dup, inplace: "ALGORITHM = INPLACE".dup }
156
133
  end
157
134
 
158
135
  # HELPER METHODS ===========================================
@@ -163,10 +140,6 @@ module ActiveRecord
163
140
  raise NotImplementedError
164
141
  end
165
142
 
166
- def new_column(*args) #:nodoc:
167
- MySQL::Column.new(*args)
168
- end
169
-
170
143
  # Must return the MySQL error number from the exception, if the exception has an
171
144
  # error number.
172
145
  def error_number(exception) # :nodoc:
@@ -176,7 +149,7 @@ module ActiveRecord
176
149
  # REFERENTIAL INTEGRITY ====================================
177
150
 
178
151
  def disable_referential_integrity #:nodoc:
179
- old = select_value("SELECT @@FOREIGN_KEY_CHECKS")
152
+ old = query_value("SELECT @@FOREIGN_KEY_CHECKS")
180
153
 
181
154
  begin
182
155
  update("SET FOREIGN_KEY_CHECKS = 0")
@@ -276,7 +249,7 @@ module ActiveRecord
276
249
  # create_database 'matt_development', charset: :big5
277
250
  def create_database(name, options = {})
278
251
  if options[:collation]
279
- execute "CREATE DATABASE #{quote_table_name(name)} DEFAULT CHARACTER SET #{quote_table_name(options[:charset] || 'utf8')} COLLATE #{quote_table_name(options[:collation])}"
252
+ execute "CREATE DATABASE #{quote_table_name(name)} DEFAULT COLLATE #{quote_table_name(options[:collation])}"
280
253
  else
281
254
  execute "CREATE DATABASE #{quote_table_name(name)} DEFAULT CHARACTER SET #{quote_table_name(options[:charset] || 'utf8')}"
282
255
  end
@@ -291,7 +264,7 @@ module ActiveRecord
291
264
  end
292
265
 
293
266
  def current_database
294
- select_value "SELECT DATABASE() as db"
267
+ query_value("SELECT database()", "SCHEMA")
295
268
  end
296
269
 
297
270
  # Returns the database character set.
@@ -308,50 +281,10 @@ module ActiveRecord
308
281
  execute "TRUNCATE TABLE #{quote_table_name(table_name)}", name
309
282
  end
310
283
 
311
- # Returns an array of indexes for the given table.
312
- def indexes(table_name, name = nil) #:nodoc:
313
- if name
314
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
315
- Passing name to #indexes is deprecated without replacement.
316
- MSG
317
- end
318
-
319
- indexes = []
320
- current_index = nil
321
- execute_and_free("SHOW KEYS FROM #{quote_table_name(table_name)}", "SCHEMA") do |result|
322
- each_hash(result) do |row|
323
- if current_index != row[:Key_name]
324
- next if row[:Key_name] == "PRIMARY" # skip the primary key
325
- current_index = row[:Key_name]
326
-
327
- mysql_index_type = row[:Index_type].downcase.to_sym
328
- index_type = INDEX_TYPES.include?(mysql_index_type) ? mysql_index_type : nil
329
- index_using = INDEX_USINGS.include?(mysql_index_type) ? mysql_index_type : nil
330
- indexes << IndexDefinition.new(row[:Table], row[:Key_name], row[:Non_unique].to_i == 0, [], {}, nil, nil, index_type, index_using, row[:Index_comment].presence)
331
- end
332
-
333
- indexes.last.columns << row[:Column_name]
334
- indexes.last.lengths.merge!(row[:Column_name] => row[:Sub_part].to_i) if row[:Sub_part]
335
- end
336
- end
337
-
338
- indexes
339
- end
340
-
341
- def new_column_from_field(table_name, field) # :nodoc:
342
- type_metadata = fetch_type_metadata(field[:Type], field[:Extra])
343
- if type_metadata.type == :datetime && field[:Default] == "CURRENT_TIMESTAMP"
344
- default, default_function = nil, field[:Default]
345
- else
346
- default, default_function = field[:Default], nil
347
- end
348
- new_column(field[:Field], default, type_metadata, field[:Null] == "YES", table_name, default_function, field[:Collation], comment: field[:Comment].presence)
349
- end
350
-
351
284
  def table_comment(table_name) # :nodoc:
352
285
  scope = quoted_scope(table_name)
353
286
 
354
- select_value(<<-SQL.strip_heredoc, "SCHEMA")
287
+ query_value(<<-SQL.strip_heredoc, "SCHEMA").presence
355
288
  SELECT table_comment
356
289
  FROM information_schema.tables
357
290
  WHERE table_schema = #{scope[:schema]}
@@ -359,14 +292,10 @@ module ActiveRecord
359
292
  SQL
360
293
  end
361
294
 
362
- def create_table(table_name, **options) #:nodoc:
363
- super(table_name, options: "ENGINE=InnoDB", **options)
364
- end
365
-
366
295
  def bulk_change_table(table_name, operations) #:nodoc:
367
296
  sqls = operations.flat_map do |command, args|
368
297
  table, arguments = args.shift, args
369
- method = :"#{command}_sql"
298
+ method = :"#{command}_for_alter"
370
299
 
371
300
  if respond_to?(method, true)
372
301
  send(method, table, *arguments)
@@ -378,6 +307,11 @@ module ActiveRecord
378
307
  execute("ALTER TABLE #{quote_table_name(table_name)} #{sqls}")
379
308
  end
380
309
 
310
+ def change_table_comment(table_name, comment) #:nodoc:
311
+ comment = "" if comment.nil?
312
+ execute("ALTER TABLE #{quote_table_name(table_name)} COMMENT #{quote(comment)}")
313
+ end
314
+
381
315
  # Renames a table.
382
316
  #
383
317
  # Example:
@@ -418,32 +352,33 @@ module ActiveRecord
418
352
 
419
353
  def change_column_default(table_name, column_name, default_or_changes) #:nodoc:
420
354
  default = extract_new_default_value(default_or_changes)
421
- column = column_for(table_name, column_name)
422
- change_column table_name, column_name, column.sql_type, default: default
355
+ change_column table_name, column_name, nil, default: default
423
356
  end
424
357
 
425
358
  def change_column_null(table_name, column_name, null, default = nil) #:nodoc:
426
- column = column_for(table_name, column_name)
427
-
428
359
  unless null || default.nil?
429
360
  execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
430
361
  end
431
362
 
432
- change_column table_name, column_name, column.sql_type, null: null
363
+ change_column table_name, column_name, nil, null: null
364
+ end
365
+
366
+ def change_column_comment(table_name, column_name, comment) #:nodoc:
367
+ change_column table_name, column_name, nil, comment: comment
433
368
  end
434
369
 
435
370
  def change_column(table_name, column_name, type, options = {}) #:nodoc:
436
- execute("ALTER TABLE #{quote_table_name(table_name)} #{change_column_sql(table_name, column_name, type, options)}")
371
+ execute("ALTER TABLE #{quote_table_name(table_name)} #{change_column_for_alter(table_name, column_name, type, options)}")
437
372
  end
438
373
 
439
374
  def rename_column(table_name, column_name, new_column_name) #:nodoc:
440
- execute("ALTER TABLE #{quote_table_name(table_name)} #{rename_column_sql(table_name, column_name, new_column_name)}")
375
+ execute("ALTER TABLE #{quote_table_name(table_name)} #{rename_column_for_alter(table_name, column_name, new_column_name)}")
441
376
  rename_column_indexes(table_name, column_name, new_column_name)
442
377
  end
443
378
 
444
379
  def add_index(table_name, column_name, options = {}) #:nodoc:
445
380
  index_name, index_type, index_columns, _, index_algorithm, index_using, comment = add_index_options(table_name, column_name, options)
446
- sql = "CREATE #{index_type} INDEX #{quote_column_name(index_name)} #{index_using} ON #{quote_table_name(table_name)} (#{index_columns}) #{index_algorithm}"
381
+ sql = "CREATE #{index_type} INDEX #{quote_column_name(index_name)} #{index_using} ON #{quote_table_name(table_name)} (#{index_columns}) #{index_algorithm}".dup
447
382
  execute add_sql_comment!(sql, comment)
448
383
  end
449
384
 
@@ -457,19 +392,20 @@ module ActiveRecord
457
392
 
458
393
  scope = quoted_scope(table_name)
459
394
 
460
- fk_info = select_all(<<-SQL.strip_heredoc, "SCHEMA")
395
+ fk_info = exec_query(<<-SQL.strip_heredoc, "SCHEMA")
461
396
  SELECT fk.referenced_table_name AS 'to_table',
462
397
  fk.referenced_column_name AS 'primary_key',
463
398
  fk.column_name AS 'column',
464
399
  fk.constraint_name AS 'name',
465
400
  rc.update_rule AS 'on_update',
466
401
  rc.delete_rule AS 'on_delete'
467
- FROM information_schema.key_column_usage fk
468
- JOIN information_schema.referential_constraints rc
402
+ FROM information_schema.referential_constraints rc
403
+ JOIN information_schema.key_column_usage fk
469
404
  USING (constraint_schema, constraint_name)
470
405
  WHERE fk.referenced_column_name IS NOT NULL
471
406
  AND fk.table_schema = #{scope[:schema]}
472
407
  AND fk.table_name = #{scope[:name]}
408
+ AND rc.constraint_schema = #{scope[:schema]}
473
409
  AND rc.table_name = #{scope[:name]}
474
410
  SQL
475
411
 
@@ -528,13 +464,13 @@ module ActiveRecord
528
464
  super
529
465
  end
530
466
 
531
- sql << " unsigned" if unsigned && type != :primary_key
467
+ sql = "#{sql} unsigned" if unsigned && type != :primary_key
532
468
  sql
533
469
  end
534
470
 
535
471
  # SHOW VARIABLES LIKE 'name'
536
472
  def show_variable(name)
537
- select_value("SELECT @@#{name}", "SCHEMA")
473
+ query_value("SELECT @@#{name}", "SCHEMA")
538
474
  rescue ActiveRecord::StatementInvalid
539
475
  nil
540
476
  end
@@ -544,7 +480,7 @@ module ActiveRecord
544
480
 
545
481
  scope = quoted_scope(table_name)
546
482
 
547
- select_values(<<-SQL.strip_heredoc, "SCHEMA")
483
+ query_values(<<-SQL.strip_heredoc, "SCHEMA")
548
484
  SELECT column_name
549
485
  FROM information_schema.key_column_usage
550
486
  WHERE constraint_name = 'PRIMARY'
@@ -590,9 +526,52 @@ module ActiveRecord
590
526
  index.using == :btree || super
591
527
  end
592
528
 
529
+ def insert_fixtures_set(fixture_set, tables_to_delete = [])
530
+ with_multi_statements do
531
+ super { discard_remaining_results }
532
+ end
533
+ end
534
+
593
535
  private
536
+ def combine_multi_statements(total_sql)
537
+ total_sql.each_with_object([]) do |sql, total_sql_chunks|
538
+ previous_packet = total_sql_chunks.last
539
+ sql << ";\n"
540
+ if max_allowed_packet_reached?(sql, previous_packet) || total_sql_chunks.empty?
541
+ total_sql_chunks << sql
542
+ else
543
+ previous_packet << sql
544
+ end
545
+ end
546
+ end
594
547
 
595
- def initialize_type_map(m)
548
+ def max_allowed_packet_reached?(current_packet, previous_packet)
549
+ if current_packet.bytesize > max_allowed_packet
550
+ raise ActiveRecordError, "Fixtures set is too large #{current_packet.bytesize}. Consider increasing the max_allowed_packet variable."
551
+ elsif previous_packet.nil?
552
+ false
553
+ else
554
+ (current_packet.bytesize + previous_packet.bytesize) > max_allowed_packet
555
+ end
556
+ end
557
+
558
+ def max_allowed_packet
559
+ bytes_margin = 2
560
+ @max_allowed_packet ||= (show_variable("max_allowed_packet") - bytes_margin)
561
+ end
562
+
563
+ def with_multi_statements
564
+ previous_flags = @config[:flags]
565
+ @config[:flags] = Mysql2::Client::MULTI_STATEMENTS
566
+ reconnect!
567
+
568
+ yield
569
+ ensure
570
+ @config[:flags] = previous_flags
571
+ reconnect!
572
+ end
573
+
574
+ def initialize_type_map(m = type_map)
596
575
  super
597
576
 
598
577
  register_class_with_limit m, %r(char)i, MysqlString
@@ -607,7 +586,6 @@ module ActiveRecord
607
586
  m.register_type %r(longblob)i, Type::Binary.new(limit: 2**32 - 1)
608
587
  m.register_type %r(^float)i, Type::Float.new(limit: 24)
609
588
  m.register_type %r(^double)i, Type::Float.new(limit: 53)
610
- m.register_type %r(^json)i, MysqlJson.new
611
589
 
612
590
  register_integer_type m, %r(^bigint)i, limit: 8
613
591
  register_integer_type m, %r(^int)i, limit: 4
@@ -650,29 +628,6 @@ module ActiveRecord
650
628
  end
651
629
  end
652
630
 
653
- def fetch_type_metadata(sql_type, extra = "")
654
- MySQL::TypeMetadata.new(super(sql_type), extra: extra)
655
- end
656
-
657
- def add_index_length(quoted_columns, **options)
658
- if length = options[:length]
659
- case length
660
- when Hash
661
- length = length.symbolize_keys
662
- quoted_columns.each { |name, column| column << "(#{length[name]})" if length[name].present? }
663
- when Integer
664
- quoted_columns.each { |name, column| column << "(#{length})" }
665
- end
666
- end
667
-
668
- quoted_columns
669
- end
670
-
671
- def add_options_for_index_columns(quoted_columns, **options)
672
- quoted_columns = add_index_length(quoted_columns, options)
673
- super
674
- end
675
-
676
631
  # See https://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html
677
632
  ER_DUP_ENTRY = 1062
678
633
  ER_NOT_NULL_VIOLATION = 1048
@@ -683,6 +638,9 @@ module ActiveRecord
683
638
  ER_LOCK_DEADLOCK = 1213
684
639
  ER_CANNOT_ADD_FOREIGN = 1215
685
640
  ER_CANNOT_CREATE_TABLE = 1005
641
+ ER_LOCK_WAIT_TIMEOUT = 1205
642
+ ER_QUERY_INTERRUPTED = 1317
643
+ ER_QUERY_TIMEOUT = 3024
686
644
 
687
645
  def translate_exception(exception, message)
688
646
  case error_number(exception)
@@ -706,19 +664,20 @@ module ActiveRecord
706
664
  NotNullViolation.new(message)
707
665
  when ER_LOCK_DEADLOCK
708
666
  Deadlocked.new(message)
667
+ when ER_LOCK_WAIT_TIMEOUT
668
+ LockWaitTimeout.new(message)
669
+ when ER_QUERY_TIMEOUT
670
+ StatementTimeout.new(message)
671
+ when ER_QUERY_INTERRUPTED
672
+ QueryCanceled.new(message)
709
673
  else
710
674
  super
711
675
  end
712
676
  end
713
677
 
714
- def add_column_sql(table_name, column_name, type, options = {})
715
- td = create_table_definition(table_name)
716
- cd = td.new_column_definition(column_name, type, options)
717
- schema_creation.accept(AddColumnDefinition.new(cd))
718
- end
719
-
720
- def change_column_sql(table_name, column_name, type, options = {})
678
+ def change_column_for_alter(table_name, column_name, type, options = {})
721
679
  column = column_for(table_name, column_name)
680
+ type ||= column.sql_type
722
681
 
723
682
  unless options.key?(:default)
724
683
  options[:default] = column.default
@@ -737,7 +696,7 @@ module ActiveRecord
737
696
  schema_creation.accept(ChangeColumnDefinition.new(cd, column.name))
738
697
  end
739
698
 
740
- def rename_column_sql(table_name, column_name, new_column_name)
699
+ def rename_column_for_alter(table_name, column_name, new_column_name)
741
700
  column = column_for(table_name, column_name)
742
701
  options = {
743
702
  default: column.default,
@@ -745,52 +704,43 @@ module ActiveRecord
745
704
  auto_increment: column.auto_increment?
746
705
  }
747
706
 
748
- current_type = select_one("SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE '#{column_name}'", "SCHEMA")["Type"]
707
+ current_type = exec_query("SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE #{quote(column_name)}", "SCHEMA").first["Type"]
749
708
  td = create_table_definition(table_name)
750
709
  cd = td.new_column_definition(new_column_name, current_type, options)
751
710
  schema_creation.accept(ChangeColumnDefinition.new(cd, column.name))
752
711
  end
753
712
 
754
- def remove_column_sql(table_name, column_name, type = nil, options = {})
755
- "DROP #{quote_column_name(column_name)}"
756
- end
757
-
758
- def remove_columns_sql(table_name, *column_names)
759
- column_names.map { |column_name| remove_column_sql(table_name, column_name) }
760
- end
761
-
762
- def add_index_sql(table_name, column_name, options = {})
713
+ def add_index_for_alter(table_name, column_name, options = {})
763
714
  index_name, index_type, index_columns, _, index_algorithm, index_using = add_index_options(table_name, column_name, options)
764
715
  index_algorithm[0, 0] = ", " if index_algorithm.present?
765
716
  "ADD #{index_type} INDEX #{quote_column_name(index_name)} #{index_using} (#{index_columns})#{index_algorithm}"
766
717
  end
767
718
 
768
- def remove_index_sql(table_name, options = {})
719
+ def remove_index_for_alter(table_name, options = {})
769
720
  index_name = index_name_for_remove(table_name, options)
770
- "DROP INDEX #{index_name}"
721
+ "DROP INDEX #{quote_column_name(index_name)}"
771
722
  end
772
723
 
773
- def add_timestamps_sql(table_name, options = {})
774
- [add_column_sql(table_name, :created_at, :datetime, options), add_column_sql(table_name, :updated_at, :datetime, options)]
724
+ def add_timestamps_for_alter(table_name, options = {})
725
+ [add_column_for_alter(table_name, :created_at, :datetime, options), add_column_for_alter(table_name, :updated_at, :datetime, options)]
775
726
  end
776
727
 
777
- def remove_timestamps_sql(table_name, options = {})
778
- [remove_column_sql(table_name, :updated_at), remove_column_sql(table_name, :created_at)]
728
+ def remove_timestamps_for_alter(table_name, options = {})
729
+ [remove_column_for_alter(table_name, :updated_at), remove_column_for_alter(table_name, :created_at)]
779
730
  end
780
731
 
781
732
  # MySQL is too stupid to create a temporary table for use subquery, so we have
782
733
  # to give it some prompting in the form of a subsubquery. Ugh!
783
734
  def subquery_for(key, select)
784
- subsubselect = select.clone
785
- subsubselect.projections = [key]
735
+ subselect = select.clone
736
+ subselect.projections = [key]
786
737
 
787
738
  # Materialize subquery by adding distinct
788
739
  # to work with MySQL 5.7.6 which sets optimizer_switch='derived_merge=on'
789
- subsubselect.distinct unless select.limit || select.offset || select.orders.any?
740
+ subselect.distinct unless select.limit || select.offset || select.orders.any?
790
741
 
791
- subselect = Arel::SelectManager.new(select.engine)
792
- subselect.project Arel.sql(key.name)
793
- subselect.from subsubselect.as("__active_record_temp")
742
+ key_name = quote_column_name(key.name)
743
+ Arel::SelectManager.new(subselect.as("__active_record_temp")).project(Arel.sql(key_name))
794
744
  end
795
745
 
796
746
  def supports_rename_index?
@@ -811,7 +761,7 @@ module ActiveRecord
811
761
  defaults = [":default", :default].to_set
812
762
 
813
763
  # Make MySQL reject illegal values rather than truncating or blanking them, see
814
- # http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_strict_all_tables
764
+ # https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_strict_all_tables
815
765
  # If the user has provided another value for sql_mode, don't replace it.
816
766
  if sql_mode = variables.delete("sql_mode")
817
767
  sql_mode = quote(sql_mode)
@@ -828,10 +778,10 @@ module ActiveRecord
828
778
  sql_mode_assignment = "@@SESSION.sql_mode = #{sql_mode}, " if sql_mode
829
779
 
830
780
  # NAMES does not have an equals sign, see
831
- # http://dev.mysql.com/doc/refman/5.7/en/set-statement.html#id944430
781
+ # https://dev.mysql.com/doc/refman/5.7/en/set-names.html
832
782
  # (trailing comma because variable_assignments will always have content)
833
783
  if @config[:encoding]
834
- encoding = "NAMES #{@config[:encoding]}"
784
+ encoding = "NAMES #{@config[:encoding]}".dup
835
785
  encoding << " COLLATE #{@config[:collation]}" if @config[:collation]
836
786
  encoding << ", "
837
787
  end
@@ -856,19 +806,12 @@ module ActiveRecord
856
806
  end
857
807
  end
858
808
 
859
- def extract_foreign_key_action(specifier) # :nodoc:
860
- case specifier
861
- when "CASCADE"; :cascade
862
- when "SET NULL"; :nullify
863
- end
864
- end
865
-
866
809
  def create_table_info(table_name) # :nodoc:
867
- select_one("SHOW CREATE TABLE #{quote_table_name(table_name)}")["Create Table"]
810
+ exec_query("SHOW CREATE TABLE #{quote_table_name(table_name)}", "SCHEMA").first["Create Table"]
868
811
  end
869
812
 
870
- def create_table_definition(*args) # :nodoc:
871
- MySQL::TableDefinition.new(*args)
813
+ def arel_visitor
814
+ Arel::Visitors::MySQL.new(self)
872
815
  end
873
816
 
874
817
  def mismatched_foreign_key(message)
@@ -914,19 +857,15 @@ module ActiveRecord
914
857
  end
915
858
  end
916
859
 
917
- class MysqlJson < Type::Internal::AbstractJson # :nodoc:
918
- def changed_in_place?(raw_old_value, new_value)
919
- # Normalization is required because MySQL JSON data format includes
920
- # the space between the elements.
921
- super(serialize(deserialize(raw_old_value)), new_value)
922
- end
860
+ def version_string
861
+ full_version.match(/^(?:5\.5\.5-)?(\d+\.\d+\.\d+)/)[1]
923
862
  end
924
863
 
925
864
  class MysqlString < Type::String # :nodoc:
926
865
  def serialize(value)
927
866
  case value
928
- when true then MySQL::Quoting::QUOTED_TRUE
929
- when false then MySQL::Quoting::QUOTED_FALSE
867
+ when true then "1"
868
+ when false then "0"
930
869
  else super
931
870
  end
932
871
  end
@@ -935,14 +874,13 @@ module ActiveRecord
935
874
 
936
875
  def cast_value(value)
937
876
  case value
938
- when true then MySQL::Quoting::QUOTED_TRUE
939
- when false then MySQL::Quoting::QUOTED_FALSE
877
+ when true then "1"
878
+ when false then "0"
940
879
  else super
941
880
  end
942
881
  end
943
882
  end
944
883
 
945
- ActiveRecord::Type.register(:json, MysqlJson, adapter: :mysql2)
946
884
  ActiveRecord::Type.register(:string, MysqlString, adapter: :mysql2)
947
885
  ActiveRecord::Type.register(:unsigned_integer, Type::UnsignedInteger, adapter: :mysql2)
948
886
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # :stopdoc:
3
5
  module ConnectionAdapters
@@ -9,11 +11,11 @@ module ActiveRecord
9
11
 
10
12
  # Instantiates a new column in the table.
11
13
  #
12
- # +name+ is the column's name, such as <tt>supplier_id</tt> in <tt>supplier_id int</tt>.
14
+ # +name+ is the column's name, such as <tt>supplier_id</tt> in <tt>supplier_id bigint</tt>.
13
15
  # +default+ is the type-casted default value, such as +new+ in <tt>sales_stage varchar(20) default 'new'</tt>.
14
16
  # +sql_type_metadata+ is various information about the type of the column
15
17
  # +null+ determines if this column allows +NULL+ values.
16
- def initialize(name, default, sql_type_metadata = nil, null = true, table_name = nil, default_function = nil, collation = nil, comment: nil)
18
+ def initialize(name, default, sql_type_metadata = nil, null = true, table_name = nil, default_function = nil, collation = nil, comment: nil, **)
17
19
  @name = name.freeze
18
20
  @table_name = table_name
19
21
  @sql_type_metadata = sql_type_metadata
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "uri"
2
4
 
3
5
  module ActiveRecord
@@ -181,13 +183,25 @@ module ActiveRecord
181
183
 
182
184
  raise(AdapterNotSpecified, "database configuration does not specify adapter") unless spec.key?(:adapter)
183
185
 
186
+ # Require the adapter itself and give useful feedback about
187
+ # 1. Missing adapter gems and
188
+ # 2. Adapter gems' missing dependencies.
184
189
  path_to_adapter = "active_record/connection_adapters/#{spec[:adapter]}_adapter"
185
190
  begin
186
191
  require path_to_adapter
187
- rescue Gem::LoadError => e
188
- raise Gem::LoadError, "Specified '#{spec[:adapter]}' for database adapter, but the gem is not loaded. Add `gem '#{e.name}'` to your Gemfile (and ensure its version is at the minimum required by ActiveRecord)."
189
192
  rescue LoadError => e
190
- raise LoadError, "Could not load '#{path_to_adapter}'. Make sure that the adapter in config/database.yml is valid. If you use an adapter other than 'mysql2', 'postgresql' or 'sqlite3' add the necessary adapter gem to the Gemfile.", e.backtrace
193
+ # We couldn't require the adapter itself. Raise an exception that
194
+ # points out config typos and missing gems.
195
+ if e.path == path_to_adapter
196
+ # We can assume that a non-builtin adapter was specified, so it's
197
+ # either misspelled or missing from Gemfile.
198
+ raise e.class, "Could not load the '#{spec[:adapter]}' Active Record adapter. Ensure that the adapter is spelled correctly in config/database.yml and that you've added the necessary adapter gem to your Gemfile.", e.backtrace
199
+
200
+ # Bubbled up from the adapter require. Prefix the exception message
201
+ # with some guidance about how to address it and reraise.
202
+ else
203
+ raise e.class, "Error loading the '#{spec[:adapter]}' Active Record adapter. Missing a gem it depends on? #{e.message}", e.backtrace
204
+ end
191
205
  end
192
206
 
193
207
  adapter_method = "#{spec[:adapter]}_connection"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module DetermineIfPreparableVisitor
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module MySQL