activerecord 4.2.11.3 → 5.0.0.1

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 +1281 -1204
  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/aggregations.rb +35 -24
  8. data/lib/active_record/association_relation.rb +3 -3
  9. data/lib/active_record/associations/alias_tracker.rb +19 -16
  10. data/lib/active_record/associations/association.rb +11 -9
  11. data/lib/active_record/associations/association_scope.rb +73 -102
  12. data/lib/active_record/associations/belongs_to_association.rb +21 -32
  13. data/lib/active_record/associations/builder/association.rb +28 -34
  14. data/lib/active_record/associations/builder/belongs_to.rb +43 -18
  15. data/lib/active_record/associations/builder/collection_association.rb +7 -19
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +14 -11
  17. data/lib/active_record/associations/builder/has_many.rb +4 -4
  18. data/lib/active_record/associations/builder/has_one.rb +11 -6
  19. data/lib/active_record/associations/builder/singular_association.rb +3 -10
  20. data/lib/active_record/associations/collection_association.rb +49 -41
  21. data/lib/active_record/associations/collection_proxy.rb +67 -27
  22. data/lib/active_record/associations/foreign_association.rb +1 -1
  23. data/lib/active_record/associations/has_many_association.rb +20 -71
  24. data/lib/active_record/associations/has_many_through_association.rb +8 -47
  25. data/lib/active_record/associations/has_one_association.rb +12 -5
  26. data/lib/active_record/associations/join_dependency/join_association.rb +16 -10
  27. data/lib/active_record/associations/join_dependency.rb +29 -19
  28. data/lib/active_record/associations/preloader/association.rb +46 -52
  29. data/lib/active_record/associations/preloader/collection_association.rb +0 -6
  30. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  31. data/lib/active_record/associations/preloader/has_one.rb +0 -8
  32. data/lib/active_record/associations/preloader/through_association.rb +27 -14
  33. data/lib/active_record/associations/preloader.rb +14 -4
  34. data/lib/active_record/associations/singular_association.rb +7 -1
  35. data/lib/active_record/associations/through_association.rb +11 -3
  36. data/lib/active_record/associations.rb +317 -209
  37. data/lib/active_record/attribute/user_provided_default.rb +28 -0
  38. data/lib/active_record/attribute.rb +68 -18
  39. data/lib/active_record/attribute_assignment.rb +19 -140
  40. data/lib/active_record/attribute_decorators.rb +6 -5
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
  42. data/lib/active_record/attribute_methods/dirty.rb +46 -86
  43. data/lib/active_record/attribute_methods/primary_key.rb +2 -2
  44. data/lib/active_record/attribute_methods/query.rb +2 -2
  45. data/lib/active_record/attribute_methods/read.rb +31 -59
  46. data/lib/active_record/attribute_methods/serialization.rb +13 -16
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -14
  48. data/lib/active_record/attribute_methods/write.rb +13 -37
  49. data/lib/active_record/attribute_methods.rb +76 -47
  50. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  51. data/lib/active_record/attribute_set/builder.rb +6 -4
  52. data/lib/active_record/attribute_set.rb +30 -3
  53. data/lib/active_record/attributes.rb +199 -81
  54. data/lib/active_record/autosave_association.rb +49 -16
  55. data/lib/active_record/base.rb +32 -23
  56. data/lib/active_record/callbacks.rb +39 -43
  57. data/lib/active_record/coders/json.rb +1 -1
  58. data/lib/active_record/coders/yaml_column.rb +20 -8
  59. data/lib/active_record/collection_cache_key.rb +40 -0
  60. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +452 -182
  61. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
  62. data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -61
  63. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -2
  64. data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -10
  65. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  66. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
  67. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -185
  68. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
  69. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +380 -141
  70. data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
  71. data/lib/active_record/connection_adapters/abstract_adapter.rb +141 -59
  72. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +401 -370
  73. data/lib/active_record/connection_adapters/column.rb +28 -43
  74. data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
  75. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
  76. data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
  77. data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
  78. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
  79. data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
  80. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
  81. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
  82. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
  83. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
  84. data/lib/active_record/connection_adapters/mysql2_adapter.rb +29 -166
  85. data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
  86. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +10 -72
  87. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +27 -57
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
  90. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
  93. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
  95. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
  96. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
  97. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
  98. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
  100. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
  101. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
  102. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
  103. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
  104. data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
  105. data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -18
  106. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
  107. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
  108. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
  109. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +234 -148
  110. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  111. data/lib/active_record/connection_adapters/postgresql_adapter.rb +248 -160
  112. data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
  113. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  114. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
  115. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
  116. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  117. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +149 -192
  118. data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
  119. data/lib/active_record/connection_handling.rb +37 -14
  120. data/lib/active_record/core.rb +89 -107
  121. data/lib/active_record/counter_cache.rb +13 -24
  122. data/lib/active_record/dynamic_matchers.rb +1 -20
  123. data/lib/active_record/enum.rb +113 -76
  124. data/lib/active_record/errors.rb +87 -48
  125. data/lib/active_record/explain_registry.rb +1 -1
  126. data/lib/active_record/explain_subscriber.rb +1 -1
  127. data/lib/active_record/fixture_set/file.rb +26 -5
  128. data/lib/active_record/fixtures.rb +76 -40
  129. data/lib/active_record/gem_version.rb +4 -4
  130. data/lib/active_record/inheritance.rb +32 -40
  131. data/lib/active_record/integration.rb +4 -4
  132. data/lib/active_record/internal_metadata.rb +56 -0
  133. data/lib/active_record/legacy_yaml_adapter.rb +18 -2
  134. data/lib/active_record/locale/en.yml +3 -2
  135. data/lib/active_record/locking/optimistic.rb +15 -15
  136. data/lib/active_record/locking/pessimistic.rb +1 -1
  137. data/lib/active_record/log_subscriber.rb +43 -21
  138. data/lib/active_record/migration/command_recorder.rb +59 -18
  139. data/lib/active_record/migration/compatibility.rb +126 -0
  140. data/lib/active_record/migration.rb +363 -133
  141. data/lib/active_record/model_schema.rb +129 -41
  142. data/lib/active_record/nested_attributes.rb +58 -29
  143. data/lib/active_record/null_relation.rb +16 -8
  144. data/lib/active_record/persistence.rb +121 -80
  145. data/lib/active_record/query_cache.rb +15 -18
  146. data/lib/active_record/querying.rb +10 -9
  147. data/lib/active_record/railtie.rb +23 -16
  148. data/lib/active_record/railties/controller_runtime.rb +1 -1
  149. data/lib/active_record/railties/databases.rake +69 -46
  150. data/lib/active_record/readonly_attributes.rb +1 -1
  151. data/lib/active_record/reflection.rb +282 -115
  152. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  153. data/lib/active_record/relation/batches.rb +139 -34
  154. data/lib/active_record/relation/calculations.rb +79 -108
  155. data/lib/active_record/relation/delegation.rb +7 -20
  156. data/lib/active_record/relation/finder_methods.rb +163 -81
  157. data/lib/active_record/relation/from_clause.rb +32 -0
  158. data/lib/active_record/relation/merger.rb +16 -42
  159. data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
  160. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
  161. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  162. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  163. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  164. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
  165. data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
  166. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  167. data/lib/active_record/relation/predicate_builder.rb +120 -107
  168. data/lib/active_record/relation/query_attribute.rb +19 -0
  169. data/lib/active_record/relation/query_methods.rb +308 -244
  170. data/lib/active_record/relation/record_fetch_warning.rb +49 -0
  171. data/lib/active_record/relation/spawn_methods.rb +4 -7
  172. data/lib/active_record/relation/where_clause.rb +174 -0
  173. data/lib/active_record/relation/where_clause_factory.rb +38 -0
  174. data/lib/active_record/relation.rb +176 -116
  175. data/lib/active_record/result.rb +4 -3
  176. data/lib/active_record/runtime_registry.rb +1 -1
  177. data/lib/active_record/sanitization.rb +95 -66
  178. data/lib/active_record/schema.rb +26 -22
  179. data/lib/active_record/schema_dumper.rb +62 -38
  180. data/lib/active_record/schema_migration.rb +11 -14
  181. data/lib/active_record/scoping/default.rb +23 -9
  182. data/lib/active_record/scoping/named.rb +49 -28
  183. data/lib/active_record/scoping.rb +32 -15
  184. data/lib/active_record/secure_token.rb +38 -0
  185. data/lib/active_record/serialization.rb +2 -4
  186. data/lib/active_record/statement_cache.rb +16 -14
  187. data/lib/active_record/store.rb +8 -3
  188. data/lib/active_record/suppressor.rb +58 -0
  189. data/lib/active_record/table_metadata.rb +68 -0
  190. data/lib/active_record/tasks/database_tasks.rb +57 -43
  191. data/lib/active_record/tasks/mysql_database_tasks.rb +6 -14
  192. data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
  193. data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
  194. data/lib/active_record/timestamp.rb +20 -9
  195. data/lib/active_record/touch_later.rb +58 -0
  196. data/lib/active_record/transactions.rb +138 -56
  197. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  198. data/lib/active_record/type/date.rb +2 -45
  199. data/lib/active_record/type/date_time.rb +2 -49
  200. data/lib/active_record/type/internal/abstract_json.rb +29 -0
  201. data/lib/active_record/type/internal/timezone.rb +15 -0
  202. data/lib/active_record/type/serialized.rb +15 -14
  203. data/lib/active_record/type/time.rb +10 -16
  204. data/lib/active_record/type/type_map.rb +4 -4
  205. data/lib/active_record/type.rb +66 -17
  206. data/lib/active_record/type_caster/connection.rb +29 -0
  207. data/lib/active_record/type_caster/map.rb +19 -0
  208. data/lib/active_record/type_caster.rb +7 -0
  209. data/lib/active_record/validations/absence.rb +23 -0
  210. data/lib/active_record/validations/associated.rb +10 -3
  211. data/lib/active_record/validations/length.rb +24 -0
  212. data/lib/active_record/validations/presence.rb +11 -12
  213. data/lib/active_record/validations/uniqueness.rb +30 -29
  214. data/lib/active_record/validations.rb +33 -32
  215. data/lib/active_record.rb +8 -4
  216. data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
  217. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
  218. data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -1
  219. data/lib/rails/generators/active_record/migration.rb +7 -0
  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 +60 -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
