activerecord 4.2.11.1 → 5.0.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 (246) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1282 -1195
  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 +8 -4
  8. data/lib/active_record/aggregations.rb +35 -24
  9. data/lib/active_record/association_relation.rb +3 -3
  10. data/lib/active_record/associations.rb +317 -209
  11. data/lib/active_record/associations/alias_tracker.rb +19 -16
  12. data/lib/active_record/associations/association.rb +11 -9
  13. data/lib/active_record/associations/association_scope.rb +73 -102
  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 +14 -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 +3 -10
  22. data/lib/active_record/associations/collection_association.rb +49 -41
  23. data/lib/active_record/associations/collection_proxy.rb +67 -27
  24. data/lib/active_record/associations/foreign_association.rb +1 -1
  25. data/lib/active_record/associations/has_many_association.rb +20 -71
  26. data/lib/active_record/associations/has_many_through_association.rb +8 -47
  27. data/lib/active_record/associations/has_one_association.rb +12 -5
  28. data/lib/active_record/associations/join_dependency.rb +29 -19
  29. data/lib/active_record/associations/join_dependency/join_association.rb +16 -10
  30. data/lib/active_record/associations/preloader.rb +14 -4
  31. data/lib/active_record/associations/preloader/association.rb +46 -52
  32. data/lib/active_record/associations/preloader/collection_association.rb +0 -6
  33. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  34. data/lib/active_record/associations/preloader/has_one.rb +0 -8
  35. data/lib/active_record/associations/preloader/through_association.rb +27 -14
  36. data/lib/active_record/associations/singular_association.rb +7 -1
  37. data/lib/active_record/associations/through_association.rb +11 -3
  38. data/lib/active_record/attribute.rb +68 -18
  39. data/lib/active_record/attribute/user_provided_default.rb +28 -0
  40. data/lib/active_record/attribute_assignment.rb +19 -140
  41. data/lib/active_record/attribute_decorators.rb +6 -5
  42. data/lib/active_record/attribute_methods.rb +76 -47
  43. data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
  44. data/lib/active_record/attribute_methods/dirty.rb +46 -86
  45. data/lib/active_record/attribute_methods/primary_key.rb +2 -2
  46. data/lib/active_record/attribute_methods/query.rb +2 -2
  47. data/lib/active_record/attribute_methods/read.rb +31 -59
  48. data/lib/active_record/attribute_methods/serialization.rb +13 -16
  49. data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -14
  50. data/lib/active_record/attribute_methods/write.rb +13 -37
  51. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  52. data/lib/active_record/attribute_set.rb +30 -3
  53. data/lib/active_record/attribute_set/builder.rb +6 -4
  54. data/lib/active_record/attributes.rb +199 -81
  55. data/lib/active_record/autosave_association.rb +49 -16
  56. data/lib/active_record/base.rb +32 -23
  57. data/lib/active_record/callbacks.rb +39 -43
  58. data/lib/active_record/coders/json.rb +1 -1
  59. data/lib/active_record/coders/yaml_column.rb +20 -8
  60. data/lib/active_record/collection_cache_key.rb +40 -0
  61. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +452 -182
  62. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
  63. data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -61
  64. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -2
  65. data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -10
  66. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  67. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
  68. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -185
  69. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
  70. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +380 -141
  71. data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
  72. data/lib/active_record/connection_adapters/abstract_adapter.rb +141 -59
  73. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +401 -370
  74. data/lib/active_record/connection_adapters/column.rb +28 -43
  75. data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
  76. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
  77. data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
  78. data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
  79. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
  80. data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
  81. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
  82. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
  83. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
  84. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
  85. data/lib/active_record/connection_adapters/mysql2_adapter.rb +29 -166
  86. data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
  87. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +10 -72
  88. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
  90. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +27 -57
  91. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
  92. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  94. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
  95. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
  96. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
  100. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
  103. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
  104. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
  106. data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -18
  107. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
  108. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
  109. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +234 -148
  111. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  112. data/lib/active_record/connection_adapters/postgresql_adapter.rb +248 -160
  113. data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
  114. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  115. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
  116. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
  117. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  118. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +149 -192
  119. data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
  120. data/lib/active_record/connection_handling.rb +37 -14
  121. data/lib/active_record/core.rb +89 -107
  122. data/lib/active_record/counter_cache.rb +13 -24
  123. data/lib/active_record/dynamic_matchers.rb +1 -20
  124. data/lib/active_record/enum.rb +113 -76
  125. data/lib/active_record/errors.rb +87 -48
  126. data/lib/active_record/explain_registry.rb +1 -1
  127. data/lib/active_record/explain_subscriber.rb +1 -1
  128. data/lib/active_record/fixture_set/file.rb +26 -5
  129. data/lib/active_record/fixtures.rb +76 -40
  130. data/lib/active_record/gem_version.rb +4 -4
  131. data/lib/active_record/inheritance.rb +32 -40
  132. data/lib/active_record/integration.rb +4 -4
  133. data/lib/active_record/internal_metadata.rb +56 -0
  134. data/lib/active_record/legacy_yaml_adapter.rb +18 -2
  135. data/lib/active_record/locale/en.yml +3 -2
  136. data/lib/active_record/locking/optimistic.rb +15 -15
  137. data/lib/active_record/locking/pessimistic.rb +1 -1
  138. data/lib/active_record/log_subscriber.rb +43 -21
  139. data/lib/active_record/migration.rb +363 -133
  140. data/lib/active_record/migration/command_recorder.rb +59 -18
  141. data/lib/active_record/migration/compatibility.rb +126 -0
  142. data/lib/active_record/model_schema.rb +129 -41
  143. data/lib/active_record/nested_attributes.rb +58 -29
  144. data/lib/active_record/null_relation.rb +16 -8
  145. data/lib/active_record/persistence.rb +121 -80
  146. data/lib/active_record/query_cache.rb +15 -18
  147. data/lib/active_record/querying.rb +10 -9
  148. data/lib/active_record/railtie.rb +23 -16
  149. data/lib/active_record/railties/controller_runtime.rb +1 -1
  150. data/lib/active_record/railties/databases.rake +69 -46
  151. data/lib/active_record/readonly_attributes.rb +1 -1
  152. data/lib/active_record/reflection.rb +282 -115
  153. data/lib/active_record/relation.rb +176 -116
  154. data/lib/active_record/relation/batches.rb +139 -34
  155. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  156. data/lib/active_record/relation/calculations.rb +79 -108
  157. data/lib/active_record/relation/delegation.rb +7 -20
  158. data/lib/active_record/relation/finder_methods.rb +163 -81
  159. data/lib/active_record/relation/from_clause.rb +32 -0
  160. data/lib/active_record/relation/merger.rb +16 -42
  161. data/lib/active_record/relation/predicate_builder.rb +120 -107
  162. data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
  163. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
  164. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  165. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  166. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  167. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
  168. data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
  169. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  170. data/lib/active_record/relation/query_attribute.rb +19 -0
  171. data/lib/active_record/relation/query_methods.rb +308 -244
  172. data/lib/active_record/relation/record_fetch_warning.rb +49 -0
  173. data/lib/active_record/relation/spawn_methods.rb +4 -7
  174. data/lib/active_record/relation/where_clause.rb +174 -0
  175. data/lib/active_record/relation/where_clause_factory.rb +38 -0
  176. data/lib/active_record/result.rb +4 -3
  177. data/lib/active_record/runtime_registry.rb +1 -1
  178. data/lib/active_record/sanitization.rb +95 -66
  179. data/lib/active_record/schema.rb +26 -22
  180. data/lib/active_record/schema_dumper.rb +62 -38
  181. data/lib/active_record/schema_migration.rb +11 -14
  182. data/lib/active_record/scoping.rb +32 -15
  183. data/lib/active_record/scoping/default.rb +23 -9
  184. data/lib/active_record/scoping/named.rb +49 -28
  185. data/lib/active_record/secure_token.rb +38 -0
  186. data/lib/active_record/serialization.rb +2 -4
  187. data/lib/active_record/statement_cache.rb +16 -14
  188. data/lib/active_record/store.rb +8 -3
  189. data/lib/active_record/suppressor.rb +58 -0
  190. data/lib/active_record/table_metadata.rb +68 -0
  191. data/lib/active_record/tasks/database_tasks.rb +57 -43
  192. data/lib/active_record/tasks/mysql_database_tasks.rb +6 -14
  193. data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
  194. data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
  195. data/lib/active_record/timestamp.rb +20 -9
  196. data/lib/active_record/touch_later.rb +58 -0
  197. data/lib/active_record/transactions.rb +138 -56
  198. data/lib/active_record/type.rb +66 -17
  199. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  200. data/lib/active_record/type/date.rb +2 -45
  201. data/lib/active_record/type/date_time.rb +2 -49
  202. data/lib/active_record/type/internal/abstract_json.rb +29 -0
  203. data/lib/active_record/type/internal/timezone.rb +15 -0
  204. data/lib/active_record/type/serialized.rb +15 -14
  205. data/lib/active_record/type/time.rb +10 -16
  206. data/lib/active_record/type/type_map.rb +4 -4
  207. data/lib/active_record/type_caster.rb +7 -0
  208. data/lib/active_record/type_caster/connection.rb +29 -0
  209. data/lib/active_record/type_caster/map.rb +19 -0
  210. data/lib/active_record/validations.rb +33 -32
  211. data/lib/active_record/validations/absence.rb +23 -0
  212. data/lib/active_record/validations/associated.rb +10 -3
  213. data/lib/active_record/validations/length.rb +24 -0
  214. data/lib/active_record/validations/presence.rb +11 -12
  215. data/lib/active_record/validations/uniqueness.rb +30 -29
  216. data/lib/rails/generators/active_record/migration.rb +7 -0
  217. data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
  218. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
  219. data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -1
  220. data/lib/rails/generators/active_record/model/model_generator.rb +32 -15
  221. data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
  222. data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
  223. metadata +59 -34
  224. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
  225. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  226. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
  227. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  228. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  229. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  230. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  231. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  232. data/lib/active_record/type/big_integer.rb +0 -13
  233. data/lib/active_record/type/binary.rb +0 -50
  234. data/lib/active_record/type/boolean.rb +0 -31
  235. data/lib/active_record/type/decimal.rb +0 -64
  236. data/lib/active_record/type/decimal_without_scale.rb +0 -11
  237. data/lib/active_record/type/decorator.rb +0 -14
  238. data/lib/active_record/type/float.rb +0 -19
  239. data/lib/active_record/type/integer.rb +0 -59
  240. data/lib/active_record/type/mutable.rb +0 -16
  241. data/lib/active_record/type/numeric.rb +0 -36
  242. data/lib/active_record/type/string.rb +0 -40
  243. data/lib/active_record/type/text.rb +0 -11
  244. data/lib/active_record/type/time_value.rb +0 -38
  245. data/lib/active_record/type/unsigned_integer.rb +0 -15
  246. 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
