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
@@ -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
@@ -0,0 +1,54 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module MySQL
4
+ module ColumnDumper
5
+ def column_spec_for_primary_key(column)
6
+ if column.bigint?
7
+ spec = { id: :bigint.inspect }
8
+ spec[:default] = schema_default(column) || 'nil' unless column.auto_increment?
9
+ else
10
+ spec = super
11
+ end
12
+ spec[:unsigned] = 'true' if column.unsigned?
13
+ spec
14
+ end
15
+
16
+ def prepare_column_options(column)
17
+ spec = super
18
+ spec[:unsigned] = 'true' if column.unsigned?
19
+ spec
20
+ end
21
+
22
+ def migration_keys
23
+ super + [:unsigned]
24
+ end
25
+
26
+ private
27
+
28
+ def default_primary_key?(column)
29
+ super && column.auto_increment?
30
+ end
31
+
32
+ def schema_type(column)
33
+ if column.sql_type == 'tinyblob'
34
+ :blob
35
+ else
36
+ super
37
+ end
38
+ end
39
+
40
+ def schema_precision(column)
41
+ super unless /time/ === column.sql_type && column.precision == 0
42
+ end
43
+
44
+ def schema_collation(column)
45
+ if column.collation && table_name = column.table_name
46
+ @table_collation_cache ||= {}
47
+ @table_collation_cache[table_name] ||= select_one("SHOW TABLE STATUS LIKE '#{table_name}'")["Collation"]
48
+ column.collation.inspect if column.collation != @table_collation_cache[table_name]
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,32 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module MySQL
4
+ class TypeMetadata < DelegateClass(SqlTypeMetadata) # :nodoc:
5
+ attr_reader :extra, :strict
6
+
7
+ def initialize(type_metadata, extra: "", strict: false)
8
+ super(type_metadata)
9
+ @type_metadata = type_metadata
10
+ @extra = extra
11
+ @strict = strict
12
+ end
13
+
14
+ def ==(other)
15
+ other.is_a?(MySQL::TypeMetadata) &&
16
+ attributes_for_hash == other.attributes_for_hash
17
+ end
18
+ alias eql? ==
19
+
20
+ def hash
21
+ attributes_for_hash.hash
22
+ end
23
+
24
+ protected
25
+
26
+ def attributes_for_hash
27
+ [self.class, @type_metadata, extra, strict]
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,7 +1,9 @@
1
1
  require 'active_record/connection_adapters/abstract_mysql_adapter'
2
+ require 'active_record/connection_adapters/mysql/database_statements'
2
3
 
3
- gem 'mysql2', '>= 0.3.13', '< 0.6.0'
4
+ gem 'mysql2', '>= 0.3.18', '< 0.5'
4
5
  require 'mysql2'
6
+ raise 'mysql2 0.4.3 is not supported. Please upgrade to 0.4.4+' if Mysql2::VERSION == '0.4.3'
5
7
 
6
8
  module ActiveRecord
7
9
  module ConnectionHandling # :nodoc:
@@ -10,17 +12,21 @@ module ActiveRecord
10
12
  config = config.symbolize_keys
11
13
 
12
14
  config[:username] = 'root' if config[:username].nil?
15
+ config[:flags] ||= 0
13
16
 
14
17
  if Mysql2::Client.const_defined? :FOUND_ROWS
15
- config[:flags] = Mysql2::Client::FOUND_ROWS
18
+ if config[:flags].kind_of? Array
19
+ config[:flags].push "FOUND_ROWS".freeze
20
+ else
21
+ config[:flags] |= Mysql2::Client::FOUND_ROWS
22
+ end
16
23
  end
17
24
 
18
25
  client = Mysql2::Client.new(config)
19
- options = [config[:host], config[:username], config[:password], config[:database], config[:port], config[:socket], 0]
20
- ConnectionAdapters::Mysql2Adapter.new(client, logger, options, config)
26
+ ConnectionAdapters::Mysql2Adapter.new(client, logger, nil, config)
21
27
  rescue Mysql2::Error => error
22
28
  if error.message.include?("Unknown database")
23
- raise ActiveRecord::NoDatabaseError.new(error.message, error)
29
+ raise ActiveRecord::NoDatabaseError
24
30
  else
25
31
  raise
26
32
  end
@@ -31,22 +37,27 @@ module ActiveRecord
31
37
  class Mysql2Adapter < AbstractMysqlAdapter
32
38
  ADAPTER_NAME = 'Mysql2'.freeze
33
39
 
40
+ include MySQL::DatabaseStatements
41
+
34
42
  def initialize(connection, logger, connection_options, config)
35
43
  super
36
- @prepared_statements = false
44
+ @prepared_statements = false unless config.key?(:prepared_statements)
37
45
  configure_connection
38
46
  end
39
47
 
40
- MAX_INDEX_LENGTH_FOR_UTF8MB4 = 191
41
- def initialize_schema_migrations_table
42
- if charset == 'utf8mb4'
43
- ActiveRecord::SchemaMigration.create_table(MAX_INDEX_LENGTH_FOR_UTF8MB4)
44
- else
45
- ActiveRecord::SchemaMigration.create_table
46
- end
48
+ def supports_json?
49
+ !mariadb? && version >= '5.7.8'
50
+ end
51
+
52
+ def supports_comments?
53
+ true
47
54
  end
48
55
 
49
- def supports_explain?
56
+ def supports_comments_in_create?
57
+ true
58
+ end
59
+
60
+ def supports_savepoints?
50
61
  true
51
62
  end
52
63
 
@@ -79,6 +90,7 @@ module ActiveRecord
79
90
  #++
80
91
 
