activerecord 4.2.11.3 → 5.0.7.2

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 (251) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1638 -1132
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +7 -8
  5. data/examples/performance.rb +2 -3
  6. data/examples/simple.rb +0 -1
  7. data/lib/active_record.rb +7 -2
  8. data/lib/active_record/aggregations.rb +34 -21
  9. data/lib/active_record/association_relation.rb +7 -4
  10. data/lib/active_record/associations.rb +347 -218
  11. data/lib/active_record/associations/alias_tracker.rb +19 -16
  12. data/lib/active_record/associations/association.rb +22 -10
  13. data/lib/active_record/associations/association_scope.rb +75 -104
  14. data/lib/active_record/associations/belongs_to_association.rb +21 -32
  15. data/lib/active_record/associations/builder/association.rb +28 -34
  16. data/lib/active_record/associations/builder/belongs_to.rb +43 -18
  17. data/lib/active_record/associations/builder/collection_association.rb +7 -19
  18. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +16 -11
  19. data/lib/active_record/associations/builder/has_many.rb +4 -4
  20. data/lib/active_record/associations/builder/has_one.rb +11 -6
  21. data/lib/active_record/associations/builder/singular_association.rb +13 -11
  22. data/lib/active_record/associations/collection_association.rb +85 -69
  23. data/lib/active_record/associations/collection_proxy.rb +104 -46
  24. data/lib/active_record/associations/foreign_association.rb +1 -1
  25. data/lib/active_record/associations/has_many_association.rb +21 -78
  26. data/lib/active_record/associations/has_many_through_association.rb +6 -47
  27. data/lib/active_record/associations/has_one_association.rb +12 -5
  28. data/lib/active_record/associations/join_dependency.rb +38 -22
  29. data/lib/active_record/associations/join_dependency/join_association.rb +15 -14
  30. data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
  31. data/lib/active_record/associations/preloader.rb +14 -4
  32. data/lib/active_record/associations/preloader/association.rb +52 -71
  33. data/lib/active_record/associations/preloader/collection_association.rb +0 -7
  34. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  35. data/lib/active_record/associations/preloader/has_one.rb +0 -8
  36. data/lib/active_record/associations/preloader/singular_association.rb +0 -1
  37. data/lib/active_record/associations/preloader/through_association.rb +36 -17
  38. data/lib/active_record/associations/singular_association.rb +13 -1
  39. data/lib/active_record/associations/through_association.rb +12 -4
  40. data/lib/active_record/attribute.rb +69 -19
  41. data/lib/active_record/attribute/user_provided_default.rb +28 -0
  42. data/lib/active_record/attribute_assignment.rb +19 -140
  43. data/lib/active_record/attribute_decorators.rb +6 -5
  44. data/lib/active_record/attribute_methods.rb +69 -44
  45. data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
  46. data/lib/active_record/attribute_methods/dirty.rb +46 -86
  47. data/lib/active_record/attribute_methods/primary_key.rb +16 -3
  48. data/lib/active_record/attribute_methods/query.rb +2 -2
  49. data/lib/active_record/attribute_methods/read.rb +31 -59
  50. data/lib/active_record/attribute_methods/serialization.rb +13 -16
  51. data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -14
  52. data/lib/active_record/attribute_methods/write.rb +13 -37
  53. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  54. data/lib/active_record/attribute_set.rb +32 -3
  55. data/lib/active_record/attribute_set/builder.rb +42 -16
  56. data/lib/active_record/attributes.rb +199 -81
  57. data/lib/active_record/autosave_association.rb +54 -17
  58. data/lib/active_record/base.rb +32 -23
  59. data/lib/active_record/callbacks.rb +39 -43
  60. data/lib/active_record/coders/json.rb +1 -1
  61. data/lib/active_record/coders/yaml_column.rb +20 -8
  62. data/lib/active_record/collection_cache_key.rb +50 -0
  63. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +467 -189
  64. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
  65. data/lib/active_record/connection_adapters/abstract/database_statements.rb +66 -62
  66. data/lib/active_record/connection_adapters/abstract/query_cache.rb +39 -4
  67. data/lib/active_record/connection_adapters/abstract/quoting.rb +86 -13
  68. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  69. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
  70. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -188
  71. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
  72. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +407 -156
  73. data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
  74. data/lib/active_record/connection_adapters/abstract_adapter.rb +177 -71
  75. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +433 -399
  76. data/lib/active_record/connection_adapters/column.rb +28 -43
  77. data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
  78. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
  79. data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
  80. data/lib/active_record/connection_adapters/mysql/database_statements.rb +108 -0
  81. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
  82. data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
  83. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
  84. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
  85. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
  86. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
  87. data/lib/active_record/connection_adapters/mysql2_adapter.rb +25 -166
  88. data/lib/active_record/connection_adapters/postgresql/column.rb +33 -11
  89. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +18 -72
  90. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
  92. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +37 -57
  93. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +3 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -2
  95. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  96. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
  97. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +13 -3
  98. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
  99. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
  101. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
  102. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
  105. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
  106. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +56 -19
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
  111. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +250 -154
  113. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  114. data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -2
  115. data/lib/active_record/connection_adapters/postgresql_adapter.rb +264 -170
  116. data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
  117. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  118. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
  119. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
  120. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  121. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +151 -194
  122. data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
  123. data/lib/active_record/connection_handling.rb +37 -14
  124. data/lib/active_record/core.rb +92 -108
  125. data/lib/active_record/counter_cache.rb +13 -24
  126. data/lib/active_record/dynamic_matchers.rb +1 -20
  127. data/lib/active_record/enum.rb +116 -76
  128. data/lib/active_record/errors.rb +87 -48
  129. data/lib/active_record/explain.rb +20 -9
  130. data/lib/active_record/explain_registry.rb +1 -1
  131. data/lib/active_record/explain_subscriber.rb +1 -1
  132. data/lib/active_record/fixture_set/file.rb +26 -5
  133. data/lib/active_record/fixtures.rb +77 -41
  134. data/lib/active_record/gem_version.rb +4 -4
  135. data/lib/active_record/inheritance.rb +32 -40
  136. data/lib/active_record/integration.rb +17 -14
  137. data/lib/active_record/internal_metadata.rb +56 -0
  138. data/lib/active_record/legacy_yaml_adapter.rb +18 -2
  139. data/lib/active_record/locale/en.yml +3 -2
  140. data/lib/active_record/locking/optimistic.rb +15 -15
  141. data/lib/active_record/locking/pessimistic.rb +1 -1
  142. data/lib/active_record/log_subscriber.rb +48 -24
  143. data/lib/active_record/migration.rb +362 -111
  144. data/lib/active_record/migration/command_recorder.rb +59 -18
  145. data/lib/active_record/migration/compatibility.rb +126 -0
  146. data/lib/active_record/model_schema.rb +270 -73
  147. data/lib/active_record/nested_attributes.rb +58 -29
  148. data/lib/active_record/no_touching.rb +4 -0
  149. data/lib/active_record/null_relation.rb +16 -8
  150. data/lib/active_record/persistence.rb +152 -90
  151. data/lib/active_record/query_cache.rb +18 -23
  152. data/lib/active_record/querying.rb +12 -11
  153. data/lib/active_record/railtie.rb +23 -16
  154. data/lib/active_record/railties/controller_runtime.rb +1 -1
  155. data/lib/active_record/railties/databases.rake +52 -41
  156. data/lib/active_record/readonly_attributes.rb +1 -1
  157. data/lib/active_record/reflection.rb +302 -115
  158. data/lib/active_record/relation.rb +187 -120
  159. data/lib/active_record/relation/batches.rb +141 -36
  160. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  161. data/lib/active_record/relation/calculations.rb +92 -117
  162. data/lib/active_record/relation/delegation.rb +8 -20
  163. data/lib/active_record/relation/finder_methods.rb +173 -89
  164. data/lib/active_record/relation/from_clause.rb +32 -0
  165. data/lib/active_record/relation/merger.rb +16 -42
  166. data/lib/active_record/relation/predicate_builder.rb +120 -107
  167. data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
  168. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
  169. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  170. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  171. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  172. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
  173. data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
  174. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  175. data/lib/active_record/relation/query_attribute.rb +19 -0
  176. data/lib/active_record/relation/query_methods.rb +308 -244
  177. data/lib/active_record/relation/record_fetch_warning.rb +49 -0
  178. data/lib/active_record/relation/spawn_methods.rb +4 -7
  179. data/lib/active_record/relation/where_clause.rb +174 -0
  180. data/lib/active_record/relation/where_clause_factory.rb +38 -0
  181. data/lib/active_record/result.rb +11 -4
  182. data/lib/active_record/runtime_registry.rb +1 -1
  183. data/lib/active_record/sanitization.rb +105 -66
  184. data/lib/active_record/schema.rb +26 -22
  185. data/lib/active_record/schema_dumper.rb +54 -37
  186. data/lib/active_record/schema_migration.rb +11 -14
  187. data/lib/active_record/scoping.rb +34 -16
  188. data/lib/active_record/scoping/default.rb +28 -10
  189. data/lib/active_record/scoping/named.rb +59 -26
  190. data/lib/active_record/secure_token.rb +38 -0
  191. data/lib/active_record/serialization.rb +3 -5
  192. data/lib/active_record/statement_cache.rb +17 -15
  193. data/lib/active_record/store.rb +8 -3
  194. data/lib/active_record/suppressor.rb +58 -0
  195. data/lib/active_record/table_metadata.rb +69 -0
  196. data/lib/active_record/tasks/database_tasks.rb +66 -49
  197. data/lib/active_record/tasks/mysql_database_tasks.rb +6 -14
  198. data/lib/active_record/tasks/postgresql_database_tasks.rb +12 -3
  199. data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
  200. data/lib/active_record/timestamp.rb +20 -9
  201. data/lib/active_record/touch_later.rb +63 -0
  202. data/lib/active_record/transactions.rb +139 -57
  203. data/lib/active_record/type.rb +66 -17
  204. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  205. data/lib/active_record/type/date.rb +2 -45
  206. data/lib/active_record/type/date_time.rb +2 -49
  207. data/lib/active_record/type/internal/abstract_json.rb +33 -0
  208. data/lib/active_record/type/internal/timezone.rb +15 -0
  209. data/lib/active_record/type/serialized.rb +15 -14
  210. data/lib/active_record/type/time.rb +10 -16
  211. data/lib/active_record/type/type_map.rb +4 -4
  212. data/lib/active_record/type_caster.rb +7 -0
  213. data/lib/active_record/type_caster/connection.rb +29 -0
  214. data/lib/active_record/type_caster/map.rb +19 -0
  215. data/lib/active_record/validations.rb +33 -32
  216. data/lib/active_record/validations/absence.rb +23 -0
  217. data/lib/active_record/validations/associated.rb +10 -3
  218. data/lib/active_record/validations/length.rb +24 -0
  219. data/lib/active_record/validations/presence.rb +11 -12
  220. data/lib/active_record/validations/uniqueness.rb +33 -33
  221. data/lib/rails/generators/active_record/migration.rb +15 -0
  222. data/lib/rails/generators/active_record/migration/migration_generator.rb +8 -5
  223. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
  224. data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -1
  225. data/lib/rails/generators/active_record/model/model_generator.rb +33 -16
  226. data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
  227. data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
  228. metadata +58 -34
  229. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
  230. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  231. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
  232. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  233. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  234. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  235. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  236. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  237. data/lib/active_record/type/big_integer.rb +0 -13
  238. data/lib/active_record/type/binary.rb +0 -50
  239. data/lib/active_record/type/boolean.rb +0 -31
  240. data/lib/active_record/type/decimal.rb +0 -64
  241. data/lib/active_record/type/decimal_without_scale.rb +0 -11
  242. data/lib/active_record/type/decorator.rb +0 -14
  243. data/lib/active_record/type/float.rb +0 -19
  244. data/lib/active_record/type/integer.rb +0 -59
  245. data/lib/active_record/type/mutable.rb +0 -16
  246. data/lib/active_record/type/numeric.rb +0 -36
  247. data/lib/active_record/type/string.rb +0 -40
  248. data/lib/active_record/type/text.rb +0 -11
  249. data/lib/active_record/type/time_value.rb +0 -38
  250. data/lib/active_record/type/unsigned_integer.rb +0 -15
  251. data/lib/active_record/type/value.rb +0 -110
