activerecord 4.2.9 → 5.2.8

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 (274) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +614 -1572
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +10 -11
  5. data/examples/performance.rb +32 -31
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/aggregations.rb +263 -249
  8. data/lib/active_record/association_relation.rb +11 -6
  9. data/lib/active_record/associations/alias_tracker.rb +29 -35
  10. data/lib/active_record/associations/association.rb +77 -43
  11. data/lib/active_record/associations/association_scope.rb +106 -133
  12. data/lib/active_record/associations/belongs_to_association.rb +52 -41
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
  14. data/lib/active_record/associations/builder/association.rb +29 -38
  15. data/lib/active_record/associations/builder/belongs_to.rb +77 -30
  16. data/lib/active_record/associations/builder/collection_association.rb +9 -22
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +42 -35
  18. data/lib/active_record/associations/builder/has_many.rb +6 -4
  19. data/lib/active_record/associations/builder/has_one.rb +13 -6
  20. data/lib/active_record/associations/builder/singular_association.rb +15 -11
  21. data/lib/active_record/associations/collection_association.rb +139 -280
  22. data/lib/active_record/associations/collection_proxy.rb +231 -133
  23. data/lib/active_record/associations/foreign_association.rb +3 -1
  24. data/lib/active_record/associations/has_many_association.rb +34 -89
  25. data/lib/active_record/associations/has_many_through_association.rb +49 -76
  26. data/lib/active_record/associations/has_one_association.rb +38 -24
  27. data/lib/active_record/associations/has_one_through_association.rb +18 -9
  28. data/lib/active_record/associations/join_dependency/join_association.rb +40 -89
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
  31. data/lib/active_record/associations/join_dependency.rb +133 -159
  32. data/lib/active_record/associations/preloader/association.rb +85 -120
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -74
  34. data/lib/active_record/associations/preloader.rb +81 -91
  35. data/lib/active_record/associations/singular_association.rb +27 -34
  36. data/lib/active_record/associations/through_association.rb +38 -18
  37. data/lib/active_record/associations.rb +1732 -1597
  38. data/lib/active_record/attribute_assignment.rb +58 -182
  39. data/lib/active_record/attribute_decorators.rb +39 -15
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +10 -8
  41. data/lib/active_record/attribute_methods/dirty.rb +94 -135
  42. data/lib/active_record/attribute_methods/primary_key.rb +86 -71
  43. data/lib/active_record/attribute_methods/query.rb +4 -2
  44. data/lib/active_record/attribute_methods/read.rb +45 -63
  45. data/lib/active_record/attribute_methods/serialization.rb +40 -20
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +58 -36
  47. data/lib/active_record/attribute_methods/write.rb +30 -45
  48. data/lib/active_record/attribute_methods.rb +166 -109
  49. data/lib/active_record/attributes.rb +201 -82
  50. data/lib/active_record/autosave_association.rb +94 -36
  51. data/lib/active_record/base.rb +57 -44
  52. data/lib/active_record/callbacks.rb +97 -57
  53. data/lib/active_record/coders/json.rb +3 -1
  54. data/lib/active_record/coders/yaml_column.rb +24 -12
  55. data/lib/active_record/collection_cache_key.rb +53 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +712 -290
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +10 -5
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +237 -90
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +71 -21
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +118 -52
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +67 -46
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +318 -217
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +81 -36
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +570 -228
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +138 -70
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +325 -202
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +542 -593
  69. data/lib/active_record/connection_adapters/column.rb +50 -41
  70. data/lib/active_record/connection_adapters/connection_specification.rb +147 -135
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +33 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +140 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +73 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +87 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +80 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +148 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +35 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +41 -188
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +35 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +45 -114
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -58
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +10 -6
  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 +4 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +5 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -22
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -19
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  99. data/lib/active_record/connection_adapters/postgresql/oid/{integer.rb → oid.rb} +6 -2
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +33 -11
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -34
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +55 -53
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +5 -3
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +107 -47
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +65 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +144 -90
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +462 -284
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +39 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +12 -8
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +432 -323
  117. data/lib/active_record/connection_adapters/schema_cache.rb +48 -24
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +34 -0
  119. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  120. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +67 -0
  121. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +106 -0
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +269 -308
  126. data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
  127. data/lib/active_record/connection_handling.rb +40 -27
  128. data/lib/active_record/core.rb +178 -198
  129. data/lib/active_record/counter_cache.rb +79 -36
  130. data/lib/active_record/define_callbacks.rb +22 -0
  131. data/lib/active_record/dynamic_matchers.rb +87 -105
  132. data/lib/active_record/enum.rb +135 -88
  133. data/lib/active_record/errors.rb +179 -52
  134. data/lib/active_record/explain.rb +23 -11
  135. data/lib/active_record/explain_registry.rb +4 -2
  136. data/lib/active_record/explain_subscriber.rb +10 -5
  137. data/lib/active_record/fixture_set/file.rb +35 -9
  138. data/lib/active_record/fixtures.rb +188 -132
  139. data/lib/active_record/gem_version.rb +4 -2
  140. data/lib/active_record/inheritance.rb +148 -112
  141. data/lib/active_record/integration.rb +70 -28
  142. data/lib/active_record/internal_metadata.rb +45 -0
  143. data/lib/active_record/legacy_yaml_adapter.rb +21 -3
  144. data/lib/active_record/locale/en.yml +3 -2
  145. data/lib/active_record/locking/optimistic.rb +88 -96
  146. data/lib/active_record/locking/pessimistic.rb +15 -3
  147. data/lib/active_record/log_subscriber.rb +95 -33
  148. data/lib/active_record/migration/command_recorder.rb +133 -90
  149. data/lib/active_record/migration/compatibility.rb +217 -0
  150. data/lib/active_record/migration/join_table.rb +8 -6
  151. data/lib/active_record/migration.rb +581 -282
  152. data/lib/active_record/model_schema.rb +290 -111
  153. data/lib/active_record/nested_attributes.rb +264 -222
  154. data/lib/active_record/no_touching.rb +7 -1
  155. data/lib/active_record/null_relation.rb +24 -37
  156. data/lib/active_record/persistence.rb +347 -119
  157. data/lib/active_record/query_cache.rb +13 -24
  158. data/lib/active_record/querying.rb +19 -17
  159. data/lib/active_record/railtie.rb +94 -32
  160. data/lib/active_record/railties/console_sandbox.rb +2 -0
  161. data/lib/active_record/railties/controller_runtime.rb +9 -3
  162. data/lib/active_record/railties/databases.rake +149 -156
  163. data/lib/active_record/readonly_attributes.rb +5 -4
  164. data/lib/active_record/reflection.rb +414 -267
  165. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  166. data/lib/active_record/relation/batches.rb +204 -55
  167. data/lib/active_record/relation/calculations.rb +256 -248
  168. data/lib/active_record/relation/delegation.rb +67 -60
  169. data/lib/active_record/relation/finder_methods.rb +288 -239
  170. data/lib/active_record/relation/from_clause.rb +26 -0
  171. data/lib/active_record/relation/merger.rb +86 -86
  172. data/lib/active_record/relation/predicate_builder/array_handler.rb +24 -24
  173. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  174. data/lib/active_record/relation/predicate_builder/base_handler.rb +19 -0
  175. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +20 -0
  176. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
  177. data/lib/active_record/relation/predicate_builder/range_handler.rb +42 -0
  178. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  179. data/lib/active_record/relation/predicate_builder.rb +116 -119
  180. data/lib/active_record/relation/query_attribute.rb +45 -0
  181. data/lib/active_record/relation/query_methods.rb +448 -393
  182. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  183. data/lib/active_record/relation/spawn_methods.rb +11 -13
  184. data/lib/active_record/relation/where_clause.rb +186 -0
  185. data/lib/active_record/relation/where_clause_factory.rb +34 -0
  186. data/lib/active_record/relation.rb +287 -340
  187. data/lib/active_record/result.rb +54 -36
  188. data/lib/active_record/runtime_registry.rb +6 -4
  189. data/lib/active_record/sanitization.rb +155 -124
  190. data/lib/active_record/schema.rb +30 -24
  191. data/lib/active_record/schema_dumper.rb +91 -87
  192. data/lib/active_record/schema_migration.rb +19 -16
  193. data/lib/active_record/scoping/default.rb +102 -85
  194. data/lib/active_record/scoping/named.rb +81 -32
  195. data/lib/active_record/scoping.rb +45 -26
  196. data/lib/active_record/secure_token.rb +40 -0
  197. data/lib/active_record/serialization.rb +5 -5
  198. data/lib/active_record/statement_cache.rb +45 -35
  199. data/lib/active_record/store.rb +42 -36
  200. data/lib/active_record/suppressor.rb +61 -0
  201. data/lib/active_record/table_metadata.rb +82 -0
  202. data/lib/active_record/tasks/database_tasks.rb +134 -96
  203. data/lib/active_record/tasks/mysql_database_tasks.rb +56 -100
  204. data/lib/active_record/tasks/postgresql_database_tasks.rb +83 -41
  205. data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -16
  206. data/lib/active_record/timestamp.rb +70 -38
  207. data/lib/active_record/touch_later.rb +64 -0
  208. data/lib/active_record/transactions.rb +199 -124
  209. data/lib/active_record/translation.rb +2 -0
  210. data/lib/active_record/type/adapter_specific_registry.rb +136 -0
  211. data/lib/active_record/type/date.rb +4 -45
  212. data/lib/active_record/type/date_time.rb +4 -49
  213. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  214. data/lib/active_record/type/hash_lookup_type_map.rb +5 -3
  215. data/lib/active_record/type/internal/timezone.rb +17 -0
  216. data/lib/active_record/type/json.rb +30 -0
  217. data/lib/active_record/type/serialized.rb +24 -15
  218. data/lib/active_record/type/text.rb +2 -2
  219. data/lib/active_record/type/time.rb +11 -16
  220. data/lib/active_record/type/type_map.rb +15 -17
  221. data/lib/active_record/type/unsigned_integer.rb +9 -7
  222. data/lib/active_record/type.rb +79 -23
  223. data/lib/active_record/type_caster/connection.rb +33 -0
  224. data/lib/active_record/type_caster/map.rb +23 -0
  225. data/lib/active_record/type_caster.rb +9 -0
  226. data/lib/active_record/validations/absence.rb +25 -0
  227. data/lib/active_record/validations/associated.rb +13 -4
  228. data/lib/active_record/validations/length.rb +26 -0
  229. data/lib/active_record/validations/presence.rb +14 -13
  230. data/lib/active_record/validations/uniqueness.rb +40 -41
  231. data/lib/active_record/validations.rb +38 -35
  232. data/lib/active_record/version.rb +3 -1
  233. data/lib/active_record.rb +34 -22
  234. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  235. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  236. data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -35
  237. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +8 -3
  238. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +8 -1
  239. data/lib/rails/generators/active_record/migration.rb +18 -1
  240. data/lib/rails/generators/active_record/model/model_generator.rb +18 -22
  241. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +3 -0
  242. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  243. data/lib/rails/generators/active_record.rb +7 -5
  244. metadata +72 -50
  245. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  246. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  247. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  248. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  249. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  250. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  251. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  252. data/lib/active_record/attribute.rb +0 -163
  253. data/lib/active_record/attribute_set/builder.rb +0 -106
  254. data/lib/active_record/attribute_set.rb +0 -81
  255. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  256. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  257. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  258. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  259. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  260. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  261. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  262. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  263. data/lib/active_record/type/big_integer.rb +0 -13
  264. data/lib/active_record/type/binary.rb +0 -50
  265. data/lib/active_record/type/boolean.rb +0 -31
  266. data/lib/active_record/type/decimal.rb +0 -64
  267. data/lib/active_record/type/decorator.rb +0 -14
  268. data/lib/active_record/type/float.rb +0 -19
  269. data/lib/active_record/type/integer.rb +0 -59
  270. data/lib/active_record/type/mutable.rb +0 -16
  271. data/lib/active_record/type/numeric.rb +0 -36
  272. data/lib/active_record/type/string.rb +0 -40
  273. data/lib/active_record/type/time_value.rb +0 -38
  274. data/lib/active_record/type/value.rb +0 -110