81
92
  def active?
93
+ return false unless @connection
82
94
  @connection.ping
83
95
  end
84
96
 
@@ -93,155 +105,10 @@ module ActiveRecord
93
105
  # Otherwise, this method does nothing.
94
106
  def disconnect!
95
107
  super
96
- @connection.close
97
- end
98
-
99
- #--
100
- # DATABASE STATEMENTS ======================================
101
- #++
102
-
103
- def explain(arel, binds = [])
104
- sql = "EXPLAIN #{to_sql(arel, binds.dup)}"
105
- start = Time.now
106
- result = exec_query(sql, 'EXPLAIN', binds)
107
- elapsed = Time.now - start
108
-
109
- ExplainPrettyPrinter.new.pp(result, elapsed)
110
- end
111
-
112
- class ExplainPrettyPrinter # :nodoc:
113
- # Pretty prints the result of a EXPLAIN in a way that resembles the output of the
114
- # MySQL shell:
115
- #
116
- # +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
117
- # | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
118
- # +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
119
- # | 1 | SIMPLE | users | const | PRIMARY | PRIMARY | 4 | const | 1 | |
120
- # | 1 | SIMPLE | posts | ALL | NULL | NULL | NULL | NULL | 1 | Using where |
121
- # +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
122
- # 2 rows in set (0.00 sec)
123
- #
124
- # This is an exercise in Ruby hyperrealism :).
125
- def pp(result, elapsed)
126
- widths = compute_column_widths(result)
127
- separator = build_separator(widths)
128
-
129
- pp = []
130
-
131
- pp << separator
132
- pp << build_cells(result.columns, widths)
133
- pp << separator
134
-
135
- result.rows.each do |row|
136
- pp << build_cells(row, widths)
137
- end
138
-
139
- pp << separator
140
- pp << build_footer(result.rows.length, elapsed)
141
-
142
- pp.join("\n") + "\n"
143
- end
144
-
145
- private
146
-
147
- def compute_column_widths(result)
148
- [].tap do |widths|
149
- result.columns.each_with_index do |column, i|
150
- cells_in_column = [column] + result.rows.map {|r| r[i].nil? ? 'NULL' : r[i].to_s}
151
- widths << cells_in_column.map(&:length).max
152
- end
153
- end
108
+ unless @connection.nil?
109
+ @connection.close
110
+ @connection = nil
154
111
  end
155
-
156
- def build_separator(widths)
157
- padding = 1
158
- '+' + widths.map {|w| '-' * (w + (padding*2))}.join('+') + '+'
159
- end
160
-
161
- def build_cells(items, widths)
162
- cells = []
163
- items.each_with_index do |item, i|
164
- item = 'NULL' if item.nil?
165
- justifier = item.is_a?(Numeric) ? 'rjust' : 'ljust'
166
- cells << item.to_s.send(justifier, widths[i])
167
- end
168
- '| ' + cells.join(' | ') + ' |'
169
- end
170
-
171
- def build_footer(nrows, elapsed)
172
- rows_label = nrows == 1 ? 'row' : 'rows'
173
- "#{nrows} #{rows_label} in set (%.2f sec)" % elapsed
174
- end
175
- end
176
-
177
- # FIXME: re-enable the following once a "better" query_cache solution is in core
178
- #
179
- # The overrides below perform much better than the originals in AbstractAdapter
180
- # because we're able to take advantage of mysql2's lazy-loading capabilities
181
- #
182
- # # Returns a record hash with the column names as keys and column values
183
- # # as values.
184
- # def select_one(sql, name = nil)
185
- # result = execute(sql, name)
186
- # result.each(as: :hash) do |r|
187
- # return r
188
- # end
189
- # end
190
- #
191
- # # Returns a single value from a record
192
- # def select_value(sql, name = nil)
193
- # result = execute(sql, name)
194
- # if first = result.first
195
- # first.first
196
- # end
197
- # end
198
- #
199
- # # Returns an array of the values of the first column in a select:
200
- # # select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
201
- # def select_values(sql, name = nil)
202
- # execute(sql, name).map { |row| row.first }
203
- # end
204
-
205
- # Returns an array of arrays containing the field values.
206
- # Order is the same as that returned by +columns+.
207
- def select_rows(sql, name = nil, binds = [])
208
- execute(sql, name).to_a
209
- end
210
-
211
- # Executes the SQL statement in the context of this connection.
212
- def execute(sql, name = nil)
213
- # make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
214
- # made since we established the connection
215
- @connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
216
-
217
- super
218
- end
219
-
220
- def exec_query(sql, name = 'SQL', binds = [])
221
- result = execute(sql, name)
222
- ActiveRecord::Result.new(result.fields, result.to_a)
223
- end
224
-
225
- alias exec_without_stmt exec_query
226
-
227
- def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
228
- super
229
- id_value || @connection.last_id
230
- end
231
- alias :create :insert_sql
232
-
233
- def exec_insert(sql, name, binds, pk = nil, sequence_name = nil)
234
- execute to_sql(sql, binds), name
235
- end
236
-
237
- def exec_delete(sql, name, binds)
238
- execute to_sql(sql, binds), name
239
- @connection.affected_rows
240
- end
241
- alias :exec_update :exec_delete
242
-
243
- def last_inserted_id(result)
244
- @connection.last_id
245
112
  end
246
113
 
247
114
  private
@@ -259,10 +126,6 @@ module ActiveRecord
259
126
  def full_version
260
127
  @full_version ||= @connection.server_info[:version]
261
128
  end
262
-
263
- def set_field_encoding field_name
264
- field_name
265
- end
266
129
  end
267
130
  end
268
131
  end