@@ -1,46 +1,35 @@
1
- require 'set'
2
-
3
1
  module ActiveRecord
4
2
  # :stopdoc:
5
3
  module ConnectionAdapters
6
4
  # An abstract definition of a column in a table.
7
5
  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
10
-
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
6
+ attr_reader :name, :default, :sql_type_metadata, :null, :table_name, :default_function, :collation, :comment
15
7
 
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
8
+ delegate :precision, :scale, :limit, :type, :sql_type, to: :sql_type_metadata, allow_nil: true
23
9
 
24
10
  # Instantiates a new column in the table.
25
11
  #
26
- # +name+ is the column's name, such as <tt>supplier_id</tt> in <tt>supplier_id int(11)</tt>.
12
+ # +name+ is the column's name, such as <tt>supplier_id</tt> in <tt>supplier_id int</tt>.
27
13
  # +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.
14
+ # +sql_type_metadata+ is various information about the type of the column
32
15
  # +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
16
+ def initialize(name, default, sql_type_metadata = nil, null = true, table_name = nil, default_function = nil, collation = nil, comment: nil, **)
17
+ @name = name.freeze
18
+ @table_name = table_name
19
+ @sql_type_metadata = sql_type_metadata
20
+ @null = null
21
+ @default = default
22
+ @default_function = default_function
23
+ @collation = collation
24
+ @comment = comment
40
25
  end
