activerecord 3.2.19 → 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 (264) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1715 -604
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +40 -45
  5. data/examples/performance.rb +33 -22
  6. data/examples/simple.rb +3 -4
  7. data/lib/active_record/aggregations.rb +76 -51
  8. data/lib/active_record/association_relation.rb +35 -0
  9. data/lib/active_record/associations/alias_tracker.rb +54 -40
  10. data/lib/active_record/associations/association.rb +76 -56
  11. data/lib/active_record/associations/association_scope.rb +125 -93
  12. data/lib/active_record/associations/belongs_to_association.rb +57 -28
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -2
  14. data/lib/active_record/associations/builder/association.rb +120 -32
  15. data/lib/active_record/associations/builder/belongs_to.rb +115 -62
  16. data/lib/active_record/associations/builder/collection_association.rb +61 -53
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +117 -43
  18. data/lib/active_record/associations/builder/has_many.rb +9 -65
  19. data/lib/active_record/associations/builder/has_one.rb +18 -52
  20. data/lib/active_record/associations/builder/singular_association.rb +18 -19
  21. data/lib/active_record/associations/collection_association.rb +268 -186
  22. data/lib/active_record/associations/collection_proxy.rb +1003 -63
  23. data/lib/active_record/associations/foreign_association.rb +11 -0
  24. data/lib/active_record/associations/has_many_association.rb +81 -41
  25. data/lib/active_record/associations/has_many_through_association.rb +76 -55
  26. data/lib/active_record/associations/has_one_association.rb +51 -21
  27. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  28. data/lib/active_record/associations/join_dependency/join_association.rb +83 -108
  29. data/lib/active_record/associations/join_dependency/join_base.rb +7 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +30 -37
  31. data/lib/active_record/associations/join_dependency.rb +239 -155
  32. data/lib/active_record/associations/preloader/association.rb +97 -62
  33. data/lib/active_record/associations/preloader/collection_association.rb +2 -8
  34. data/lib/active_record/associations/preloader/has_many_through.rb +7 -3
  35. data/lib/active_record/associations/preloader/has_one.rb +0 -8
  36. data/lib/active_record/associations/preloader/singular_association.rb +3 -3
  37. data/lib/active_record/associations/preloader/through_association.rb +75 -33
  38. data/lib/active_record/associations/preloader.rb +111 -79
  39. data/lib/active_record/associations/singular_association.rb +35 -13
  40. data/lib/active_record/associations/through_association.rb +41 -19
  41. data/lib/active_record/associations.rb +727 -501
  42. data/lib/active_record/attribute/user_provided_default.rb +28 -0
  43. data/lib/active_record/attribute.rb +213 -0
  44. data/lib/active_record/attribute_assignment.rb +32 -162
  45. data/lib/active_record/attribute_decorators.rb +67 -0
  46. data/lib/active_record/attribute_methods/before_type_cast.rb +52 -7
  47. data/lib/active_record/attribute_methods/dirty.rb +101 -61
  48. data/lib/active_record/attribute_methods/primary_key.rb +50 -36
  49. data/lib/active_record/attribute_methods/query.rb +7 -6
  50. data/lib/active_record/attribute_methods/read.rb +56 -117
  51. data/lib/active_record/attribute_methods/serialization.rb +43 -96
  52. data/lib/active_record/attribute_methods/time_zone_conversion.rb +93 -42
  53. data/lib/active_record/attribute_methods/write.rb +34 -45
  54. data/lib/active_record/attribute_methods.rb +333 -144
  55. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  56. data/lib/active_record/attribute_set/builder.rb +108 -0
  57. data/lib/active_record/attribute_set.rb +108 -0
  58. data/lib/active_record/attributes.rb +265 -0
  59. data/lib/active_record/autosave_association.rb +285 -223
  60. data/lib/active_record/base.rb +95 -490
  61. data/lib/active_record/callbacks.rb +95 -61
  62. data/lib/active_record/coders/json.rb +13 -0
  63. data/lib/active_record/coders/yaml_column.rb +28 -19
  64. data/lib/active_record/collection_cache_key.rb +40 -0
  65. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +724 -277
  66. data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
  67. data/lib/active_record/connection_adapters/abstract/database_statements.rb +199 -192
  68. data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -26
  69. data/lib/active_record/connection_adapters/abstract/quoting.rb +140 -57
  70. data/lib/active_record/connection_adapters/abstract/savepoints.rb +21 -0
  71. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +147 -0
  72. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +419 -276
  73. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +105 -0
  74. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +963 -276
  75. data/lib/active_record/connection_adapters/abstract/transaction.rb +232 -0
  76. data/lib/active_record/connection_adapters/abstract_adapter.rb +397 -106
  77. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +643 -342
  78. data/lib/active_record/connection_adapters/column.rb +30 -259
  79. data/lib/active_record/connection_adapters/connection_specification.rb +263 -0
  80. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
  81. data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
  82. data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
  83. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
  84. data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
  85. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
  86. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
  87. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
  88. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
  89. data/lib/active_record/connection_adapters/mysql2_adapter.rb +47 -196
  90. data/lib/active_record/connection_adapters/postgresql/column.rb +15 -0
  91. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +170 -0
  92. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +70 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +15 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +48 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +21 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +19 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +10 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +39 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +93 -0
  109. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +15 -0
  110. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +109 -0
  111. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -0
  112. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
  113. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
  114. data/lib/active_record/connection_adapters/postgresql/oid.rb +31 -0
  115. data/lib/active_record/connection_adapters/postgresql/quoting.rb +116 -0
  116. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +49 -0
  117. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +180 -0
  118. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
  119. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +682 -0
  120. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  121. data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
  122. data/lib/active_record/connection_adapters/postgresql_adapter.rb +558 -1039
  123. data/lib/active_record/connection_adapters/schema_cache.rb +74 -36
  124. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  125. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
  126. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
  127. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  128. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +538 -24
  129. data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
  130. data/lib/active_record/connection_handling.rb +155 -0
  131. data/lib/active_record/core.rb +561 -0
  132. data/lib/active_record/counter_cache.rb +146 -105
  133. data/lib/active_record/dynamic_matchers.rb +101 -64
  134. data/lib/active_record/enum.rb +234 -0
  135. data/lib/active_record/errors.rb +153 -56
  136. data/lib/active_record/explain.rb +15 -63
  137. data/lib/active_record/explain_registry.rb +30 -0
  138. data/lib/active_record/explain_subscriber.rb +10 -6
  139. data/lib/active_record/fixture_set/file.rb +77 -0
  140. data/lib/active_record/fixtures.rb +355 -232
  141. data/lib/active_record/gem_version.rb +15 -0
  142. data/lib/active_record/inheritance.rb +144 -79
  143. data/lib/active_record/integration.rb +66 -13
  144. data/lib/active_record/internal_metadata.rb +56 -0
  145. data/lib/active_record/legacy_yaml_adapter.rb +46 -0
  146. data/lib/active_record/locale/en.yml +9 -1
  147. data/lib/active_record/locking/optimistic.rb +77 -56
  148. data/lib/active_record/locking/pessimistic.rb +6 -6
  149. data/lib/active_record/log_subscriber.rb +53 -28
  150. data/lib/active_record/migration/command_recorder.rb +166 -33
  151. data/lib/active_record/migration/compatibility.rb +126 -0
  152. data/lib/active_record/migration/join_table.rb +15 -0
  153. data/lib/active_record/migration.rb +792 -264
  154. data/lib/active_record/model_schema.rb +192 -130
  155. data/lib/active_record/nested_attributes.rb +238 -145
  156. data/lib/active_record/no_touching.rb +52 -0
  157. data/lib/active_record/null_relation.rb +89 -0
  158. data/lib/active_record/persistence.rb +357 -157
  159. data/lib/active_record/query_cache.rb +22 -43
  160. data/lib/active_record/querying.rb +34 -23
  161. data/lib/active_record/railtie.rb +88 -48
  162. data/lib/active_record/railties/console_sandbox.rb +3 -4
  163. data/lib/active_record/railties/controller_runtime.rb +5 -4
  164. data/lib/active_record/railties/databases.rake +170 -422
  165. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  166. data/lib/active_record/readonly_attributes.rb +2 -5
  167. data/lib/active_record/reflection.rb +715 -189
  168. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  169. data/lib/active_record/relation/batches.rb +203 -50
  170. data/lib/active_record/relation/calculations.rb +203 -194
  171. data/lib/active_record/relation/delegation.rb +103 -25
  172. data/lib/active_record/relation/finder_methods.rb +457 -261
  173. data/lib/active_record/relation/from_clause.rb +32 -0
  174. data/lib/active_record/relation/merger.rb +167 -0
  175. data/lib/active_record/relation/predicate_builder/array_handler.rb +43 -0
  176. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
  177. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  178. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  179. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  180. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
  181. data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
  182. data/lib/active_record/relation/predicate_builder/relation_handler.rb +13 -0
  183. data/lib/active_record/relation/predicate_builder.rb +153 -48
  184. data/lib/active_record/relation/query_attribute.rb +19 -0
  185. data/lib/active_record/relation/query_methods.rb +1019 -194
  186. data/lib/active_record/relation/record_fetch_warning.rb +49 -0
  187. data/lib/active_record/relation/spawn_methods.rb +46 -150
  188. data/lib/active_record/relation/where_clause.rb +174 -0
  189. data/lib/active_record/relation/where_clause_factory.rb +38 -0
  190. data/lib/active_record/relation.rb +450 -245
  191. data/lib/active_record/result.rb +104 -12
  192. data/lib/active_record/runtime_registry.rb +22 -0
  193. data/lib/active_record/sanitization.rb +120 -94
  194. data/lib/active_record/schema.rb +28 -18
  195. data/lib/active_record/schema_dumper.rb +141 -74
  196. data/lib/active_record/schema_migration.rb +50 -0
  197. data/lib/active_record/scoping/default.rb +64 -57
  198. data/lib/active_record/scoping/named.rb +93 -108
  199. data/lib/active_record/scoping.rb +73 -121
  200. data/lib/active_record/secure_token.rb +38 -0
  201. data/lib/active_record/serialization.rb +7 -5
  202. data/lib/active_record/statement_cache.rb +113 -0
  203. data/lib/active_record/store.rb +173 -15
  204. data/lib/active_record/suppressor.rb +58 -0
  205. data/lib/active_record/table_metadata.rb +68 -0
  206. data/lib/active_record/tasks/database_tasks.rb +313 -0
  207. data/lib/active_record/tasks/mysql_database_tasks.rb +151 -0
  208. data/lib/active_record/tasks/postgresql_database_tasks.rb +110 -0
  209. data/lib/active_record/tasks/sqlite_database_tasks.rb +59 -0
  210. data/lib/active_record/timestamp.rb +42 -24
  211. data/lib/active_record/touch_later.rb +58 -0
  212. data/lib/active_record/transactions.rb +233 -105
  213. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  214. data/lib/active_record/type/date.rb +7 -0
  215. data/lib/active_record/type/date_time.rb +7 -0
  216. data/lib/active_record/type/hash_lookup_type_map.rb +23 -0
  217. data/lib/active_record/type/internal/abstract_json.rb +29 -0
  218. data/lib/active_record/type/internal/timezone.rb +15 -0
  219. data/lib/active_record/type/serialized.rb +63 -0
  220. data/lib/active_record/type/time.rb +20 -0
  221. data/lib/active_record/type/type_map.rb +64 -0
  222. data/lib/active_record/type.rb +72 -0
  223. data/lib/active_record/type_caster/connection.rb +29 -0
  224. data/lib/active_record/type_caster/map.rb +19 -0
  225. data/lib/active_record/type_caster.rb +7 -0
  226. data/lib/active_record/validations/absence.rb +23 -0
  227. data/lib/active_record/validations/associated.rb +33 -18
  228. data/lib/active_record/validations/length.rb +24 -0
  229. data/lib/active_record/validations/presence.rb +66 -0
  230. data/lib/active_record/validations/uniqueness.rb +128 -68
  231. data/lib/active_record/validations.rb +48 -40
  232. data/lib/active_record/version.rb +5 -7
  233. data/lib/active_record.rb +71 -47
  234. data/lib/rails/generators/active_record/migration/migration_generator.rb +56 -8
  235. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +24 -0
  236. data/lib/rails/generators/active_record/migration/templates/migration.rb +28 -16
  237. data/lib/rails/generators/active_record/migration.rb +18 -8
  238. data/lib/rails/generators/active_record/model/model_generator.rb +38 -16
  239. data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
  240. data/lib/rails/generators/active_record/model/templates/model.rb +7 -6
  241. data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
  242. data/lib/rails/generators/active_record.rb +3 -11
  243. metadata +188 -134
  244. data/examples/associations.png +0 -0
  245. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -63
  246. data/lib/active_record/associations/join_helper.rb +0 -55
  247. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
  248. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
  249. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
  250. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -441
  251. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
  252. data/lib/active_record/dynamic_finder_match.rb +0 -68
  253. data/lib/active_record/dynamic_scope_match.rb +0 -23
  254. data/lib/active_record/fixtures/file.rb +0 -65
  255. data/lib/active_record/identity_map.rb +0 -162
  256. data/lib/active_record/observer.rb +0 -121
  257. data/lib/active_record/serializers/xml_serializer.rb +0 -203
  258. data/lib/active_record/session_store.rb +0 -360
  259. data/lib/active_record/test_case.rb +0 -73
  260. data/lib/rails/generators/active_record/model/templates/migration.rb +0 -15
  261. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  262. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  263. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  264. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -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
@@ -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