@@ -1,46 +1,37 @@
1
- require 'set'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecord
4
4
  # :stopdoc:
5
5
  module ConnectionAdapters
6
6
  # An abstract definition of a column in a table.
7
7
  class Column
8
- TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON'].to_set
9
- FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE', 'off', 'OFF'].to_set
8
+ attr_reader :name, :default, :sql_type_metadata, :null, :table_name, :default_function, :collation, :comment
10
9
 
11
- module Format
12
- ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/
13
- ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/
14
- end
15
-
16
- attr_reader :name, :cast_type, :null, :sql_type, :default, :default_function
17
-
18
- delegate :type, :precision, :scale, :limit, :klass, :accessor,
19
- :text?, :number?, :binary?, :changed?,
20
- :type_cast_from_user, :type_cast_from_database, :type_cast_for_database,
21
- :type_cast_for_schema,
22
- to: :cast_type
10
+ delegate :precision, :scale, :limit, :type, :sql_type, to: :sql_type_metadata, allow_nil: true
23
11
 
24
12
  # Instantiates a new column in the table.
25
13
  #
26
- # +name+ is the column's name, such as <tt>supplier_id</tt> in <tt>supplier_id int(11)</tt>.
14
+ # +name+ is the column's name, such as <tt>supplier_id</tt> in <tt>supplier_id bigint</tt>.
27
15
  # +default+ is the type-casted default value, such as +new+ in <tt>sales_stage varchar(20) default 'new'</tt>.