41
26
 
42
27
  def has_default?
43
- !default.nil?
28
+ !default.nil? || default_function
29
+ end
30
+
31
+ def bigint?
32
+ /\Abigint\b/ === sql_type
44
33
  end
45
34
 
46
35
  # Returns the human name of the column name.
@@ -51,19 +40,9 @@ module ActiveRecord
51
40
  Base.human_attribute_name(@name)
52
41
  end
53
42
 
54
- def with_type(type)
55
- dup.tap do |clone|
56
- clone.instance_variable_set('@cast_type', type)
57
- end
58
- end
59
-
60
43
  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
44
+ other.is_a?(Column) &&
45
+ attributes_for_hash == other.attributes_for_hash
67
46
  end
68
47
  alias :eql? :==
69
48
 
@@ -71,10 +50,16 @@ module ActiveRecord
71
50
  attributes_for_hash.hash
72
51
  end
73
52
 
74
- private
53
+ protected
75
54
 
76
55
  def attributes_for_hash
77
- [self.class, name, default, cast_type, sql_type, null, default_function]
56
+ [self.class, name, default, sql_type_metadata, null, table_name, default_function, collation]
57
+ end
58
+ end
59
+
60
+ class NullColumn < Column
61
+ def initialize(name)
62
+ super(name, nil)
78
63
  end
