activerecord 5.1.7 → 5.2.0

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 (261) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +372 -765
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -5
  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 +19 -27
  10. data/lib/active_record/associations/association.rb +16 -27
  11. data/lib/active_record/associations/association_scope.rb +38 -50
  12. data/lib/active_record/associations/belongs_to_association.rb +20 -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 +4 -5
  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 +43 -35
  22. data/lib/active_record/associations/collection_proxy.rb +12 -15
  23. data/lib/active_record/associations/foreign_association.rb +2 -0
  24. data/lib/active_record/associations/has_many_association.rb +3 -1
  25. data/lib/active_record/associations/has_many_through_association.rb +7 -18
  26. data/lib/active_record/associations/has_one_association.rb +4 -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 -56
  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 +23 -43
  32. data/lib/active_record/associations/preloader/association.rb +45 -61
  33. data/lib/active_record/associations/preloader/through_association.rb +71 -79
  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 +25 -10
  37. data/lib/active_record/associations.rb +31 -54
  38. data/lib/active_record/attribute_assignment.rb +2 -5
  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 +25 -214
  42. data/lib/active_record/attribute_methods/primary_key.rb +7 -6
  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 +21 -9
  48. data/lib/active_record/attribute_methods.rb +65 -24
  49. data/lib/active_record/attributes.rb +6 -5
  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 -10
  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 +11 -7
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +111 -38
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +157 -29
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +7 -2
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +13 -32
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +14 -5
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +57 -2
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +158 -78
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +81 -96
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +111 -183
  69. data/lib/active_record/connection_adapters/column.rb +3 -1
  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 -2
  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 -30
  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 +2 -0
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -0
  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 +3 -11
  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.rb +23 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +2 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
  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 -1
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
  99. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +4 -6
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +18 -0
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +246 -110
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -0
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +58 -82
  117. data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
  119. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
  120. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +18 -1
  121. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
  123. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
  124. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +71 -1
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +80 -90
  126. data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
  127. data/lib/active_record/connection_handling.rb +4 -2
  128. data/lib/active_record/core.rb +39 -60
  129. data/lib/active_record/counter_cache.rb +15 -12
  130. data/lib/active_record/define_callbacks.rb +5 -3
  131. data/lib/active_record/dynamic_matchers.rb +9 -9
  132. data/lib/active_record/enum.rb +17 -13
  133. data/lib/active_record/errors.rb +54 -21
  134. data/lib/active_record/explain.rb +3 -1
  135. data/lib/active_record/explain_registry.rb +2 -0
  136. data/lib/active_record/explain_subscriber.rb +2 -0
  137. data/lib/active_record/fixture_set/file.rb +2 -0
  138. data/lib/active_record/fixtures.rb +67 -60
  139. data/lib/active_record/gem_version.rb +4 -2
  140. data/lib/active_record/inheritance.rb +49 -19
  141. data/lib/active_record/integration.rb +58 -19
  142. data/lib/active_record/internal_metadata.rb +2 -0
  143. data/lib/active_record/legacy_yaml_adapter.rb +3 -1
  144. data/lib/active_record/locking/optimistic.rb +14 -17
  145. data/lib/active_record/locking/pessimistic.rb +9 -6
  146. data/lib/active_record/log_subscriber.rb +43 -0
  147. data/lib/active_record/migration/command_recorder.rb +11 -9
  148. data/lib/active_record/migration/compatibility.rb +40 -2
  149. data/lib/active_record/migration/join_table.rb +2 -0
  150. data/lib/active_record/migration.rb +189 -139
  151. data/lib/active_record/model_schema.rb +16 -21
  152. data/lib/active_record/nested_attributes.rb +18 -6
  153. data/lib/active_record/no_touching.rb +3 -1
  154. data/lib/active_record/null_relation.rb +2 -0
  155. data/lib/active_record/persistence.rb +166 -16
  156. data/lib/active_record/query_cache.rb +11 -6
  157. data/lib/active_record/querying.rb +3 -1
  158. data/lib/active_record/railtie.rb +61 -3
  159. data/lib/active_record/railties/console_sandbox.rb +2 -0
  160. data/lib/active_record/railties/controller_runtime.rb +2 -0
  161. data/lib/active_record/railties/databases.rake +46 -36
  162. data/lib/active_record/readonly_attributes.rb +3 -2
  163. data/lib/active_record/reflection.rb +110 -192
  164. data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
  165. data/lib/active_record/relation/batches.rb +20 -5
  166. data/lib/active_record/relation/calculations.rb +30 -8
  167. data/lib/active_record/relation/delegation.rb +15 -27
  168. data/lib/active_record/relation/finder_methods.rb +75 -78
  169. data/lib/active_record/relation/from_clause.rb +2 -8
  170. data/lib/active_record/relation/merger.rb +51 -20
  171. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
  172. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  173. data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
  174. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
  175. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
  176. data/lib/active_record/relation/predicate_builder/range_handler.rb +26 -9
  177. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  178. data/lib/active_record/relation/predicate_builder.rb +53 -78
  179. data/lib/active_record/relation/query_attribute.rb +26 -2
  180. data/lib/active_record/relation/query_methods.rb +89 -88
  181. data/lib/active_record/relation/record_fetch_warning.rb +2 -0
  182. data/lib/active_record/relation/spawn_methods.rb +3 -1
  183. data/lib/active_record/relation/where_clause.rb +65 -68
  184. data/lib/active_record/relation/where_clause_factory.rb +5 -48
  185. data/lib/active_record/relation.rb +95 -208
  186. data/lib/active_record/result.rb +2 -0
  187. data/lib/active_record/runtime_registry.rb +2 -0
  188. data/lib/active_record/sanitization.rb +129 -121
  189. data/lib/active_record/schema.rb +4 -2
  190. data/lib/active_record/schema_dumper.rb +36 -26
  191. data/lib/active_record/schema_migration.rb +2 -0
  192. data/lib/active_record/scoping/default.rb +6 -7
  193. data/lib/active_record/scoping/named.rb +21 -7
  194. data/lib/active_record/scoping.rb +9 -8
  195. data/lib/active_record/secure_token.rb +2 -0
  196. data/lib/active_record/serialization.rb +2 -0
  197. data/lib/active_record/statement_cache.rb +22 -12
  198. data/lib/active_record/store.rb +3 -1
  199. data/lib/active_record/suppressor.rb +2 -0
  200. data/lib/active_record/table_metadata.rb +12 -3
  201. data/lib/active_record/tasks/database_tasks.rb +26 -15
  202. data/lib/active_record/tasks/mysql_database_tasks.rb +9 -48
  203. data/lib/active_record/tasks/postgresql_database_tasks.rb +10 -2
  204. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
  205. data/lib/active_record/timestamp.rb +5 -12
  206. data/lib/active_record/touch_later.rb +2 -0
  207. data/lib/active_record/transactions.rb +9 -7
  208. data/lib/active_record/translation.rb +2 -0
  209. data/lib/active_record/type/adapter_specific_registry.rb +2 -0
  210. data/lib/active_record/type/date.rb +2 -0
  211. data/lib/active_record/type/date_time.rb +2 -0
  212. data/lib/active_record/type/decimal_without_scale.rb +2 -0
  213. data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
  214. data/lib/active_record/type/internal/timezone.rb +2 -0
  215. data/lib/active_record/type/json.rb +30 -0
  216. data/lib/active_record/type/serialized.rb +2 -4
  217. data/lib/active_record/type/text.rb +2 -0
  218. data/lib/active_record/type/time.rb +2 -0
  219. data/lib/active_record/type/type_map.rb +2 -0
  220. data/lib/active_record/type/unsigned_integer.rb +2 -0
  221. data/lib/active_record/type.rb +4 -1
  222. data/lib/active_record/type_caster/connection.rb +2 -0
  223. data/lib/active_record/type_caster/map.rb +3 -1
  224. data/lib/active_record/type_caster.rb +2 -0
  225. data/lib/active_record/validations/absence.rb +2 -0
  226. data/lib/active_record/validations/associated.rb +2 -0
  227. data/lib/active_record/validations/length.rb +2 -0
  228. data/lib/active_record/validations/presence.rb +2 -0
  229. data/lib/active_record/validations/uniqueness.rb +35 -5
  230. data/lib/active_record/validations.rb +2 -0
  231. data/lib/active_record/version.rb +2 -0
  232. data/lib/active_record.rb +11 -4
  233. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  234. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  235. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
  236. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
  237. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
  238. data/lib/rails/generators/active_record/migration.rb +2 -0
  239. data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
  240. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
  241. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  242. data/lib/rails/generators/active_record.rb +3 -1
  243. metadata +24 -36
  244. data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
  245. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  246. data/lib/active_record/associations/preloader/has_many.rb +0 -15
  247. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  248. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  249. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  250. data/lib/active_record/associations/preloader/singular_association.rb +0 -18
  251. data/lib/active_record/attribute/user_provided_default.rb +0 -30
  252. data/lib/active_record/attribute.rb +0 -240
  253. data/lib/active_record/attribute_mutation_tracker.rb +0 -122
  254. data/lib/active_record/attribute_set/builder.rb +0 -126
  255. data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
  256. data/lib/active_record/attribute_set.rb +0 -113
  257. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
  258. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  259. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  260. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
  261. data/lib/active_record/type/internal/abstract_json.rb +0 -37