28
- # +cast_type+ is the object used for type casting and type information.
29
- # +sql_type+ is used to extract the column's length, if necessary. For example +60+ in
30
- # <tt>company_name varchar(60)</tt>.
31
- # It will be mapped to one of the standard Rails SQL types in the <tt>type</tt> attribute.
16
+ # +sql_type_metadata+ is various information about the type of the column
32
17
  # +null+ determines if this column allows +NULL+ values.
33
- def initialize(name, default, cast_type, sql_type = nil, null = true)
34
- @name = name.freeze
35
- @cast_type = cast_type
36
- @sql_type = sql_type
37
- @null = null
38
- @default = default
39
- @default_function = nil
18
+ def initialize(name, default, sql_type_metadata = nil, null = true, table_name = nil, default_function = nil, collation = nil, comment: nil, **)
19
+ @name = name.freeze
20
+ @table_name = table_name
21
+ @sql_type_metadata = sql_type_metadata
22
+ @null = null
23
+ @default = default
24
+ @default_function = default_function
25
+ @collation = collation
26
+ @comment = comment
40
27
  end
41
28
 
42
29
  def has_default?
43
- !default.nil?
30
+ !default.nil? || default_function
31
+ end
32
+
33
+ def bigint?
34
+ /\Abigint\b/.match?(sql_type)
44
35
  end
