activerecord 6.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 (340) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1013 -0
  3. data/MIT-LICENSE +22 -0
  4. data/README.rdoc +219 -0
  5. data/examples/performance.rb +185 -0
  6. data/examples/simple.rb +15 -0
  7. data/lib/active_record.rb +195 -0
  8. data/lib/active_record/aggregations.rb +285 -0
  9. data/lib/active_record/association_relation.rb +40 -0
  10. data/lib/active_record/associations.rb +1865 -0
  11. data/lib/active_record/associations/alias_tracker.rb +81 -0
  12. data/lib/active_record/associations/association.rb +332 -0
  13. data/lib/active_record/associations/association_scope.rb +166 -0
  14. data/lib/active_record/associations/belongs_to_association.rb +124 -0
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +36 -0
  16. data/lib/active_record/associations/builder/association.rb +136 -0
  17. data/lib/active_record/associations/builder/belongs_to.rb +130 -0
  18. data/lib/active_record/associations/builder/collection_association.rb +72 -0
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +114 -0
  20. data/lib/active_record/associations/builder/has_many.rb +19 -0
  21. data/lib/active_record/associations/builder/has_one.rb +64 -0
  22. data/lib/active_record/associations/builder/singular_association.rb +44 -0
  23. data/lib/active_record/associations/collection_association.rb +498 -0
  24. data/lib/active_record/associations/collection_proxy.rb +1128 -0
  25. data/lib/active_record/associations/foreign_association.rb +20 -0
  26. data/lib/active_record/associations/has_many_association.rb +136 -0
  27. data/lib/active_record/associations/has_many_through_association.rb +220 -0
  28. data/lib/active_record/associations/has_one_association.rb +118 -0
  29. data/lib/active_record/associations/has_one_through_association.rb +45 -0
  30. data/lib/active_record/associations/join_dependency.rb +258 -0
  31. data/lib/active_record/associations/join_dependency/join_association.rb +80 -0
  32. data/lib/active_record/associations/join_dependency/join_base.rb +23 -0
  33. data/lib/active_record/associations/join_dependency/join_part.rb +71 -0
  34. data/lib/active_record/associations/preloader.rb +201 -0
  35. data/lib/active_record/associations/preloader/association.rb +133 -0
  36. data/lib/active_record/associations/preloader/through_association.rb +116 -0
  37. data/lib/active_record/associations/singular_association.rb +59 -0
  38. data/lib/active_record/associations/through_association.rb +121 -0
  39. data/lib/active_record/attribute_assignment.rb +85 -0
  40. data/lib/active_record/attribute_decorators.rb +90 -0
  41. data/lib/active_record/attribute_methods.rb +420 -0
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +81 -0
  43. data/lib/active_record/attribute_methods/dirty.rb +221 -0
  44. data/lib/active_record/attribute_methods/primary_key.rb +136 -0
  45. data/lib/active_record/attribute_methods/query.rb +41 -0
  46. data/lib/active_record/attribute_methods/read.rb +47 -0
  47. data/lib/active_record/attribute_methods/serialization.rb +90 -0
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +91 -0
  49. data/lib/active_record/attribute_methods/write.rb +61 -0
  50. data/lib/active_record/attributes.rb +279 -0
  51. data/lib/active_record/autosave_association.rb +508 -0
  52. data/lib/active_record/base.rb +328 -0
  53. data/lib/active_record/callbacks.rb +339 -0
  54. data/lib/active_record/coders/json.rb +15 -0
  55. data/lib/active_record/coders/yaml_column.rb +50 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +1165 -0
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +85 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +512 -0
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +154 -0
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +251 -0
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +713 -0
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +93 -0
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1475 -0
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +323 -0
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +761 -0
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +821 -0
  69. data/lib/active_record/connection_adapters/column.rb +95 -0
  70. data/lib/active_record/connection_adapters/connection_specification.rb +297 -0
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +200 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +146 -0
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -0
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +182 -0
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +92 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +53 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +23 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +41 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +113 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +26 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +205 -0
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +222 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +776 -0
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +949 -0
  117. data/lib/active_record/connection_adapters/schema_cache.rb +141 -0
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
  119. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
  120. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  121. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  126. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +557 -0
  127. data/lib/active_record/connection_adapters/statement_pool.rb +61 -0
  128. data/lib/active_record/connection_handling.rb +267 -0
  129. data/lib/active_record/core.rb +599 -0
  130. data/lib/active_record/counter_cache.rb +193 -0
  131. data/lib/active_record/database_configurations.rb +233 -0
  132. data/lib/active_record/database_configurations/database_config.rb +37 -0
  133. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  134. data/lib/active_record/database_configurations/url_config.rb +79 -0
  135. data/lib/active_record/define_callbacks.rb +22 -0
  136. data/lib/active_record/dynamic_matchers.rb +122 -0
  137. data/lib/active_record/enum.rb +274 -0
  138. data/lib/active_record/errors.rb +388 -0
  139. data/lib/active_record/explain.rb +50 -0
  140. data/lib/active_record/explain_registry.rb +32 -0
  141. data/lib/active_record/explain_subscriber.rb +34 -0
  142. data/lib/active_record/fixture_set/file.rb +82 -0
  143. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  144. data/lib/active_record/fixture_set/render_context.rb +17 -0
  145. data/lib/active_record/fixture_set/table_row.rb +153 -0
  146. data/lib/active_record/fixture_set/table_rows.rb +47 -0
  147. data/lib/active_record/fixtures.rb +738 -0
  148. data/lib/active_record/gem_version.rb +17 -0
  149. data/lib/active_record/inheritance.rb +293 -0
  150. data/lib/active_record/insert_all.rb +179 -0
  151. data/lib/active_record/integration.rb +207 -0
  152. data/lib/active_record/internal_metadata.rb +53 -0
  153. data/lib/active_record/legacy_yaml_adapter.rb +48 -0
  154. data/lib/active_record/locale/en.yml +48 -0
  155. data/lib/active_record/locking/optimistic.rb +197 -0
  156. data/lib/active_record/locking/pessimistic.rb +89 -0
  157. data/lib/active_record/log_subscriber.rb +118 -0
  158. data/lib/active_record/middleware/database_selector.rb +75 -0
  159. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  160. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  161. data/lib/active_record/migration.rb +1397 -0
  162. data/lib/active_record/migration/command_recorder.rb +284 -0
  163. data/lib/active_record/migration/compatibility.rb +244 -0
  164. data/lib/active_record/migration/join_table.rb +17 -0
  165. data/lib/active_record/model_schema.rb +542 -0
  166. data/lib/active_record/nested_attributes.rb +600 -0
  167. data/lib/active_record/no_touching.rb +65 -0
  168. data/lib/active_record/null_relation.rb +68 -0
  169. data/lib/active_record/persistence.rb +967 -0
  170. data/lib/active_record/query_cache.rb +52 -0
  171. data/lib/active_record/querying.rb +82 -0
  172. data/lib/active_record/railtie.rb +263 -0
  173. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  174. data/lib/active_record/railties/console_sandbox.rb +7 -0
  175. data/lib/active_record/railties/controller_runtime.rb +51 -0
  176. data/lib/active_record/railties/databases.rake +527 -0
  177. data/lib/active_record/readonly_attributes.rb +24 -0
  178. data/lib/active_record/reflection.rb +1042 -0
  179. data/lib/active_record/relation.rb +859 -0
  180. data/lib/active_record/relation/batches.rb +290 -0
  181. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  182. data/lib/active_record/relation/calculations.rb +424 -0
  183. data/lib/active_record/relation/delegation.rb +130 -0
  184. data/lib/active_record/relation/finder_methods.rb +552 -0
  185. data/lib/active_record/relation/from_clause.rb +26 -0
  186. data/lib/active_record/relation/merger.rb +184 -0
  187. data/lib/active_record/relation/predicate_builder.rb +150 -0
  188. data/lib/active_record/relation/predicate_builder/array_handler.rb +49 -0
  189. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  190. data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
  191. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  192. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  193. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  194. data/lib/active_record/relation/predicate_builder/relation_handler.rb +19 -0
  195. data/lib/active_record/relation/query_attribute.rb +50 -0
  196. data/lib/active_record/relation/query_methods.rb +1359 -0
  197. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  198. data/lib/active_record/relation/spawn_methods.rb +77 -0
  199. data/lib/active_record/relation/where_clause.rb +190 -0
  200. data/lib/active_record/relation/where_clause_factory.rb +33 -0
  201. data/lib/active_record/result.rb +168 -0
  202. data/lib/active_record/runtime_registry.rb +24 -0
  203. data/lib/active_record/sanitization.rb +214 -0
  204. data/lib/active_record/schema.rb +61 -0
  205. data/lib/active_record/schema_dumper.rb +270 -0
  206. data/lib/active_record/schema_migration.rb +60 -0
  207. data/lib/active_record/scoping.rb +106 -0
  208. data/lib/active_record/scoping/default.rb +151 -0
  209. data/lib/active_record/scoping/named.rb +217 -0
  210. data/lib/active_record/secure_token.rb +40 -0
  211. data/lib/active_record/serialization.rb +22 -0
  212. data/lib/active_record/statement_cache.rb +148 -0
  213. data/lib/active_record/store.rb +290 -0
  214. data/lib/active_record/suppressor.rb +61 -0
  215. data/lib/active_record/table_metadata.rb +75 -0
  216. data/lib/active_record/tasks/database_tasks.rb +506 -0
  217. data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
  218. data/lib/active_record/tasks/postgresql_database_tasks.rb +141 -0
  219. data/lib/active_record/tasks/sqlite_database_tasks.rb +77 -0
  220. data/lib/active_record/test_databases.rb +23 -0
  221. data/lib/active_record/test_fixtures.rb +224 -0
  222. data/lib/active_record/timestamp.rb +167 -0
  223. data/lib/active_record/touch_later.rb +66 -0
  224. data/lib/active_record/transactions.rb +493 -0
  225. data/lib/active_record/translation.rb +24 -0
  226. data/lib/active_record/type.rb +78 -0
  227. data/lib/active_record/type/adapter_specific_registry.rb +129 -0
  228. data/lib/active_record/type/date.rb +9 -0
  229. data/lib/active_record/type/date_time.rb +9 -0
  230. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  231. data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
  232. data/lib/active_record/type/internal/timezone.rb +17 -0
  233. data/lib/active_record/type/json.rb +30 -0
  234. data/lib/active_record/type/serialized.rb +71 -0
  235. data/lib/active_record/type/text.rb +11 -0
  236. data/lib/active_record/type/time.rb +21 -0
  237. data/lib/active_record/type/type_map.rb +62 -0
  238. data/lib/active_record/type/unsigned_integer.rb +17 -0
  239. data/lib/active_record/type_caster.rb +9 -0
  240. data/lib/active_record/type_caster/connection.rb +34 -0
  241. data/lib/active_record/type_caster/map.rb +20 -0
  242. data/lib/active_record/validations.rb +94 -0
  243. data/lib/active_record/validations/absence.rb +25 -0
  244. data/lib/active_record/validations/associated.rb +60 -0
  245. data/lib/active_record/validations/length.rb +26 -0
  246. data/lib/active_record/validations/presence.rb +68 -0
  247. data/lib/active_record/validations/uniqueness.rb +226 -0
  248. data/lib/active_record/version.rb +10 -0
  249. data/lib/arel.rb +51 -0
  250. data/lib/arel/alias_predication.rb +9 -0
  251. data/lib/arel/attributes.rb +22 -0
  252. data/lib/arel/attributes/attribute.rb +37 -0
  253. data/lib/arel/collectors/bind.rb +24 -0
  254. data/lib/arel/collectors/composite.rb +31 -0
  255. data/lib/arel/collectors/plain_string.rb +20 -0
  256. data/lib/arel/collectors/sql_string.rb +20 -0
  257. data/lib/arel/collectors/substitute_binds.rb +28 -0
  258. data/lib/arel/crud.rb +42 -0
  259. data/lib/arel/delete_manager.rb +18 -0
  260. data/lib/arel/errors.rb +9 -0
  261. data/lib/arel/expressions.rb +29 -0
  262. data/lib/arel/factory_methods.rb +49 -0
  263. data/lib/arel/insert_manager.rb +49 -0
  264. data/lib/arel/math.rb +45 -0
  265. data/lib/arel/nodes.rb +68 -0
  266. data/lib/arel/nodes/and.rb +32 -0
  267. data/lib/arel/nodes/ascending.rb +23 -0
  268. data/lib/arel/nodes/binary.rb +52 -0
  269. data/lib/arel/nodes/bind_param.rb +36 -0
  270. data/lib/arel/nodes/case.rb +55 -0
  271. data/lib/arel/nodes/casted.rb +50 -0
  272. data/lib/arel/nodes/comment.rb +29 -0
  273. data/lib/arel/nodes/count.rb +12 -0
  274. data/lib/arel/nodes/delete_statement.rb +45 -0
  275. data/lib/arel/nodes/descending.rb +23 -0
  276. data/lib/arel/nodes/equality.rb +18 -0
  277. data/lib/arel/nodes/extract.rb +24 -0
  278. data/lib/arel/nodes/false.rb +16 -0
  279. data/lib/arel/nodes/full_outer_join.rb +8 -0
  280. data/lib/arel/nodes/function.rb +44 -0
  281. data/lib/arel/nodes/grouping.rb +8 -0
  282. data/lib/arel/nodes/in.rb +8 -0
  283. data/lib/arel/nodes/infix_operation.rb +80 -0
  284. data/lib/arel/nodes/inner_join.rb +8 -0
  285. data/lib/arel/nodes/insert_statement.rb +37 -0
  286. data/lib/arel/nodes/join_source.rb +20 -0
  287. data/lib/arel/nodes/matches.rb +18 -0
  288. data/lib/arel/nodes/named_function.rb +23 -0
  289. data/lib/arel/nodes/node.rb +50 -0
  290. data/lib/arel/nodes/node_expression.rb +13 -0
  291. data/lib/arel/nodes/outer_join.rb +8 -0
  292. data/lib/arel/nodes/over.rb +15 -0
  293. data/lib/arel/nodes/regexp.rb +16 -0
  294. data/lib/arel/nodes/right_outer_join.rb +8 -0
  295. data/lib/arel/nodes/select_core.rb +67 -0
  296. data/lib/arel/nodes/select_statement.rb +41 -0
  297. data/lib/arel/nodes/sql_literal.rb +16 -0
  298. data/lib/arel/nodes/string_join.rb +11 -0
  299. data/lib/arel/nodes/table_alias.rb +27 -0
  300. data/lib/arel/nodes/terminal.rb +16 -0
  301. data/lib/arel/nodes/true.rb +16 -0
  302. data/lib/arel/nodes/unary.rb +45 -0
  303. data/lib/arel/nodes/unary_operation.rb +20 -0
  304. data/lib/arel/nodes/unqualified_column.rb +22 -0
  305. data/lib/arel/nodes/update_statement.rb +41 -0
  306. data/lib/arel/nodes/values_list.rb +9 -0
  307. data/lib/arel/nodes/window.rb +126 -0
  308. data/lib/arel/nodes/with.rb +11 -0
  309. data/lib/arel/order_predications.rb +13 -0
  310. data/lib/arel/predications.rb +257 -0
  311. data/lib/arel/select_manager.rb +271 -0
  312. data/lib/arel/table.rb +110 -0
  313. data/lib/arel/tree_manager.rb +72 -0
  314. data/lib/arel/update_manager.rb +34 -0
  315. data/lib/arel/visitors.rb +20 -0
  316. data/lib/arel/visitors/depth_first.rb +204 -0
  317. data/lib/arel/visitors/dot.rb +297 -0
  318. data/lib/arel/visitors/ibm_db.rb +34 -0
  319. data/lib/arel/visitors/informix.rb +62 -0
  320. data/lib/arel/visitors/mssql.rb +157 -0
  321. data/lib/arel/visitors/mysql.rb +83 -0
  322. data/lib/arel/visitors/oracle.rb +159 -0
  323. data/lib/arel/visitors/oracle12.rb +66 -0
  324. data/lib/arel/visitors/postgresql.rb +110 -0
  325. data/lib/arel/visitors/sqlite.rb +39 -0
  326. data/lib/arel/visitors/to_sql.rb +889 -0
  327. data/lib/arel/visitors/visitor.rb +46 -0
  328. data/lib/arel/visitors/where_sql.rb +23 -0
  329. data/lib/arel/window_predications.rb +9 -0
  330. data/lib/rails/generators/active_record.rb +19 -0
  331. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  332. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  333. data/lib/rails/generators/active_record/migration.rb +48 -0
  334. data/lib/rails/generators/active_record/migration/migration_generator.rb +75 -0
  335. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  336. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +48 -0
  337. data/lib/rails/generators/active_record/model/model_generator.rb +49 -0
  338. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  339. data/lib/rails/generators/active_record/model/templates/module.rb.tt +7 -0
  340. metadata +415 -0
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ module MySQL
6
+ class SchemaDumper < ConnectionAdapters::SchemaDumper # :nodoc:
7
+ private
8
+ def prepare_column_options(column)
9
+ spec = super
10
+ spec[:unsigned] = "true" if column.unsigned?
11
+ spec[:auto_increment] = "true" if column.auto_increment?
12
+
13
+ if /\A(?<size>tiny|medium|long)(?:text|blob)/ =~ column.sql_type
14
+ spec = { size: size.to_sym.inspect }.merge!(spec)
15
+ end
16
+
17
+ if @connection.supports_virtual_columns? && column.virtual?
18
+ spec[:as] = extract_expression_for_virtual_column(column)
19
+ spec[:stored] = "true" if /\b(?:STORED|PERSISTENT)\b/.match?(column.extra)
20
+ spec = { type: schema_type(column).inspect }.merge!(spec)
21
+ end
22
+
23
+ spec
24
+ end
25
+
26
+ def column_spec_for_primary_key(column)
27
+ spec = super
28
+ spec.delete(:auto_increment) if column.type == :integer && column.auto_increment?
29
+ spec
30
+ end
31
+
32
+ def default_primary_key?(column)
33
+ super && column.auto_increment? && !column.unsigned?
34
+ end
35
+
36
+ def explicit_primary_key_default?(column)
37
+ column.type == :integer && !column.auto_increment?
38
+ end
39
+
40
+ def schema_type(column)
41
+ case column.sql_type
42
+ when /\Atimestamp\b/
43
+ :timestamp
44
+ when /\A(?:enum|set)\b/
45
+ column.sql_type
46
+ else
47
+ super
48
+ end
49
+ end
50
+
51
+ def schema_limit(column)
52
+ super unless /\A(?:enum|set|(?:tiny|medium|long)?(?:text|blob))\b/.match?(column.sql_type)
53
+ end
54
+
55
+ def schema_precision(column)
56
+ super unless /\A(?:date)?time(?:stamp)?\b/.match?(column.sql_type) && column.precision == 0
57
+ end
58
+
59
+ def schema_collation(column)
60
+ if column.collation
61
+ @table_collation_cache ||= {}
62
+ @table_collation_cache[table_name] ||=
63
+ @connection.exec_query("SHOW TABLE STATUS LIKE #{@connection.quote(table_name)}", "SCHEMA").first["Collation"]
64
+ column.collation.inspect if column.collation != @table_collation_cache[table_name]
65
+ end
66
+ end
67
+
68
+ def extract_expression_for_virtual_column(column)
69
+ if @connection.mariadb? && @connection.database_version < "10.2.5"
70
+ create_table_info = @connection.send(:create_table_info, table_name)
71
+ column_name = @connection.quote_column_name(column.name)
72
+ if %r/#{column_name} #{Regexp.quote(column.sql_type)}(?: COLLATE \w+)? AS \((?<expression>.+?)\) #{column.extra}/ =~ create_table_info
73
+ $~[:expression].inspect
74
+ end
75
+ else
76
+ scope = @connection.send(:quoted_scope, table_name)
77
+ column_name = @connection.quote(column.name)
78
+ sql = "SELECT generation_expression FROM information_schema.columns" \
79
+ " WHERE table_schema = #{scope[:schema]}" \
80
+ " AND table_name = #{scope[:name]}" \
81
+ " AND column_name = #{column_name}"
82
+ @connection.query_value(sql, "SCHEMA").inspect
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,264 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ module MySQL
6
+ module SchemaStatements # :nodoc:
7
+ # Returns an array of indexes for the given table.
8
+ def indexes(table_name)
9
+ indexes = []
10
+ current_index = nil
11
+ execute_and_free("SHOW KEYS FROM #{quote_table_name(table_name)}", "SCHEMA") do |result|
12
+ each_hash(result) do |row|
13
+ if current_index != row[:Key_name]
14
+ next if row[:Key_name] == "PRIMARY" # skip the primary key
15
+ current_index = row[:Key_name]
16
+
17
+ mysql_index_type = row[:Index_type].downcase.to_sym
18
+ case mysql_index_type
19
+ when :fulltext, :spatial
20
+ index_type = mysql_index_type
21
+ when :btree, :hash
22
+ index_using = mysql_index_type
23
+ end
24
+
25
+ indexes << [
26
+ row[:Table],
27
+ row[:Key_name],
28
+ row[:Non_unique].to_i == 0,
29
+ [],
30
+ lengths: {},
31
+ orders: {},
32
+ type: index_type,
33
+ using: index_using,
34
+ comment: row[:Index_comment].presence
35
+ ]
36
+ end
37
+
38
+ if row[:Expression]
39
+ expression = row[:Expression]
40
+ expression = +"(#{expression})" unless expression.start_with?("(")
41
+ indexes.last[-2] << expression
42
+ indexes.last[-1][:expressions] ||= {}
43
+ indexes.last[-1][:expressions][expression] = expression
44
+ indexes.last[-1][:orders][expression] = :desc if row[:Collation] == "D"
45
+ else
46
+ indexes.last[-2] << row[:Column_name]
47
+ indexes.last[-1][:lengths][row[:Column_name]] = row[:Sub_part].to_i if row[:Sub_part]
48
+ indexes.last[-1][:orders][row[:Column_name]] = :desc if row[:Collation] == "D"
49
+ end
50
+ end
51
+ end
52
+
53
+ indexes.map do |index|
54
+ options = index.last
55
+
56
+ if expressions = options.delete(:expressions)
57
+ orders = options.delete(:orders)
58
+ lengths = options.delete(:lengths)
59
+
60
+ columns = index[-2].map { |name|
61
+ [ name.to_sym, expressions[name] || +quote_column_name(name) ]
62
+ }.to_h
63
+
64
+ index[-2] = add_options_for_index_columns(
65
+ columns, order: orders, length: lengths
66
+ ).values.join(", ")
67
+ end
68
+
69
+ IndexDefinition.new(*index)
70
+ end
71
+ end
72
+
73
+ def remove_column(table_name, column_name, type = nil, options = {})
74
+ if foreign_key_exists?(table_name, column: column_name)
75
+ remove_foreign_key(table_name, column: column_name)
76
+ end
77
+ super
78
+ end
79
+
80
+ def create_table(table_name, options: default_row_format, **)
81
+ super
82
+ end
83
+
84
+ def internal_string_options_for_primary_key
85
+ super.tap do |options|
86
+ if !row_format_dynamic_by_default? && CHARSETS_OF_4BYTES_MAXLEN.include?(charset)
87
+ options[:collation] = collation.sub(/\A[^_]+/, "utf8")
88
+ end
89
+ end
90
+ end
91
+
92
+ def update_table_definition(table_name, base)
93
+ MySQL::Table.new(table_name, base)
94
+ end
95
+
96
+ def create_schema_dumper(options)
97
+ MySQL::SchemaDumper.create(self, options)
98
+ end
99
+
100
+ # Maps logical Rails types to MySQL-specific data types.
101
+ def type_to_sql(type, limit: nil, precision: nil, scale: nil, size: limit_to_size(limit, type), unsigned: nil, **)
102
+ sql =
103
+ case type.to_s
104
+ when "integer"
105
+ integer_to_sql(limit)
106
+ when "text"
107
+ type_with_size_to_sql("text", size)
108
+ when "blob"
109
+ type_with_size_to_sql("blob", size)
110
+ when "binary"
111
+ if (0..0xfff) === limit
112
+ "varbinary(#{limit})"
113
+ else
114
+ type_with_size_to_sql("blob", size)
115
+ end
116
+ else
117
+ super
118
+ end
119
+
120
+ sql = "#{sql} unsigned" if unsigned && type != :primary_key
121
+ sql
122
+ end
123
+
124
+ def table_alias_length
125
+ 256 # https://dev.mysql.com/doc/refman/8.0/en/identifiers.html
126
+ end
127
+
128
+ private
129
+ CHARSETS_OF_4BYTES_MAXLEN = ["utf8mb4", "utf16", "utf16le", "utf32"]
130
+
131
+ def row_format_dynamic_by_default?
132
+ if mariadb?
133
+ database_version >= "10.2.2"
134
+ else
135
+ database_version >= "5.7.9"
136
+ end
137
+ end
138
+
139
+ def default_row_format
140
+ return if row_format_dynamic_by_default?
141
+
142
+ unless defined?(@default_row_format)
143
+ if query_value("SELECT @@innodb_file_per_table = 1 AND @@innodb_file_format = 'Barracuda'") == 1
144
+ @default_row_format = "ROW_FORMAT=DYNAMIC"
145
+ else
146
+ @default_row_format = nil
147
+ end
148
+ end
149
+
150
+ @default_row_format
151
+ end
152
+
153
+ def schema_creation
154
+ MySQL::SchemaCreation.new(self)
155
+ end
156
+
157
+ def create_table_definition(*args)
158
+ MySQL::TableDefinition.new(self, *args)
159
+ end
160
+
161
+ def new_column_from_field(table_name, field)
162
+ type_metadata = fetch_type_metadata(field[:Type], field[:Extra])
163
+ default, default_function = field[:Default], nil
164
+
165
+ if type_metadata.type == :datetime && /\ACURRENT_TIMESTAMP(?:\([0-6]?\))?\z/i.match?(default)
166
+ default, default_function = nil, default
167
+ elsif type_metadata.extra == "DEFAULT_GENERATED"
168
+ default = +"(#{default})" unless default.start_with?("(")
169
+ default, default_function = nil, default
170
+ end
171
+
172
+ MySQL::Column.new(
173
+ field[:Field],
174
+ default,
175
+ type_metadata,
176
+ field[:Null] == "YES",
177
+ default_function,
178
+ collation: field[:Collation],
179
+ comment: field[:Comment].presence
180
+ )
181
+ end
182
+
183
+ def fetch_type_metadata(sql_type, extra = "")
184
+ MySQL::TypeMetadata.new(super(sql_type), extra: extra)
185
+ end
186
+
187
+ def extract_foreign_key_action(specifier)
188
+ super unless specifier == "RESTRICT"
189
+ end
190
+
191
+ def add_index_length(quoted_columns, **options)
192
+ lengths = options_for_index_columns(options[:length])
193
+ quoted_columns.each do |name, column|
194
+ column << "(#{lengths[name]})" if lengths[name].present?
195
+ end
196
+ end
197
+
198
+ def add_options_for_index_columns(quoted_columns, **options)
199
+ quoted_columns = add_index_length(quoted_columns, options)
200
+ super
201
+ end
202
+
203
+ def data_source_sql(name = nil, type: nil)
204
+ scope = quoted_scope(name, type: type)
205
+
206
+ sql = +"SELECT table_name FROM information_schema.tables"
207
+ sql << " WHERE table_schema = #{scope[:schema]}"
208
+ sql << " AND table_name = #{scope[:name]}" if scope[:name]
209
+ sql << " AND table_type = #{scope[:type]}" if scope[:type]
210
+ sql
211
+ end
212
+
213
+ def quoted_scope(name = nil, type: nil)
214
+ schema, name = extract_schema_qualified_name(name)
215
+ scope = {}
216
+ scope[:schema] = schema ? quote(schema) : "database()"
217
+ scope[:name] = quote(name) if name
218
+ scope[:type] = quote(type) if type
219
+ scope
220
+ end
221
+
222
+ def extract_schema_qualified_name(string)
223
+ schema, name = string.to_s.scan(/[^`.\s]+|`[^`]*`/)
224
+ schema, name = nil, schema unless name
225
+ [schema, name]
226
+ end
227
+
228
+ def type_with_size_to_sql(type, size)
229
+ case size&.to_s
230
+ when nil, "tiny", "medium", "long"
231
+ "#{size}#{type}"
232
+ else
233
+ raise ArgumentError,
234
+ "#{size.inspect} is invalid :size value. Only :tiny, :medium, and :long are allowed."
235
+ end
236
+ end
237
+
238
+ def limit_to_size(limit, type)
239
+ case type.to_s
240
+ when "text", "blob", "binary"
241
+ case limit
242
+ when 0..0xff; "tiny"
243
+ when nil, 0x100..0xffff; nil
244
+ when 0x10000..0xffffff; "medium"
245
+ when 0x1000000..0xffffffff; "long"
246
+ else raise ArgumentError, "No #{type} type has byte size #{limit}"
247
+ end
248
+ end
249
+ end
250
+
251
+ def integer_to_sql(limit)
252
+ case limit
253
+ when 1; "tinyint"
254
+ when 2; "smallint"
255
+ when 3; "mediumint"
256
+ when nil, 4; "int"
257
+ when 5..8; "bigint"
258
+ else raise ArgumentError, "No integer type has byte size #{limit}. Use a decimal with scale 0 instead."
259
+ end
260
+ end
261
+ end
262
+ end
263
+ end
264
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ module MySQL
6
+ class TypeMetadata < DelegateClass(SqlTypeMetadata) # :nodoc:
7
+ undef to_yaml if method_defined?(:to_yaml)
8
+
9
+ attr_reader :extra
10
+
11
+ def initialize(type_metadata, extra: "")
12
+ super(type_metadata)
13
+ @extra = extra
14
+ end
15
+
16
+ def ==(other)
17
+ other.is_a?(TypeMetadata) &&
18
+ __getobj__ == other.__getobj__ &&
19
+ extra == other.extra
20
+ end
21
+ alias eql? ==
22
+
23
+ def hash
24
+ TypeMetadata.hash ^
25
+ __getobj__.hash ^
26
+ extra.hash
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,146 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record/connection_adapters/abstract_mysql_adapter"
4
+ require "active_record/connection_adapters/mysql/database_statements"
5
+
6
+ gem "mysql2", ">= 0.4.4"
7
+ require "mysql2"
8
+
9
+ module ActiveRecord
10
+ module ConnectionHandling # :nodoc:
11
+ ER_BAD_DB_ERROR = 1049
12
+
13
+ # Establishes a connection to the database that's used by all Active Record objects.
14
+ def mysql2_connection(config)
15
+ config = config.symbolize_keys
16
+ config[:flags] ||= 0
17
+
18
+ if config[:flags].kind_of? Array
19
+ config[:flags].push "FOUND_ROWS"
20
+ else
21
+ config[:flags] |= Mysql2::Client::FOUND_ROWS
22
+ end
23
+
24
+ client = Mysql2::Client.new(config)
25
+ ConnectionAdapters::Mysql2Adapter.new(client, logger, nil, config)
26
+ rescue Mysql2::Error => error
27
+ if error.error_number == ER_BAD_DB_ERROR
28
+ raise ActiveRecord::NoDatabaseError
29
+ else
30
+ raise
31
+ end
32
+ end
33
+ end
34
+
35
+ module ConnectionAdapters
36
+ class Mysql2Adapter < AbstractMysqlAdapter
37
+ ADAPTER_NAME = "Mysql2"
38
+
39
+ include MySQL::DatabaseStatements
40
+
41
+ def initialize(connection, logger, connection_options, config)
42
+ superclass_config = config.reverse_merge(prepared_statements: false)
43
+ super(connection, logger, connection_options, superclass_config)
44
+ configure_connection
45
+ end
46
+
47
+ def self.database_exists?(config)
48
+ !!ActiveRecord::Base.mysql2_connection(config)
49
+ rescue ActiveRecord::NoDatabaseError
50
+ false
51
+ end
52
+
53
+ def supports_json?
54
+ !mariadb? && database_version >= "5.7.8"
55
+ end
56
+
57
+ def supports_comments?
58
+ true
59
+ end
60
+
61
+ def supports_comments_in_create?
62
+ true
63
+ end
64
+
65
+ def supports_savepoints?
66
+ true
67
+ end
68
+
69
+ def supports_lazy_transactions?
70
+ true
71
+ end
72
+
73
+ # HELPER METHODS ===========================================
74
+
75
+ def each_hash(result) # :nodoc:
76
+ if block_given?
77
+ result.each(as: :hash, symbolize_keys: true) do |row|
78
+ yield row
79
+ end
80
+ else
81
+ to_enum(:each_hash, result)
82
+ end
83
+ end
84
+
85
+ def error_number(exception)
86
+ exception.error_number if exception.respond_to?(:error_number)
87
+ end
88
+
89
+ #--
90
+ # QUOTING ==================================================
91
+ #++
92
+
93
+ def quote_string(string)
94
+ @connection.escape(string)
95
+ end
96
+
97
+ #--
98
+ # CONNECTION MANAGEMENT ====================================
99
+ #++
100
+
101
+ def active?
102
+ @connection.ping
103
+ end
104
+
105
+ def reconnect!
106
+ super
107
+ disconnect!
108
+ connect
109
+ end
110
+ alias :reset! :reconnect!
111
+
112
+ # Disconnects from the database if already connected.
113
+ # Otherwise, this method does nothing.
114
+ def disconnect!
115
+ super
116
+ @connection.close
117
+ end
118
+
119
+ def discard! # :nodoc:
120
+ super
121
+ @connection.automatic_close = false
122
+ @connection = nil
123
+ end
124
+
125
+ private
126
+
127
+ def connect
128
+ @connection = Mysql2::Client.new(@config)
129
+ configure_connection
130
+ end
131
+
132
+ def configure_connection
133
+ @connection.query_options[:as] = :array
134
+ super
135
+ end
136
+
137
+ def full_version
138
+ schema_cache.database_version.full_version_string
139
+ end
140
+
141
+ def get_full_version
142
+ @connection.server_info[:version]
143
+ end
144
+ end
145
+ end
146
+ end