@@ -1,9 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module MySQL
4
6
  module Quoting # :nodoc:
5
- QUOTED_TRUE, QUOTED_FALSE = "1".freeze, "0".freeze
6
-
7
7
  def quote_column_name(name)
8
8
  @quoted_column_names[name] ||= "`#{super.gsub('`', '``')}`".freeze
9
9
  end
@@ -12,18 +12,10 @@ module ActiveRecord
12
12
  @quoted_table_names[name] ||= super.gsub(".", "`.`").freeze
13
13
  end
14
14
 
15
- def quoted_true
16
- QUOTED_TRUE
17
- end
18
-
19
15
  def unquoted_true
20
16
  1
21
17
  end
22
18
 
23
- def quoted_false
24
- QUOTED_FALSE
25
- end
26
-
27
19
  def unquoted_false
28
20
  0
29
21
  end
@@ -39,6 +31,13 @@ module ActiveRecord
39
31
  def quoted_binary(value)
40
32
  "x'#{value.hex}'"
41
33
  end
34
+
35
+ def _type_cast(value)
36
+ case value
37
+ when Date, Time then value
38
+ else super
39
+ end
40
+ end
42
41
  end
43
42
  end
44
43
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module MySQL
@@ -16,7 +18,7 @@ module ActiveRecord
16
18
  end