45
36
 
46
37
  # Returns the human name of the column name.
@@ -51,19 +42,31 @@ module ActiveRecord
51
42
  Base.human_attribute_name(@name)
52
43
  end
53
44
 
54
- def with_type(type)
55
- dup.tap do |clone|
56
- clone.instance_variable_set('@cast_type', type)
57
- end
45
+ def init_with(coder)
46
+ @name = coder["name"]
47
+ @table_name = coder["table_name"]
48
+ @sql_type_metadata = coder["sql_type_metadata"]
49
+ @null = coder["null"]
50
+ @default = coder["default"]
51
+ @default_function = coder["default_function"]
52
+ @collation = coder["collation"]
53
+ @comment = coder["comment"]
54
+ end
55
+
56
+ def encode_with(coder)
57
+ coder["name"] = @name
58
+ coder["table_name"] = @table_name
59
+ coder["sql_type_metadata"] = @sql_type_metadata
60
+ coder["null"] = @null
61
+ coder["default"] = @default
62
+ coder["default_function"] = @default_function
63
+ coder["collation"] = @collation
64
+ coder["comment"] = @comment
58
65
  end
59
66
 
60
67
  def ==(other)
61
- other.name == name &&
62
- other.default == default &&
63
- other.cast_type == cast_type &&
64
- other.sql_type == sql_type &&
65
- other.null == null &&
66
- other.default_function == default_function
68
+ other.is_a?(Column) &&
69
+ attributes_for_hash == other.attributes_for_hash
67
70
  end