79
64
  end
80
65
  end
@@ -1,13 +1,12 @@
1
1
  require 'uri'
2
- require 'active_support/core_ext/string/filters'
3
2
 
4
3
  module ActiveRecord
5
4
  module ConnectionAdapters
6
5
  class ConnectionSpecification #:nodoc:
7
- attr_reader :config, :adapter_method
6
+ attr_reader :name, :config, :adapter_method
8
7
 
9
- def initialize(config, adapter_method)
10
- @config, @adapter_method = config, adapter_method
8
+ def initialize(name, config, adapter_method)
9
+ @name, @config, @adapter_method = name, config, adapter_method
11
10
  end
12
11
 
13
12
  def initialize_dup(original)
@@ -34,7 +33,7 @@ module ActiveRecord
34
33
  def initialize(url)
35
34
  raise "Database URL cannot be empty" if url.blank?
36
35
  @uri = uri_parser.parse(url)
37
- @adapter = @uri.scheme.tr('-', '_')
36
+ @adapter = @uri.scheme && @uri.scheme.tr('-', '_')
38
37
  @adapter = "postgresql" if @adapter == "postgres"
39
38
 
40
39
  if @uri.opaque
@@ -165,7 +164,7 @@ module ActiveRecord
165
164
  # spec.config
166
165
  # # => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3" }
167
166
  #
168
- def spec(config)
167
+ def spec(config, name = nil)
169
168
  spec = resolve(config).symbolize_keys
170
169
 
171
170
  raise(AdapterNotSpecified, "database configuration does not specify adapter") unless spec.key?(:adapter)
@@ -176,11 +175,18 @@ module ActiveRecord
176
175
  rescue Gem::LoadError => e
177
176
  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
177
  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
178
+ 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
180
179
  end
181
180
 
182
181
  adapter_method = "#{spec[:adapter]}_connection"
183
- ConnectionSpecification.new(spec, adapter_method)
182
+
183
+ name ||=
184
+ if config.is_a?(Symbol)
185
+ config.to_s
186
+ else
187
+ "primary"
188
+ end
189
+ ConnectionSpecification.new(name, spec, adapter_method)
184
190
  end
185
191
 
186
192
  private
@@ -210,30 +216,12 @@ module ActiveRecord
210
216
  when Symbol
211
217
  resolve_symbol_connection spec
212
218
  when String
213
- resolve_string_connection spec
219
+ resolve_url_connection spec
214
220
  when Hash
215
221
  resolve_hash_connection spec
216
222
  end
217
223
  end