17
19
 
18
20
  def visit_ChangeColumnDefinition(o)
19
- change_column_sql = "CHANGE #{quote_column_name(o.name)} #{accept(o.column)}"
21
+ change_column_sql = "CHANGE #{quote_column_name(o.name)} #{accept(o.column)}".dup
20
22
  add_column_position!(change_column_sql, column_options(o.column))
21
23
  end
22
24
 
@@ -28,7 +30,7 @@ module ActiveRecord
28
30
  # By default, TIMESTAMP columns are NOT NULL, cannot contain NULL values,
29
31
  # and assigning NULL assigns the current timestamp. To permit a TIMESTAMP
30
32
  # column to contain NULL, explicitly declare it with the NULL attribute.
31
- # See http://dev.mysql.com/doc/refman/5.7/en/timestamp-initialization.html
33
+ # See https://dev.mysql.com/doc/refman/5.7/en/timestamp-initialization.html
32
34
  if /\Atimestamp\b/.match?(options[:column].sql_type) && !options[:primary_key]
33
35
  sql << " NULL" unless options[:null] == false || options_include_default?(options)
34
36
  end
@@ -63,7 +65,7 @@ module ActiveRecord
63
65
 
64
66
  def index_in_create(table_name, column_name, options)
65
67
  index_name, index_type, index_columns, _, _, index_using, comment = @conn.add_index_options(table_name, column_name, options)
66
- add_sql_comment!("#{index_type} INDEX #{quote_column_name(index_name)} #{index_using} (#{index_columns})", comment)
68
+ add_sql_comment!("#{index_type} INDEX #{quote_column_name(index_name)} #{index_using} (#{index_columns})".dup, comment)
67
69
  end