68
71
  alias :eql? :==
69
72
 
@@ -71,10 +74,16 @@ module ActiveRecord
71
74
  attributes_for_hash.hash
72
75
  end
73
76
 
74
- private
77
+ protected
78
+
79
+ def attributes_for_hash
80
+ [self.class, name, default, sql_type_metadata, null, table_name, default_function, collation]
81
+ end
82
+ end
75
83
 
76
- def attributes_for_hash
77
- [self.class, name, default, cast_type, sql_type, null, default_function]
84
+ class NullColumn < Column
85
+ def initialize(name)
86
+ super(name, nil)
78
87
  end
79
88
  end
80
89
  end
@@ -1,22 +1,26 @@
1
- require 'uri'
2
- require 'active_support/core_ext/string/filters'
1
+ # frozen_string_literal: true
2
+
3
+ require "uri"
3
4
 
4
5
  module ActiveRecord
5
6
  module ConnectionAdapters
6
7
  class ConnectionSpecification #:nodoc:
7
- attr_reader :config, :adapter_method
8
+ attr_reader :name, :config, :adapter_method
8
9
 
9
- def initialize(config, adapter_method)
10
- @config, @adapter_method = config, adapter_method
10
+ def initialize(name, config, adapter_method)
11
+ @name, @config, @adapter_method = name, config, adapter_method
11
12
  end
12
13
 
13
14
  def initialize_dup(original)
14
15
  @config = original.config.dup
15
16
  end
16
17
 
18
+ def to_hash
19
+ @config.merge(name: @name)
20
+ end
21
+
17
22
  # Expands a connection string into a hash.
18
23
  class ConnectionUrlResolver # :nodoc:
19
-
20
24
  # == Example
21
25
  #
22
26
  # url = "postgresql://foo:bar@localhost:9000/foo_test?pool=5&timeout=3000"
@@ -34,11 +38,11 @@ module ActiveRecord
34
38
  def initialize(url)
35
39
  raise "Database URL cannot be empty" if url.blank?
36
40
  @uri = uri_parser.parse(url)
37
- @adapter = @uri.scheme.tr('-', '_')
41
+ @adapter = @uri.scheme && @uri.scheme.tr("-", "_")
38
42
  @adapter = "postgresql" if @adapter == "postgres"
39
43
 
40
44
  if @uri.opaque
41
- @uri.opaque, @query = @uri.opaque.split('?', 2)
45
+ @uri.opaque, @query = @uri.opaque.split("?", 2)
42
46
  else
43
47
  @query = @uri.query
44
48
  end
@@ -46,65 +50,65 @@ module ActiveRecord
46
50
 
47
51
  # Converts the given URL to a full connection hash.
48
52
  def to_hash
49
- config = raw_config.reject { |_,value| value.blank? }
50
- config.map { |key,value| config[key] = uri_parser.unescape(value) if value.is_a? String }
53
+ config = raw_config.reject { |_, value| value.blank? }
54
+ config.map { |key, value| config[key] = uri_parser.unescape(value) if value.is_a? String }
51
55
  config
52
56
  end
53
57
 
54
58
  private
55
59
 
56
- def uri
57
- @uri
58
- end
60
+ def uri
61
+ @uri
62
+ end
59
63
 
60
- def uri_parser
61
- @uri_parser ||= URI::Parser.new
62
- end
64
+ def uri_parser
65
+ @uri_parser ||= URI::Parser.new
66
+ end
63
67
 