218
224
 
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)
234
- end
235
- end
236
-
237
225
  # Takes the environment such as +:production+ or +:development+.
238
226
  # This requires that the @configurations was initialized with a key that
239
227
  # matches.
@@ -0,0 +1,22 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module DetermineIfPreparableVisitor
4
+ attr_reader :preparable
5
+
6
+ def accept(*)
7
+ @preparable = true
8
+ super
9
+ end
10
+
11
+ def visit_Arel_Nodes_In(*)
12
+ @preparable = false
13
+ super
14
+ end
15
+
16
+ def visit_Arel_Nodes_SqlLiteral(*)
17
+ @preparable = false
18
+ super
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,50 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module MySQL
4
+ class Column < ConnectionAdapters::Column # :nodoc:
5
+ delegate :strict, :extra, to: :sql_type_metadata, allow_nil: true
6
+
7
+ def initialize(*)
8
+ super
9
+ assert_valid_default
10
+ extract_default
11
+ end
12
+
13
+ def has_default?
14
+ return false if blob_or_text_column? # MySQL forbids defaults on blob and text columns
15
+ super
16
+ end
17
+
18
+ def blob_or_text_column?
19
+ /\A(?:tiny|medium|long)?blob\b/ === sql_type || type == :text
20
+ end
21
+
22
+ def unsigned?
23
+ /\A(?:enum|set)\b/ !~ sql_type && /\bunsigned\b/ === sql_type
24
+ end
25
+
26
+ def case_sensitive?
27
+ collation && collation !~ /_ci\z/
28
+ end
29
+
30
+ def auto_increment?
31
+ extra == 'auto_increment'
32
+ end
33
+
34
+ private
35
+
36
+ def extract_default
37
+ if blob_or_text_column?
38
+ @default = null || strict ? nil : ''
39
+ end
40
+ end
41
+
42
+ def assert_valid_default
43
+ if blob_or_text_column? && default.present?
44
+ raise ArgumentError, "#{type} columns cannot have a default value: #{default.inspect}"
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,108 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module MySQL
4
+ module DatabaseStatements
5
+ # Returns an ActiveRecord::Result instance.
6
+ def select_all(arel, name = nil, binds = [], preparable: nil)
7
+ result = if ExplainRegistry.collect? && prepared_statements
8
+ unprepared_statement { super }
9
+ else
10
+ super
11
+ end
12
+ @connection.next_result while @connection.more_results?
13
+ result
14
+ end
15
+
16
+ # Returns an array of arrays containing the field values.
17
+ # Order is the same as that returned by +columns+.
18
+ def select_rows(sql, name = nil, binds = [])
19
+ select_result(sql, name, binds) do |result|
20
+ @connection.next_result while @connection.more_results?
21
+ result.to_a
22
+ end
23
+ end
24
+
25
+ # Executes the SQL statement in the context of this connection.
26
+ def execute(sql, name = nil)
27
+ # make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
28
+ # made since we established the connection
29
+ @connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
30
+
31
+ super
32
+ end
33
+
34
+ def exec_query(sql, name = 'SQL', binds = [], prepare: false)
35
+ if without_prepared_statement?(binds)
36
+ execute_and_free(sql, name) do |result|
37
+ ActiveRecord::Result.new(result.fields, result.to_a) if result
38
+ end
39
+ else
40
+ exec_stmt_and_free(sql, name, binds, cache_stmt: prepare) do |_, result|
41
+ ActiveRecord::Result.new(result.fields, result.to_a) if result
42
+ end
43
+ end
44
+ end
45
+
46
+ def exec_delete(sql, name, binds)
47
+ if without_prepared_statement?(binds)
48
+ execute_and_free(sql, name) { @connection.affected_rows }
49
+ else
50
+ exec_stmt_and_free(sql, name, binds) { |stmt| stmt.affected_rows }
51
+ end
52
+ end
53
+ alias :exec_update :exec_delete
54
+
55
+ protected
56
+
57
+ def last_inserted_id(result)
58
+ @connection.last_id
59
+ end
60
+
61
+ private
62
+
63
+ def select_result(sql, name = nil, binds = [])
64
+ if without_prepared_statement?(binds)
65
+ execute_and_free(sql, name) { |result| yield result }
66
+ else
67
+ exec_stmt_and_free(sql, name, binds, cache_stmt: true) { |_, result| yield result }
68
+ end
69
+ end
70
+
71
+ def exec_stmt_and_free(sql, name, binds, cache_stmt: false)
72
+ # make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
73
+ # made since we established the connection
74
+ @connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
75
+
76
+ type_casted_binds = type_casted_binds(binds)
77
+
78
+ log(sql, name, binds, type_casted_binds) do
79
+ if cache_stmt
80
+ cache = @statements[sql] ||= {
81
+ stmt: @connection.prepare(sql)
82
+ }
83
+ stmt = cache[:stmt]
84
+ else
85
+ stmt = @connection.prepare(sql)
86
+ end
87
+
88
+ begin
89
+ result = stmt.execute(*type_casted_binds)
90
+ rescue Mysql2::Error => e
91
+ if cache_stmt
92
+ @statements.delete(sql)
93
+ else
94
+ stmt.close
95
+ end
96
+ raise e
97
+ end
98
+
99
+ ret = yield stmt, result
100
+ result.free if result
101
+ stmt.close unless cache_stmt
102
+ ret
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,70 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module MySQL
4
+ class ExplainPrettyPrinter # :nodoc:
5
+ # Pretty prints the result of an EXPLAIN in a way that resembles the output of the
6
+ # MySQL shell:
7
+ #
8
+ # +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
9
+ # | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
10
+ # +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
11
+ # | 1 | SIMPLE | users | const | PRIMARY | PRIMARY | 4 | const | 1 | |
12
+ # | 1 | SIMPLE | posts | ALL | NULL | NULL | NULL | NULL | 1 | Using where |
13
+ # +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
14
+ # 2 rows in set (0.00 sec)
15
+ #
16
+ # This is an exercise in Ruby hyperrealism :).
17
+ def pp(result, elapsed)
18
+ widths = compute_column_widths(result)
19
+ separator = build_separator(widths)
20
+
21
+ pp = []
22
+
23
+ pp << separator
24
+ pp << build_cells(result.columns, widths)
25
+ pp << separator
26
+
27
+ result.rows.each do |row|
28
+ pp << build_cells(row, widths)
29
+ end
30
+
31
+ pp << separator
32
+ pp << build_footer(result.rows.length, elapsed)
33
+
34
+ pp.join("\n") + "\n"
35
+ end
36
+
37
+ private
38
+
39
+ def compute_column_widths(result)
40
+ [].tap do |widths|
41
+ result.columns.each_with_index do |column, i|
42
+ cells_in_column = [column] + result.rows.map {|r| r[i].nil? ? 'NULL' : r[i].to_s}
43
+ widths << cells_in_column.map(&:length).max
44
+ end
45
+ end
46
+ end
47
+
48
+ def build_separator(widths)
49
+ padding = 1
50
+ '+' + widths.map {|w| '-' * (w + (padding*2))}.join('+') + '+'
51
+ end
52
+
53
+ def build_cells(items, widths)
54
+ cells = []
55
+ items.each_with_index do |item, i|
56
+ item = 'NULL' if item.nil?
57
+ justifier = item.is_a?(Numeric) ? 'rjust' : 'ljust'
58
+ cells << item.to_s.send(justifier, widths[i])
59
+ end
60
+ '| ' + cells.join(' | ') + ' |'
61
+ end
62
+
63
+ def build_footer(nrows, elapsed)
64
+ rows_label = nrows == 1 ? 'row' : 'rows'
65
+ "#{nrows} #{rows_label} in set (%.2f sec)" % elapsed
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,51 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module MySQL
4
+ module Quoting # :nodoc:
5
+ QUOTED_TRUE, QUOTED_FALSE = '1'.freeze, '0'.freeze
6
+
7
+ def quote_column_name(name)
8
+ @quoted_column_names[name] ||= "`#{super.gsub('`', '``')}`"
9
+ end
10
+
11
+ def quote_table_name(name)
12
+ @quoted_table_names[name] ||= super.gsub('.', '`.`')
13
+ end
14
+
15
+ def quoted_true
16
+ QUOTED_TRUE
17
+ end
18
+
19
+ def unquoted_true
20
+ 1
21
+ end
22
+
23
+ def quoted_false
24
+ QUOTED_FALSE
25
+ end
26
+
27
+ def unquoted_false
28
+ 0
29
+ end
30
+
31
+ def quoted_date(value)
32
+ if supports_datetime_with_precision?
33
+ super
34
+ else
35
+ super.sub(/\.\d{6}\z/, '')
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def _quote(value)
42
+ if value.is_a?(Type::Binary::Data)
43
+ "x'#{value.hex}'"
44
+ else
45
+ super
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end