68
70
  end
69
71
  end
@@ -1,12 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module MySQL
4
6
  module ColumnMethods
5
- def primary_key(name, type = :primary_key, **options)
6
- options[:auto_increment] = true if [:integer, :bigint].include?(type) && !options.key?(:default)
7
- super
8
- end
9
-
10
7
  def blob(*args, **options)
11
8
  args.each { |name| column(name, :blob, options) }
12
9
  end
@@ -35,10 +32,6 @@ module ActiveRecord
35
32
  args.each { |name| column(name, :longtext, options) }
36
33
  end
37
34
 
38
- def json(*args, **options)
39
- args.each { |name| column(name, :json, options) }
40
- end
41
-
42
35
  def unsigned_integer(*args, **options)
43
36
  args.each { |name| column(name, :unsigned_integer, options) }
44
37
  end
@@ -66,7 +59,6 @@ module ActiveRecord
66
59
  when :primary_key
67
60
  type = :integer
68
61
  options[:limit] ||= 8
69
- options[:auto_increment] = true
70
62
  options[:primary_key] = true
71
63
  when /\Aunsigned_(?<type>.+)\z/
72
64
  type = $~[:type].to_sym
@@ -80,6 +72,11 @@ module ActiveRecord
80
72
  def aliased_types(name, fallback)
81
73
  fallback
82
74
  end
75
+
76
+ def integer_like_primary_key_type(type, options)
77
+ options[:auto_increment] = true
78
+ type
79
+ end
83
80
  end
84
81
 
85
82
  class Table < ActiveRecord::ConnectionAdapters::Table
@@ -1,32 +1,29 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module MySQL
4
- module ColumnDumper # :nodoc:
5
- def prepare_column_options(column)
6
- spec = super
7
- spec[:unsigned] = "true" if column.unsigned?
8
- spec[:auto_increment] = "true" if column.auto_increment?
9
-
10
- if supports_virtual_columns? && column.virtual?
11
- spec[:as] = extract_expression_for_virtual_column(column)
12
- spec[:stored] = "true" if /\b(?:STORED|PERSISTENT)\b/.match?(column.extra)
13
- spec = { type: schema_type(column).inspect }.merge!(spec)
14
- end
15
-
16
- spec
17
- end
6
+ class SchemaDumper < ConnectionAdapters::SchemaDumper # :nodoc:
7
+ private
8
+ def prepare_column_options(column)
9
+ spec = super
10
+ spec[:unsigned] = "true" if column.unsigned?
11
+ spec[:auto_increment] = "true" if column.auto_increment?
18
12
 
19
- def column_spec_for_primary_key(column)
20
- spec = super
21
- spec.delete(:auto_increment) if column.type == :integer && column.auto_increment?
22
- spec
23
- end
13
+ if @connection.supports_virtual_columns? && column.virtual?
14
+ spec[:as] = extract_expression_for_virtual_column(column)
15
+ spec[:stored] = "true" if /\b(?:STORED|PERSISTENT)\b/.match?(column.extra)
16
+ spec = { type: schema_type(column).inspect }.merge!(spec)
17
+ end
24
18
 
25
- def migration_keys
26
- super + [:unsigned]
27
- end
19
+ spec
20
+ end
28
21
 
29
- private
22
+ def column_spec_for_primary_key(column)
23
+ spec = super
24
+ spec.delete(:auto_increment) if column.type == :integer && column.auto_increment?
25
+ spec
26
+ end
30
27
 
31
28
  def default_primary_key?(column)
32
29
  super && column.auto_increment? && !column.unsigned?
@@ -54,24 +51,27 @@ module ActiveRecord
54
51
  def schema_collation(column)
55
52
  if column.collation && table_name = column.table_name
56
53
  @table_collation_cache ||= {}
57
- @table_collation_cache[table_name] ||= exec_query("SHOW TABLE STATUS LIKE #{quote(table_name)}", "SCHEMA").first["Collation"]
54
+ @table_collation_cache[table_name] ||=
55
+ @connection.exec_query("SHOW TABLE STATUS LIKE #{@connection.quote(table_name)}", "SCHEMA").first["Collation"]
58
56
  column.collation.inspect if column.collation != @table_collation_cache[table_name]