64
- # Converts the query parameters of the URI into a hash.
65
- #
66
- # "localhost?pool=5&reaping_frequency=2"
67
- # # => { "pool" => "5", "reaping_frequency" => "2" }
68
- #
69
- # returns empty hash if no query present.
70
- #
71
- # "localhost"
72
- # # => {}
73
- def query_hash
74
- Hash[(@query || '').split("&").map { |pair| pair.split("=") }]
75
- end
68
+ # Converts the query parameters of the URI into a hash.
69
+ #
70
+ # "localhost?pool=5&reaping_frequency=2"
71
+ # # => { "pool" => "5", "reaping_frequency" => "2" }
72
+ #
73
+ # returns empty hash if no query present.
74
+ #
75
+ # "localhost"
76
+ # # => {}
77
+ def query_hash
78
+ Hash[(@query || "").split("&").map { |pair| pair.split("=") }]
79
+ end
76
80
 
77
- def raw_config
78
- if uri.opaque
79
- query_hash.merge({
80
- "adapter" => @adapter,
81
- "database" => uri.opaque })
82
- else
83
- query_hash.merge({
84
- "adapter" => @adapter,
85
- "username" => uri.user,
86
- "password" => uri.password,
87
- "port" => uri.port,
88
- "database" => database_from_path,
89
- "host" => uri.hostname })
81
+ def raw_config
82
+ if uri.opaque
83
+ query_hash.merge(
84
+ "adapter" => @adapter,
85
+ "database" => uri.opaque)
86
+ else
87
+ query_hash.merge(
88
+ "adapter" => @adapter,
89
+ "username" => uri.user,
90
+ "password" => uri.password,
91
+ "port" => uri.port,
92
+ "database" => database_from_path,
93
+ "host" => uri.hostname)
94
+ end
90
95
  end
91
- end
92
96
 
93
- # Returns name of the database.
94
- def database_from_path
95
- if @adapter == 'sqlite3'
96
- # 'sqlite3:/foo' is absolute, because that makes sense. The
97
- # corresponding relative version, 'sqlite3:foo', is handled
98
- # elsewhere, as an "opaque".
97
+ # Returns name of the database.
98
+ def database_from_path
99
+ if @adapter == "sqlite3"
100
+ # 'sqlite3:/foo' is absolute, because that makes sense. The
101
+ # corresponding relative version, 'sqlite3:foo', is handled
102
+ # elsewhere, as an "opaque".
99
103
 
100
- uri.path
101
- else
102
- # Only SQLite uses a filename as the "database" name; for
103
- # anything else, a leading slash would be silly.
104
+ uri.path
105
+ else
106
+ # Only SQLite uses a filename as the "database" name; for
107
+ # anything else, a leading slash would be silly.
104
108
 
105
- uri.path.sub(%r{^/}, "")
109
+ uri.path.sub(%r{^/}, "")
110
+ end
106
111
  end
107
- end
108
112
  end
109
113
 
110
114
  ##
@@ -147,9 +151,18 @@ module ActiveRecord
147
151
  # Expands each key in @configurations hash into fully resolved hash
148
152
  def resolve_all
149
153
  config = configurations.dup
154
+
155
+ if env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
156
+ env_config = config[env] if config[env].is_a?(Hash) && !(config[env].key?("adapter") || config[env].key?("url"))
157
+ end
158
+
159
+ config.reject! { |k, v| v.is_a?(Hash) && !(v.key?("adapter") || v.key?("url")) }
160
+ config.merge! env_config if env_config
161
+
150
162
  config.each do |key, value|
151
163
  config[key] = resolve(value) if value
152
164
  end
165
+
153
166
  config
154
167
  end
155
168
 
@@ -170,105 +183,104 @@ module ActiveRecord
170
183
 
171
184
  raise(AdapterNotSpecified, "database configuration does not specify adapter") unless spec.key?(:adapter)
172
185
 