@@ -0,0 +1,51 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module MySQL
4
+ module Quoting # :nodoc:
5
+ QUOTED_TRUE, QUOTED_FALSE = '1', '0'
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
@@ -0,0 +1,67 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module MySQL
4
+ class SchemaCreation < AbstractAdapter::SchemaCreation
5
+ delegate :add_sql_comment!, to: :@conn
6
+ private :add_sql_comment!
7
+
8
+ private
9
+
10
+ def visit_DropForeignKey(name)
11
+ "DROP FOREIGN KEY #{name}"
12
+ end
13
+
14
+ def visit_ColumnDefinition(o)
15
+ o.sql_type = type_to_sql(o.type, o.limit, o.precision, o.scale, o.unsigned)
16
+ super
17
+ end
18
+
19
+ def visit_AddColumnDefinition(o)
20
+ add_column_position!(super, column_options(o.column))
21
+ end
22
+
23
+ def visit_ChangeColumnDefinition(o)
24
+ change_column_sql = "CHANGE #{quote_column_name(o.name)} #{accept(o.column)}"
25
+ add_column_position!(change_column_sql, column_options(o.column))
26
+ end
27
+
28
+ def add_table_options!(create_sql, options)
29
+ add_sql_comment!(super, options[:comment])
30
+ end
31
+
32
+ def column_options(o)
33
+ column_options = super
34
+ column_options[:charset] = o.charset
35
+ column_options
36
+ end
37
+
38
+ def add_column_options!(sql, options)
39
+ if charset = options[:charset]
40
+ sql << " CHARACTER SET #{charset}"
41
+ end
42
+
43
+ if collation = options[:collation]
44
+ sql << " COLLATE #{collation}"
45
+ end
46
+
47
+ add_sql_comment!(super, options[:comment])
48
+ end
49
+
50
+ def add_column_position!(sql, options)
51
+ if options[:first]
52
+ sql << " FIRST"
53
+ elsif options[:after]
54
+ sql << " AFTER #{quote_column_name(options[:after])}"
55
+ end
56
+
57
+ sql
58
+ end
59
+
60
+ def index_in_create(table_name, column_name, options)
61
+ index_name, index_type, index_columns, _, _, index_using, comment = @conn.add_index_options(table_name, column_name, options)
62
+ add_sql_comment!("#{index_type} INDEX #{quote_column_name(index_name)} #{index_using} (#{index_columns})", comment)
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,93 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module MySQL
4
+ module ColumnMethods
5
+ def primary_key(name, type = :primary_key, **options)
6
+ options[:auto_increment] = true if type == :bigint && !options.key?(:default)
7
+ super
8
+ end
9
+
10
+ def blob(*args, **options)
11
+ args.each { |name| column(name, :blob, options) }
12
+ end
13
+
14
+ def tinyblob(*args, **options)
15
+ args.each { |name| column(name, :tinyblob, options) }
16
+ end
17
+
18
+ def mediumblob(*args, **options)
19
+ args.each { |name| column(name, :mediumblob, options) }
20
+ end
21
+
22
+ def longblob(*args, **options)
23
+ args.each { |name| column(name, :longblob, options) }
24
+ end
25
+
26
+ def tinytext(*args, **options)
27
+ args.each { |name| column(name, :tinytext, options) }
28
+ end
29
+
30
+ def mediumtext(*args, **options)
31
+ args.each { |name| column(name, :mediumtext, options) }
32
+ end
33
+
34
+ def longtext(*args, **options)
35
+ args.each { |name| column(name, :longtext, options) }
36
+ end
37
+
38
+ def json(*args, **options)
39
+ args.each { |name| column(name, :json, options) }
40
+ end
41
+
42
+ def unsigned_integer(*args, **options)
43
+ args.each { |name| column(name, :unsigned_integer, options) }
44
+ end
45
+
46
+ def unsigned_bigint(*args, **options)
47
+ args.each { |name| column(name, :unsigned_bigint, options) }
48
+ end
49
+
50
+ def unsigned_float(*args, **options)
51
+ args.each { |name| column(name, :unsigned_float, options) }
52
+ end
53
+
54
+ def unsigned_decimal(*args, **options)
55
+ args.each { |name| column(name, :unsigned_decimal, options) }
56
+ end
57
+ end
58
+
59
+ class ColumnDefinition < ActiveRecord::ConnectionAdapters::ColumnDefinition
60
+ attr_accessor :charset, :unsigned
61
+ end
62
+
63
+ class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
64
+ include ColumnMethods
65
+
66
+ def new_column_definition(name, type, options) # :nodoc:
67
+ column = super
68
+ case column.type
69
+ when :primary_key
70
+ column.type = :integer
71
+ column.auto_increment = true
72
+ when /\Aunsigned_(?<type>.+)\z/
73
+ column.type = $~[:type].to_sym
74
+ column.unsigned = true
75
+ end
76
+ column.unsigned ||= options[:unsigned]
77
+ column.charset = options[:charset]
78
+ column
79
+ end
80
+
81
+ private
82
+
83
+ def create_column_definition(name, type)
84
+ MySQL::ColumnDefinition.new(name, type)
85
+ end
86
+ end
87
+
88
+ class Table < ActiveRecord::ConnectionAdapters::Table
89
+ include ColumnMethods
90
+ end
91
+ end
92
+ end
93
+ end