59
57
  end
60
58
  end
61
59
 
62
60
  def extract_expression_for_virtual_column(column)
63
- if mariadb? && version < "10.2.5"
64
- create_table_info = create_table_info(column.table_name)
65
- if %r/#{quote_column_name(column.name)} #{Regexp.quote(column.sql_type)}(?: COLLATE \w+)? AS \((?<expression>.+?)\) #{column.extra}/ =~ create_table_info
61
+ if @connection.mariadb? && @connection.version < "10.2.5"
62
+ create_table_info = @connection.send(:create_table_info, column.table_name)
63
+ column_name = @connection.quote_column_name(column.name)
64
+ if %r/#{column_name} #{Regexp.quote(column.sql_type)}(?: COLLATE \w+)? AS \((?<expression>.+?)\) #{column.extra}/ =~ create_table_info
66
65
  $~[:expression].inspect
67
66
  end
68
67
  else
69
- scope = quoted_scope(column.table_name)
68
+ scope = @connection.send(:quoted_scope, column.table_name)
69
+ column_name = @connection.quote(column.name)
70
70
  sql = "SELECT generation_expression FROM information_schema.columns" \
71
71
  " WHERE table_schema = #{scope[:schema]}" \
72
72
  " AND table_name = #{scope[:name]}" \
73
- " AND column_name = #{quote(column.name)}"
74
- query_value(sql, "SCHEMA").inspect
73
+ " AND column_name = #{column_name}"
74
+ @connection.query_value(sql, "SCHEMA").inspect
75
75
  end
76
76
  end
77
77
  end
@@ -1,7 +1,56 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module MySQL
4
6
  module SchemaStatements # :nodoc:
7
+ # Returns an array of indexes for the given table.
8
+ def indexes(table_name)
9
+ indexes = []
10
+ current_index = nil
11
+ execute_and_free("SHOW KEYS FROM #{quote_table_name(table_name)}", "SCHEMA") do |result|
12
+ each_hash(result) do |row|
13
+ if current_index != row[:Key_name]
14
+ next if row[:Key_name] == "PRIMARY" # skip the primary key
15
+ current_index = row[:Key_name]
16
+
17
+ mysql_index_type = row[:Index_type].downcase.to_sym
18
+ case mysql_index_type
19
+ when :fulltext, :spatial
20
+ index_type = mysql_index_type
21
+ when :btree, :hash
22
+ index_using = mysql_index_type
23
+ end
24
+
25
+ indexes << [
26
+ row[:Table],
27
+ row[:Key_name],
28
+ row[:Non_unique].to_i == 0,
29
+ [],
30
+ lengths: {},
31
+ orders: {},
32
+ type: index_type,
33
+ using: index_using,
34
+ comment: row[:Index_comment].presence
35
+ ]
36
+ end
37
+
38
+ indexes.last[-2] << row[:Column_name]
39
+ indexes.last[-1][:lengths].merge!(row[:Column_name] => row[:Sub_part].to_i) if row[:Sub_part]
40
+ indexes.last[-1][:orders].merge!(row[:Column_name] => :desc) if row[:Collation] == "D"
41
+ end
42
+ end
43
+
44
+ indexes.map { |index| IndexDefinition.new(*index) }
45
+ end
46
+
47
+ def remove_column(table_name, column_name, type = nil, options = {})
48
+ if foreign_key_exists?(table_name, column: column_name)
49
+ remove_foreign_key(table_name, column: column_name)
50
+ end
51
+ super
52
+ end
53
+
5
54
  def internal_string_options_for_primary_key
6
55
  super.tap do |options|
7
56
  if CHARSETS_OF_4BYTES_MAXLEN.include?(charset) && (mariadb? || version < "8.0.0")
@@ -10,13 +59,69 @@ module ActiveRecord
10
59
  end
11
60
  end
12
61
 
62
+ def update_table_definition(table_name, base)
63
+ MySQL::Table.new(table_name, base)
64
+ end
65
+
66
+ def create_schema_dumper(options)
67
+ MySQL::SchemaDumper.create(self, options)
68
+ end
69
+
13
70
  private