186
+ # Require the adapter itself and give useful feedback about
187
+ # 1. Missing adapter gems and
188
+ # 2. Adapter gems' missing dependencies.
173
189
  path_to_adapter = "active_record/connection_adapters/#{spec[:adapter]}_adapter"
174
190
  begin
175
191
  require path_to_adapter
176
- rescue Gem::LoadError => e
177
- 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)."
178
192
  rescue LoadError => e
179
- 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 'mysql', '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 LoadError, "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 LoadError, "Error loading the '#{spec[:adapter]}' Active Record adapter. Missing a gem it depends on? #{e.message}", e.backtrace
204
+ end
180
205
  end
181
206
 
182
207
  adapter_method = "#{spec[:adapter]}_connection"
183
- ConnectionSpecification.new(spec, adapter_method)
208
+
209
+ unless ActiveRecord::Base.respond_to?(adapter_method)
210
+ raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
211
+ end
212
+
213
+ ConnectionSpecification.new(spec.delete(:name) || "primary", spec, adapter_method)
184
214
  end
185
215
 
186
216
  private
187
217
 
188
- # Returns fully resolved connection, accepts hash, string or symbol.
189
- # Always returns a hash.
190
- #
191
- # == Examples
192
- #
193
- # Symbol representing current environment.
194
- #
195
- # Resolver.new("production" => {}).resolve_connection(:production)
196
- # # => {}
197
- #
198
- # One layer deep hash of connection values.
199
- #
200
- # Resolver.new({}).resolve_connection("adapter" => "sqlite3")
201
- # # => { "adapter" => "sqlite3" }
202
- #
203
- # Connection URL.
204
- #
205
- # Resolver.new({}).resolve_connection("postgresql://localhost/foo")
206
- # # => { "host" => "localhost", "database" => "foo", "adapter" => "postgresql" }
207
- #
208
- def resolve_connection(spec)
209
- case spec
210
- when Symbol
211
- resolve_symbol_connection spec
212
- when String
213
- resolve_string_connection spec
214
- when Hash
215
- resolve_hash_connection spec
218
+ # Returns fully resolved connection, accepts hash, string or symbol.
219
+ # Always returns a hash.
220
+ #
221
+ # == Examples
222
+ #
223
+ # Symbol representing current environment.
224
+ #
225
+ # Resolver.new("production" => {}).resolve_connection(:production)
226
+ # # => {}
227
+ #
228
+ # One layer deep hash of connection values.
229
+ #
230
+ # Resolver.new({}).resolve_connection("adapter" => "sqlite3")
231
+ # # => { "adapter" => "sqlite3" }
232
+ #
233
+ # Connection URL.
234
+ #
235
+ # Resolver.new({}).resolve_connection("postgresql://localhost/foo")
236
+ # # => { "host" => "localhost", "database" => "foo", "adapter" => "postgresql" }
237
+ #
238
+ def resolve_connection(spec)
239
+ case spec
240
+ when Symbol
241
+ resolve_symbol_connection spec
242
+ when String
243
+ resolve_url_connection spec
244
+ when Hash
245
+ resolve_hash_connection spec
246
+ end
216
247
  end
217
- end
218
248
 