+ /\bunsigned\z/ === 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,125 @@
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 a record hash with the column names as keys and column values
17
+ # as values.
18
+ def select_one(arel, name = nil, binds = [])
19
+ arel, binds = binds_from_relation(arel, binds)
20
+ @connection.query_options.merge!(as: :hash)
21
+ select_result(to_sql(arel, binds), name, binds) do |result|
22
+ @connection.next_result while @connection.more_results?
23
+ result.first
24
+ end
25
+ ensure
26
+ @connection.query_options.merge!(as: :array)
27
+ end
28
+
29
+ # Returns an array of arrays containing the field values.
30
+ # Order is the same as that returned by +columns+.
31
+ def select_rows(sql, name = nil, binds = [])
32
+ select_result(sql, name, binds) do |result|
33
+ @connection.next_result while @connection.more_results?
34
+ result.to_a
35
+ end
36
+ end
37
+
38
+ # Executes the SQL statement in the context of this connection.
39
+ def execute(sql, name = nil)
40
+ if @connection
41
+ # make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
42
+ # made since we established the connection
43
+ @connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
44
+ end
45
+
46
+ super
47
+ end
48
+
49
+ def exec_query(sql, name = 'SQL', binds = [], prepare: false)
50
+ if without_prepared_statement?(binds)
51
+ execute_and_free(sql, name) do |result|
52
+ ActiveRecord::Result.new(result.fields, result.to_a) if result
53
+ end
54
+ else
55
+ exec_stmt_and_free(sql, name, binds, cache_stmt: prepare) do |_, result|
56
+ ActiveRecord::Result.new(result.fields, result.to_a) if result
57
+ end
58
+ end
59
+ end
60
+
61
+ def exec_delete(sql, name, binds)
62
+ if without_prepared_statement?(binds)
63
+ execute_and_free(sql, name) { @connection.affected_rows }
64
+ else
65
+ exec_stmt_and_free(sql, name, binds) { |stmt| stmt.affected_rows }
66
+ end
67
+ end
68
+ alias :exec_update :exec_delete
69
+
70
+ protected
71
+
72
+ def last_inserted_id(result)
73
+ @connection.last_id
74
+ end
75
+
76
+ private
77
+
78
+ def select_result(sql, name = nil, binds = [])
79
+ if without_prepared_statement?(binds)
80
+ execute_and_free(sql, name) { |result| yield result }
81
+ else
82
+ exec_stmt_and_free(sql, name, binds, cache_stmt: true) { |_, result| yield result }
83
+ end
84
+ end
85
+
86
+ def exec_stmt_and_free(sql, name, binds, cache_stmt: false)
87
+ if @connection
88
+ # make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
89
+ # made since we established the connection
90
+ @connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
91
+ end
92
+
93
+ type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) }
94
+
95
+ log(sql, name, binds) do
96
+ if cache_stmt
97
+ cache = @statements[sql] ||= {
98
+ stmt: @connection.prepare(sql)
99
+ }
100
+ stmt = cache[:stmt]
101
+ else
102
+ stmt = @connection.prepare(sql)
103
+ end
104
+
105
+ begin
106
+ result = stmt.execute(*type_casted_binds)
107
+ rescue Mysql2::Error => e
108
+ if cache_stmt
109
+ @statements.delete(sql)
110
+ else
111
+ stmt.close
112
+ end
113
+ raise e
114
+ end
115
+
116
+ ret = yield stmt, result
117
+ result.free if result
118
+ stmt.close unless cache_stmt
119
+ ret
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+ 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