14
71
  CHARSETS_OF_4BYTES_MAXLEN = ["utf8mb4", "utf16", "utf16le", "utf32"]
15
72
 
73
+ def schema_creation
74
+ MySQL::SchemaCreation.new(self)
75
+ end
76
+
77
+ def create_table_definition(*args)
78
+ MySQL::TableDefinition.new(*args)
79
+ end
80
+
81
+ def new_column_from_field(table_name, field)
82
+ type_metadata = fetch_type_metadata(field[:Type], field[:Extra])
83
+ if type_metadata.type == :datetime && /\ACURRENT_TIMESTAMP(?:\(\))?\z/i.match?(field[:Default])
84
+ default, default_function = nil, "CURRENT_TIMESTAMP"
85
+ else
86
+ default, default_function = field[:Default], nil
87
+ end
88
+
89
+ MySQL::Column.new(
90
+ field[:Field],
91
+ default,
92
+ type_metadata,
93
+ field[:Null] == "YES",
94
+ table_name,
95
+ default_function,
96
+ field[:Collation],
97
+ comment: field[:Comment].presence
98
+ )
99
+ end
100
+
101
+ def fetch_type_metadata(sql_type, extra = "")
102
+ MySQL::TypeMetadata.new(super(sql_type), extra: extra)
103
+ end
104
+
105
+ def extract_foreign_key_action(specifier)
106
+ super unless specifier == "RESTRICT"
107
+ end
108
+
109
+ def add_index_length(quoted_columns, **options)
110
+ lengths = options_for_index_columns(options[:length])
111
+ quoted_columns.each do |name, column|
112
+ column << "(#{lengths[name]})" if lengths[name].present?
113
+ end
114
+ end
115
+
116
+ def add_options_for_index_columns(quoted_columns, **options)
117
+ quoted_columns = add_index_length(quoted_columns, options)
118
+ super
119
+ end
120
+
16
121
  def data_source_sql(name = nil, type: nil)
17
122
  scope = quoted_scope(name, type: type)
18
123
 
19
- sql = "SELECT table_name FROM information_schema.tables"
124
+ sql = "SELECT table_name FROM information_schema.tables".dup
20
125
  sql << " WHERE table_schema = #{scope[:schema]}"
21
126
  sql << " AND table_name = #{scope[:name]}" if scope[:name]
22
127
  sql << " AND table_type = #{scope[:type]}" if scope[:type]
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module MySQL
@@ -1,9 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_record/connection_adapters/abstract_mysql_adapter"
2
4
  require "active_record/connection_adapters/mysql/database_statements"
3
5
 
4
- gem "mysql2", ">= 0.3.18", "< 0.6.0"
6
+ gem "mysql2", ">= 0.4.4", "< 0.6.0"
5
7
  require "mysql2"
6
- raise "mysql2 0.4.3 is not supported. Please upgrade to 0.4.4+" if Mysql2::VERSION == "0.4.3"
7
8
 
8
9
  module ActiveRecord
9
10
  module ConnectionHandling # :nodoc:
@@ -103,6 +104,11 @@ module ActiveRecord
103
104
  @connection.close
104
105
  end
105
106
 
107
+ def discard! # :nodoc:
108
+ @connection.automatic_close = false
109
+ @connection = nil
110
+ end
111
+
106
112
  private
107
113
 
108
114
  def connect
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  # PostgreSQL-specific extensions to column definitions in a table.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
@@ -147,6 +149,10 @@ module ActiveRecord
147
149
  end
148
150
 
149
151
  private
152
+ # Returns the current ID of a table's sequence.
153
+ def last_insert_id_result(sequence_name)
154
+ exec_query("SELECT currval(#{quote(sequence_name)})", "SQL")
155
+ end
150
156
 
151
157
  def suppress_composite_primary_key(pk)
152
158
  pk unless pk.is_a?(Array)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
@@ -31,13 +33,7 @@ module ActiveRecord
31
33
 
32
34
  def cast(value)
33
35
  if value.is_a?(::String)