219
- def resolve_string_connection(spec)
220
- # Rails has historically accepted a string to mean either
221
- # an environment key or a URL spec, so we have deprecated
222
- # this ambiguous behaviour and in the future this function
223
- # can be removed in favor of resolve_url_connection.
224
- if configurations.key?(spec) || spec !~ /:/
225
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
226
- Passing a string to ActiveRecord::Base.establish_connection for a
227
- configuration lookup is deprecated, please pass a symbol
228
- (#{spec.to_sym.inspect}) instead.
229
- MSG
230
-
231
- resolve_symbol_connection(spec)
232
- else
233
- resolve_url_connection(spec)
249
+ # Takes the environment such as +:production+ or +:development+.
250
+ # This requires that the @configurations was initialized with a key that
251
+ # matches.
252
+ #
253
+ # Resolver.new("production" => {}).resolve_symbol_connection(:production)
254
+ # # => {}
255
+ #
256
+ def resolve_symbol_connection(spec)
257
+ if config = configurations[spec.to_s]
258
+ resolve_connection(config).merge("name" => spec.to_s)
259
+ else
260
+ raise(AdapterNotSpecified, "'#{spec}' database is not configured. Available: #{configurations.keys.inspect}")
261
+ end
234
262
  end
235
- end
236
263
 
237
- # Takes the environment such as +:production+ or +:development+.
238
- # This requires that the @configurations was initialized with a key that
239
- # matches.
240
- #
241
- # Resolver.new("production" => {}).resolve_symbol_connection(:production)
242
- # # => {}
243
- #
244
- def resolve_symbol_connection(spec)
245
- if config = configurations[spec.to_s]
246
- resolve_connection(config)
247
- else
248
- raise(AdapterNotSpecified, "'#{spec}' database is not configured. Available: #{configurations.keys.inspect}")
264
+ # Accepts a hash. Expands the "url" key that contains a
265
+ # URL database connection to a full connection
266
+ # hash and merges with the rest of the hash.
267
+ # Connection details inside of the "url" key win any merge conflicts
268
+ def resolve_hash_connection(spec)
269
+ if spec["url"] && spec["url"] !~ /^jdbc:/
270
+ connection_hash = resolve_url_connection(spec.delete("url"))
271
+ spec.merge!(connection_hash)
272
+ end
273
+ spec
249
274
  end
250
- end
251
275
 
252
- # Accepts a hash. Expands the "url" key that contains a
253
- # URL database connection to a full connection
254
- # hash and merges with the rest of the hash.
255
- # Connection details inside of the "url" key win any merge conflicts
256
- def resolve_hash_connection(spec)
257
- if spec["url"] && spec["url"] !~ /^jdbc:/
258
- connection_hash = resolve_url_connection(spec.delete("url"))
259
- spec.merge!(connection_hash)
276
+ # Takes a connection URL.
277
+ #
278
+ # Resolver.new({}).resolve_url_connection("postgresql://localhost/foo")
279
+ # # => { "host" => "localhost", "database" => "foo", "adapter" => "postgresql" }
280
+ #
281
+ def resolve_url_connection(url)
282
+ ConnectionUrlResolver.new(url).to_hash
260
283
  end
261
- spec
262
- end
263
-
264
- # Takes a connection URL.
265
- #
266
- # Resolver.new({}).resolve_url_connection("postgresql://localhost/foo")
267
- # # => { "host" => "localhost", "database" => "foo", "adapter" => "postgresql" }
268
- #
269
- def resolve_url_connection(url)
270
- ConnectionUrlResolver.new(url).to_hash
271
- end
272
284
  end
273
285
  end
274
286
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ module DetermineIfPreparableVisitor
6
+ attr_accessor :preparable
7
+
8
+ def accept(*)
9
+ @preparable = true
10
+ super
11
+ end
12
+
13
+ def visit_Arel_Nodes_In(o, collector)
14
+ @preparable = false
15
+
16
+ if Array === o.right && !o.right.empty?
17
+ o.right.delete_if do |bind|
18
+ if Arel::Nodes::BindParam === bind && Relation::QueryAttribute === bind.value
19
+ !bind.value.boundable?
20
+ end
21
+ end
22
+ end
23
+
24
+ super
25
+ end
26
+
27
+ def visit_Arel_Nodes_SqlLiteral(*)
28
+ @preparable = false
29
+ super
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ module MySQL
6
+ class Column < ConnectionAdapters::Column # :nodoc:
7
+ delegate :extra, to: :sql_type_metadata, allow_nil: true
8
+
9
+ def unsigned?
10
+ /\bunsigned(?: zerofill)?\z/.match?(sql_type)
11
+ end
12
+
13
+ def case_sensitive?
14
+ collation && !/_ci\z/.match?(collation)
15
+ end
16
+
17
+ def auto_increment?
18
+ extra == "auto_increment"
19
+ end
20
+
21
+ def virtual?
22
+ /\b(?:VIRTUAL|STORED|PERSISTENT)\b/.match?(extra)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end