34
- value = begin
35
- @pg_decoder.decode(value)
36
- rescue TypeError
37
- # malformed array string is treated as [], will raise in PG 2.0 gem
38
- # this keeps a consistent implementation
39
- []
40
- end
36
+ value = @pg_decoder.decode(value)
41
37
  end
42
38
  type_cast_array(value, :cast)
43
39
  end
@@ -70,10 +66,6 @@ module ActiveRecord
70
66
  deserialize(raw_old_value) != new_value
71
67
  end
72
68
 
73
- def force_equality?(value)
74
- value.is_a?(::Array)
75
- end
76
-
77
69
  private
78
70
 
79
71
  def type_cast_array(value, method)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "ipaddr"
2
4
 
3
5
  module ActiveRecord
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ module PostgreSQL
6
+ module OID # :nodoc:
7
+ class Date < Type::Date # :nodoc:
8
+ def cast_value(value)
9
+ case value
10
+ when "infinity" then ::Float::INFINITY
11
+ when "-infinity" then -::Float::INFINITY
12
+ when / BC$/
13
+ astronomical_year = format("%04d", -value[/^\d+/].to_i + 1)
14
+ super(value.sub(/ BC$/, "").sub(/^\d+/, astronomical_year))
15
+ else
16
+ super
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
4
6
  module OID # :nodoc:
5
- class Jsonb < Json # :nodoc:
7
+ class Jsonb < Type::Json # :nodoc:
6
8
  def type
7
9
  :jsonb
8
10
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
@@ -22,7 +24,7 @@ module ActiveRecord
22
24
  # (3) -$2.55
23
25
  # (4) ($2.55)
24
26
 
25
- value.sub!(/^\((.+)\)$/, '-\1') # (4)
27
+ value = value.sub(/^\((.+)\)$/, '-\1') # (4)
26
28
  case value
27
29
  when /^-?\D+[\d,]+\.\d{2}$/ # (1)
28
30
  value.gsub!(/[^-\d.]/, "")
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  Point = Struct.new(:x, :y)
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
@@ -33,7 +35,7 @@ module ActiveRecord
33
35
  if value.is_a?(::Range)
34
36
  from = type_cast_single_for_database(value.begin)
35
37
  to = type_cast_single_for_database(value.end)
36
- "[#{from},#{to}#{value.exclude_end? ? ')' : ']'}"
38
+ ::Range.new(from, to, value.exclude_end?)
37
39
  else
38
40
  super
39
41
  end
@@ -51,10 +53,6 @@ module ActiveRecord
51
53
  ::Range.new(new_begin, new_end, value.exclude_end?)
52
54
  end
53
55
 
54
- def force_equality?(value)
55
- value.is_a?(::Range)
56
- end
57
-
58
56
  private
59
57
 
60
58
  def type_cast_single(value)
@@ -62,7 +60,7 @@ module ActiveRecord
62
60
  end
63
61
 
64
62
  def type_cast_single_for_database(value)
65
- infinity?(value) ? "" : @subtype.serialize(value)
63
+ infinity?(value) ? value : @subtype.serialize(value)
66
64
  end
67
65
 
68
66
  def extract_bounds(value)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
@@ -29,8 +31,8 @@ module ActiveRecord
29
31
  composites.each { |row| register_composite_type(row) }
30
32
  end
31
33
 
32
- def query_conditions_for_initial_load(type_map)
33
- known_type_names = type_map.keys.map { |n| "'#{n}'" }
34
+ def query_conditions_for_initial_load
35
+ known_type_names = @store.keys.map { |n| "'#{n}'" }
34
36
  known_type_types = %w('r' 'e' 'd')
35
37
  <<-SQL % [known_type_names.join(", "), known_type_types.join(", ")]
36
38
  WHERE
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
4
6
  module OID # :nodoc:
5
7
  class Uuid < Type::Value # :nodoc:
6
- ACCEPTABLE_UUID = %r{\A\{?([a-fA-F0-9]{4}-?){8}\}?\z}x
8
+ ACCEPTABLE_UUID = %r{\A(\{)?([a-fA-F0-9]{4}-?){8}(?(1)\}|)\z}
7
9
 
8
10
  alias_method :serialize, :deserialize
9
11
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module PostgreSQL