activerecord 5.0.7.2 → 6.0.6.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (359) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +844 -1944
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +9 -7
  5. data/examples/performance.rb +31 -29
  6. data/examples/simple.rb +5 -3
  7. data/lib/active_record/advisory_lock_base.rb +18 -0
  8. data/lib/active_record/aggregations.rb +249 -247
  9. data/lib/active_record/association_relation.rb +18 -14
  10. data/lib/active_record/associations/alias_tracker.rb +24 -34
  11. data/lib/active_record/associations/association.rb +113 -55
  12. data/lib/active_record/associations/association_scope.rb +102 -96
  13. data/lib/active_record/associations/belongs_to_association.rb +58 -42
  14. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
  15. data/lib/active_record/associations/builder/association.rb +18 -25
  16. data/lib/active_record/associations/builder/belongs_to.rb +43 -54
  17. data/lib/active_record/associations/builder/collection_association.rb +7 -18
  18. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +41 -62
  19. data/lib/active_record/associations/builder/has_many.rb +4 -0
  20. data/lib/active_record/associations/builder/has_one.rb +37 -1
  21. data/lib/active_record/associations/builder/singular_association.rb +4 -0
  22. data/lib/active_record/associations/collection_association.rb +93 -254
  23. data/lib/active_record/associations/collection_proxy.rb +159 -122
  24. data/lib/active_record/associations/foreign_association.rb +9 -0
  25. data/lib/active_record/associations/has_many_association.rb +23 -30
  26. data/lib/active_record/associations/has_many_through_association.rb +58 -44
  27. data/lib/active_record/associations/has_one_association.rb +59 -54
  28. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  29. data/lib/active_record/associations/join_dependency/join_association.rb +43 -85
  30. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  31. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  32. data/lib/active_record/associations/join_dependency.rb +152 -177
  33. data/lib/active_record/associations/preloader/association.rb +101 -97
  34. data/lib/active_record/associations/preloader/through_association.rb +77 -76
  35. data/lib/active_record/associations/preloader.rb +94 -103
  36. data/lib/active_record/associations/singular_association.rb +12 -45
  37. data/lib/active_record/associations/through_association.rb +27 -15
  38. data/lib/active_record/associations.rb +1603 -1592
  39. data/lib/active_record/attribute_assignment.rb +54 -61
  40. data/lib/active_record/attribute_decorators.rb +38 -17
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +12 -8
  42. data/lib/active_record/attribute_methods/dirty.rb +179 -109
  43. data/lib/active_record/attribute_methods/primary_key.rb +85 -92
  44. data/lib/active_record/attribute_methods/query.rb +4 -3
  45. data/lib/active_record/attribute_methods/read.rb +20 -49
  46. data/lib/active_record/attribute_methods/serialization.rb +29 -7
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -66
  48. data/lib/active_record/attribute_methods/write.rb +34 -33
  49. data/lib/active_record/attribute_methods.rb +66 -106
  50. data/lib/active_record/attributes.rb +38 -25
  51. data/lib/active_record/autosave_association.rb +58 -39
  52. data/lib/active_record/base.rb +27 -24
  53. data/lib/active_record/callbacks.rb +64 -35
  54. data/lib/active_record/coders/json.rb +2 -0
  55. data/lib/active_record/coders/yaml_column.rb +34 -13
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +558 -323
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +23 -5
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +215 -94
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +59 -35
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +128 -75
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +33 -28
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +233 -147
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +400 -213
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -79
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +373 -202
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +401 -562
  69. data/lib/active_record/connection_adapters/column.rb +41 -13
  70. data/lib/active_record/connection_adapters/connection_specification.rb +172 -139
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +11 -4
  72. data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +137 -49
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -23
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +58 -56
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +12 -13
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +48 -30
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +19 -31
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -54
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -11
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +12 -2
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -18
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
  99. data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +30 -9
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -30
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +8 -4
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +24 -21
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +95 -35
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +20 -26
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +34 -32
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +378 -308
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +26 -25
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -6
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +383 -275
  117. data/lib/active_record/connection_adapters/schema_cache.rb +46 -12
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +13 -8
  119. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
  120. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
  121. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +72 -18
  122. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +3 -8
  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 +261 -267
  127. data/lib/active_record/connection_adapters/statement_pool.rb +9 -8
  128. data/lib/active_record/connection_handling.rb +143 -40
  129. data/lib/active_record/core.rb +207 -160
  130. data/lib/active_record/counter_cache.rb +60 -28
  131. data/lib/active_record/database_configurations/database_config.rb +37 -0
  132. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  133. data/lib/active_record/database_configurations/url_config.rb +78 -0
  134. data/lib/active_record/database_configurations.rb +233 -0
  135. data/lib/active_record/define_callbacks.rb +22 -0
  136. data/lib/active_record/dynamic_matchers.rb +87 -87
  137. data/lib/active_record/enum.rb +67 -23
  138. data/lib/active_record/errors.rb +114 -18
  139. data/lib/active_record/explain.rb +4 -4
  140. data/lib/active_record/explain_registry.rb +3 -1
  141. data/lib/active_record/explain_subscriber.rb +9 -4
  142. data/lib/active_record/fixture_set/file.rb +13 -8
  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 +152 -0
  146. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  147. data/lib/active_record/fixtures.rb +194 -504
  148. data/lib/active_record/gem_version.rb +5 -3
  149. data/lib/active_record/inheritance.rb +150 -99
  150. data/lib/active_record/insert_all.rb +179 -0
  151. data/lib/active_record/integration.rb +116 -25
  152. data/lib/active_record/internal_metadata.rb +16 -19
  153. data/lib/active_record/legacy_yaml_adapter.rb +4 -2
  154. data/lib/active_record/locking/optimistic.rb +85 -86
  155. data/lib/active_record/locking/pessimistic.rb +18 -6
  156. data/lib/active_record/log_subscriber.rb +48 -29
  157. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  158. data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
  159. data/lib/active_record/middleware/database_selector.rb +74 -0
  160. data/lib/active_record/migration/command_recorder.rb +134 -100
  161. data/lib/active_record/migration/compatibility.rb +174 -56
  162. data/lib/active_record/migration/join_table.rb +8 -7
  163. data/lib/active_record/migration.rb +369 -302
  164. data/lib/active_record/model_schema.rb +160 -127
  165. data/lib/active_record/nested_attributes.rb +213 -202
  166. data/lib/active_record/no_touching.rb +12 -3
  167. data/lib/active_record/null_relation.rb +12 -34
  168. data/lib/active_record/persistence.rb +446 -77
  169. data/lib/active_record/query_cache.rb +13 -12
  170. data/lib/active_record/querying.rb +37 -24
  171. data/lib/active_record/railtie.rb +128 -36
  172. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  173. data/lib/active_record/railties/console_sandbox.rb +2 -0
  174. data/lib/active_record/railties/controller_runtime.rb +34 -33
  175. data/lib/active_record/railties/databases.rake +312 -177
  176. data/lib/active_record/readonly_attributes.rb +5 -4
  177. data/lib/active_record/reflection.rb +214 -254
  178. data/lib/active_record/relation/batches/batch_enumerator.rb +3 -1
  179. data/lib/active_record/relation/batches.rb +98 -52
  180. data/lib/active_record/relation/calculations.rb +212 -173
  181. data/lib/active_record/relation/delegation.rb +73 -69
  182. data/lib/active_record/relation/finder_methods.rb +207 -247
  183. data/lib/active_record/relation/from_clause.rb +6 -8
  184. data/lib/active_record/relation/merger.rb +82 -61
  185. data/lib/active_record/relation/predicate_builder/array_handler.rb +20 -14
  186. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  187. data/lib/active_record/relation/predicate_builder/base_handler.rb +4 -3
  188. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
  189. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  190. data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
  191. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  192. data/lib/active_record/relation/predicate_builder.rb +83 -105
  193. data/lib/active_record/relation/query_attribute.rb +33 -2
  194. data/lib/active_record/relation/query_methods.rb +488 -332
  195. data/lib/active_record/relation/record_fetch_warning.rb +5 -3
  196. data/lib/active_record/relation/spawn_methods.rb +8 -8
  197. data/lib/active_record/relation/where_clause.rb +111 -96
  198. data/lib/active_record/relation/where_clause_factory.rb +6 -11
  199. data/lib/active_record/relation.rb +443 -318
  200. data/lib/active_record/result.rb +69 -40
  201. data/lib/active_record/runtime_registry.rb +5 -3
  202. data/lib/active_record/sanitization.rb +83 -99
  203. data/lib/active_record/schema.rb +7 -14
  204. data/lib/active_record/schema_dumper.rb +71 -69
  205. data/lib/active_record/schema_migration.rb +16 -6
  206. data/lib/active_record/scoping/default.rb +92 -95
  207. data/lib/active_record/scoping/named.rb +51 -26
  208. data/lib/active_record/scoping.rb +20 -20
  209. data/lib/active_record/secure_token.rb +4 -2
  210. data/lib/active_record/serialization.rb +2 -0
  211. data/lib/active_record/statement_cache.rb +63 -28
  212. data/lib/active_record/store.rb +121 -41
  213. data/lib/active_record/suppressor.rb +6 -3
  214. data/lib/active_record/table_metadata.rb +39 -18
  215. data/lib/active_record/tasks/database_tasks.rb +271 -81
  216. data/lib/active_record/tasks/mysql_database_tasks.rb +54 -91
  217. data/lib/active_record/tasks/postgresql_database_tasks.rb +77 -47
  218. data/lib/active_record/tasks/sqlite_database_tasks.rb +33 -16
  219. data/lib/active_record/test_databases.rb +23 -0
  220. data/lib/active_record/test_fixtures.rb +243 -0
  221. data/lib/active_record/timestamp.rb +70 -36
  222. data/lib/active_record/touch_later.rb +8 -6
  223. data/lib/active_record/transactions.rb +141 -157
  224. data/lib/active_record/translation.rb +3 -1
  225. data/lib/active_record/type/adapter_specific_registry.rb +44 -48
  226. data/lib/active_record/type/date.rb +2 -0
  227. data/lib/active_record/type/date_time.rb +2 -0
  228. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  229. data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
  230. data/lib/active_record/type/internal/timezone.rb +2 -0
  231. data/lib/active_record/type/json.rb +30 -0
  232. data/lib/active_record/type/serialized.rb +16 -9
  233. data/lib/active_record/type/text.rb +11 -0
  234. data/lib/active_record/type/time.rb +12 -1
  235. data/lib/active_record/type/type_map.rb +14 -17
  236. data/lib/active_record/type/unsigned_integer.rb +16 -0
  237. data/lib/active_record/type.rb +23 -18
  238. data/lib/active_record/type_caster/connection.rb +17 -12
  239. data/lib/active_record/type_caster/map.rb +5 -4
  240. data/lib/active_record/type_caster.rb +4 -2
  241. data/lib/active_record/validations/absence.rb +2 -0
  242. data/lib/active_record/validations/associated.rb +3 -2
  243. data/lib/active_record/validations/length.rb +2 -0
  244. data/lib/active_record/validations/presence.rb +4 -2
  245. data/lib/active_record/validations/uniqueness.rb +29 -42
  246. data/lib/active_record/validations.rb +7 -5
  247. data/lib/active_record/version.rb +3 -1
  248. data/lib/active_record.rb +37 -22
  249. data/lib/arel/alias_predication.rb +9 -0
  250. data/lib/arel/attributes/attribute.rb +37 -0
  251. data/lib/arel/attributes.rb +22 -0
  252. data/lib/arel/collectors/bind.rb +24 -0
  253. data/lib/arel/collectors/composite.rb +31 -0
  254. data/lib/arel/collectors/plain_string.rb +20 -0
  255. data/lib/arel/collectors/sql_string.rb +20 -0
  256. data/lib/arel/collectors/substitute_binds.rb +28 -0
  257. data/lib/arel/crud.rb +42 -0
  258. data/lib/arel/delete_manager.rb +18 -0
  259. data/lib/arel/errors.rb +9 -0
  260. data/lib/arel/expressions.rb +29 -0
  261. data/lib/arel/factory_methods.rb +49 -0
  262. data/lib/arel/insert_manager.rb +49 -0
  263. data/lib/arel/math.rb +45 -0
  264. data/lib/arel/nodes/and.rb +32 -0
  265. data/lib/arel/nodes/ascending.rb +23 -0
  266. data/lib/arel/nodes/binary.rb +52 -0
  267. data/lib/arel/nodes/bind_param.rb +36 -0
  268. data/lib/arel/nodes/case.rb +55 -0
  269. data/lib/arel/nodes/casted.rb +50 -0
  270. data/lib/arel/nodes/comment.rb +29 -0
  271. data/lib/arel/nodes/count.rb +12 -0
  272. data/lib/arel/nodes/delete_statement.rb +45 -0
  273. data/lib/arel/nodes/descending.rb +23 -0
  274. data/lib/arel/nodes/equality.rb +18 -0
  275. data/lib/arel/nodes/extract.rb +24 -0
  276. data/lib/arel/nodes/false.rb +16 -0
  277. data/lib/arel/nodes/full_outer_join.rb +8 -0
  278. data/lib/arel/nodes/function.rb +44 -0
  279. data/lib/arel/nodes/grouping.rb +8 -0
  280. data/lib/arel/nodes/in.rb +8 -0
  281. data/lib/arel/nodes/infix_operation.rb +80 -0
  282. data/lib/arel/nodes/inner_join.rb +8 -0
  283. data/lib/arel/nodes/insert_statement.rb +37 -0
  284. data/lib/arel/nodes/join_source.rb +20 -0
  285. data/lib/arel/nodes/matches.rb +18 -0
  286. data/lib/arel/nodes/named_function.rb +23 -0
  287. data/lib/arel/nodes/node.rb +50 -0
  288. data/lib/arel/nodes/node_expression.rb +13 -0
  289. data/lib/arel/nodes/outer_join.rb +8 -0
  290. data/lib/arel/nodes/over.rb +15 -0
  291. data/lib/arel/nodes/regexp.rb +16 -0
  292. data/lib/arel/nodes/right_outer_join.rb +8 -0
  293. data/lib/arel/nodes/select_core.rb +67 -0
  294. data/lib/arel/nodes/select_statement.rb +41 -0
  295. data/lib/arel/nodes/sql_literal.rb +16 -0
  296. data/lib/arel/nodes/string_join.rb +11 -0
  297. data/lib/arel/nodes/table_alias.rb +27 -0
  298. data/lib/arel/nodes/terminal.rb +16 -0
  299. data/lib/arel/nodes/true.rb +16 -0
  300. data/lib/arel/nodes/unary.rb +45 -0
  301. data/lib/arel/nodes/unary_operation.rb +20 -0
  302. data/lib/arel/nodes/unqualified_column.rb +22 -0
  303. data/lib/arel/nodes/update_statement.rb +41 -0
  304. data/lib/arel/nodes/values_list.rb +9 -0
  305. data/lib/arel/nodes/window.rb +126 -0
  306. data/lib/arel/nodes/with.rb +11 -0
  307. data/lib/arel/nodes.rb +68 -0
  308. data/lib/arel/order_predications.rb +13 -0
  309. data/lib/arel/predications.rb +256 -0
  310. data/lib/arel/select_manager.rb +271 -0
  311. data/lib/arel/table.rb +110 -0
  312. data/lib/arel/tree_manager.rb +72 -0
  313. data/lib/arel/update_manager.rb +34 -0
  314. data/lib/arel/visitors/depth_first.rb +203 -0
  315. data/lib/arel/visitors/dot.rb +296 -0
  316. data/lib/arel/visitors/ibm_db.rb +34 -0
  317. data/lib/arel/visitors/informix.rb +62 -0
  318. data/lib/arel/visitors/mssql.rb +156 -0
  319. data/lib/arel/visitors/mysql.rb +83 -0
  320. data/lib/arel/visitors/oracle.rb +158 -0
  321. data/lib/arel/visitors/oracle12.rb +65 -0
  322. data/lib/arel/visitors/postgresql.rb +109 -0
  323. data/lib/arel/visitors/sqlite.rb +38 -0
  324. data/lib/arel/visitors/to_sql.rb +888 -0
  325. data/lib/arel/visitors/visitor.rb +45 -0
  326. data/lib/arel/visitors/where_sql.rb +22 -0
  327. data/lib/arel/visitors.rb +20 -0
  328. data/lib/arel/window_predications.rb +9 -0
  329. data/lib/arel.rb +62 -0
  330. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  331. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -35
  332. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +1 -1
  333. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +4 -2
  334. data/lib/rails/generators/active_record/migration.rb +17 -3
  335. data/lib/rails/generators/active_record/model/model_generator.rb +9 -30
  336. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
  337. data/lib/rails/generators/active_record.rb +7 -5
  338. metadata +138 -52
  339. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  340. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  341. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  342. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  343. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  344. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  345. data/lib/active_record/associations/preloader/singular_association.rb +0 -20
  346. data/lib/active_record/attribute/user_provided_default.rb +0 -28
  347. data/lib/active_record/attribute.rb +0 -213
  348. data/lib/active_record/attribute_mutation_tracker.rb +0 -70
  349. data/lib/active_record/attribute_set/builder.rb +0 -132
  350. data/lib/active_record/attribute_set.rb +0 -110
  351. data/lib/active_record/collection_cache_key.rb +0 -50
  352. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
  353. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  354. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  355. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
  356. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
  357. data/lib/active_record/type/internal/abstract_json.rb +0 -33
  358. /data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  359. /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,20 +1,31 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Make sure we're using pg high enough for type casts and Ruby 2.2+ compatibility
2
4
  gem "pg", ">= 0.18", "< 2.0"
3
- require 'pg'
5
+ require "pg"
6
+
7
+ # Use async_exec instead of exec_params on pg versions before 1.1
8
+ class ::PG::Connection # :nodoc:
9
+ unless self.public_method_defined?(:async_exec_params)
10
+ remove_method :exec_params
11
+ alias exec_params async_exec
12
+ end
13
+ end
4
14
 
5
15
  require "active_record/connection_adapters/abstract_adapter"
16
+ require "active_record/connection_adapters/statement_pool"
6
17
  require "active_record/connection_adapters/postgresql/column"
7
18
  require "active_record/connection_adapters/postgresql/database_statements"
8
19
  require "active_record/connection_adapters/postgresql/explain_pretty_printer"
9
20
  require "active_record/connection_adapters/postgresql/oid"
10
21
  require "active_record/connection_adapters/postgresql/quoting"
11
22
  require "active_record/connection_adapters/postgresql/referential_integrity"
23
+ require "active_record/connection_adapters/postgresql/schema_creation"
12
24
  require "active_record/connection_adapters/postgresql/schema_definitions"
13
25
  require "active_record/connection_adapters/postgresql/schema_dumper"
14
26
  require "active_record/connection_adapters/postgresql/schema_statements"
15
27
  require "active_record/connection_adapters/postgresql/type_metadata"
16
28
  require "active_record/connection_adapters/postgresql/utils"
17
- require "active_record/connection_adapters/statement_pool"
18
29
 
19
30
  module ActiveRecord
20
31
  module ConnectionHandling # :nodoc:
@@ -32,9 +43,14 @@ module ActiveRecord
32
43
  valid_conn_param_keys = PG::Connection.conndefaults_hash.keys + [:requiressl]
33
44
  conn_params.slice!(*valid_conn_param_keys)
34
45
 
35
- # The postgres drivers don't allow the creation of an unconnected PG::Connection object,
36
- # so just pass a nil connection object for the time being.
37
- ConnectionAdapters::PostgreSQLAdapter.new(nil, logger, conn_params, config)
46
+ conn = PG.connect(conn_params)
47
+ ConnectionAdapters::PostgreSQLAdapter.new(conn, logger, conn_params, config)
48
+ rescue ::PG::Error => error
49
+ if error.message.include?(conn_params[:dbname])
50
+ raise ActiveRecord::NoDatabaseError
51
+ else
52
+ raise
53
+ end
38
54
  end
39
55
  end
40
56
 
@@ -61,19 +77,32 @@ module ActiveRecord
61
77
  # defaults to true.
62
78
  #
63
79
  # Any further options are used as connection parameters to libpq. See
64
- # http://www.postgresql.org/docs/current/static/libpq-connect.html for the
80
+ # https://www.postgresql.org/docs/current/static/libpq-connect.html for the
65
81
  # list of parameters.
66
82
  #
67
83
  # In addition, default connection parameters of libpq can be set per environment variables.
68
- # See http://www.postgresql.org/docs/current/static/libpq-envars.html .
84
+ # See https://www.postgresql.org/docs/current/static/libpq-envars.html .
69
85
  class PostgreSQLAdapter < AbstractAdapter
70
- ADAPTER_NAME = 'PostgreSQL'.freeze
86
+ ADAPTER_NAME = "PostgreSQL"
87
+
88
+ ##
89
+ # :singleton-method:
90
+ # PostgreSQL allows the creation of "unlogged" tables, which do not record
91
+ # data in the PostgreSQL Write-Ahead Log. This can make the tables faster,
92
+ # but significantly increases the risk of data loss if the database
93
+ # crashes. As a result, this should not be used in production
94
+ # environments. If you would like all created tables to be unlogged in
95
+ # the test environment you can add the following line to your test.rb
96
+ # file:
97
+ #
98
+ # ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.create_unlogged_tables = true
99
+ class_attribute :create_unlogged_tables, default: false
71
100
 
72
101
  NATIVE_DATABASE_TYPES = {
73
- primary_key: "serial primary key",
102
+ primary_key: "bigserial primary key",
74
103
  string: { name: "character varying" },
75
104
  text: { name: "text" },
76
- integer: { name: "integer" },
105
+ integer: { name: "integer", limit: 4 },
77
106
  float: { name: "float" },
78
107
  decimal: { name: "decimal" },
79
108
  datetime: { name: "timestamp" },
@@ -108,6 +137,8 @@ module ActiveRecord
108
137
  bit: { name: "bit" },
109
138
  bit_varying: { name: "bit varying" },
110
139
  money: { name: "money" },
140
+ interval: { name: "interval" },
141
+ oid: { name: "oid" },
111
142
  }
112
143
 
113
144
  OID = PostgreSQL::OID #:nodoc:
@@ -116,19 +147,8 @@ module ActiveRecord
116
147
  include PostgreSQL::ReferentialIntegrity
117
148
  include PostgreSQL::SchemaStatements
118
149
  include PostgreSQL::DatabaseStatements
119
- include PostgreSQL::ColumnDumper
120
-
121
- def schema_creation # :nodoc:
122
- PostgreSQL::SchemaCreation.new self
123
- end
124
150
 
125
- def arel_visitor # :nodoc:
126
- Arel::Visitors::PostgreSQL.new(self)
127
- end
128
-
129
- # Returns true, since this connection adapter supports prepared statement
130
- # caching.
131
- def supports_statement_cache?
151
+ def supports_bulk_alter?
132
152
  true
133
153
  end
134
154
 
@@ -136,6 +156,10 @@ module ActiveRecord
136
156
  true
137
157
  end
138
158
 
159
+ def supports_partitioned_indexes?
160
+ database_version >= 110_000
161
+ end
162
+
139
163
  def supports_partial_index?
140
164
  true
141
165
  end
@@ -152,6 +176,10 @@ module ActiveRecord
152
176
  true
153
177
  end
154
178
 
179
+ def supports_validate_constraints?
180
+ true
181
+ end
182
+
155
183
  def supports_views?
156
184
  true
157
185
  end
@@ -161,7 +189,7 @@ module ActiveRecord
161
189
  end
162
190
 
163
191
  def supports_json?
164
- postgresql_version >= 90200
192
+ true
165
193
  end
166
194
 
167
195
  def supports_comments?
@@ -172,11 +200,22 @@ module ActiveRecord
172
200
  true
173
201
  end
174
202
 
203
+ def supports_insert_returning?
204
+ true
205
+ end
206
+
207
+ def supports_insert_on_conflict?
208
+ database_version >= 90500
209
+ end
210
+ alias supports_insert_on_duplicate_skip? supports_insert_on_conflict?
211
+ alias supports_insert_on_duplicate_update? supports_insert_on_conflict?
212
+ alias supports_insert_conflict_target? supports_insert_on_conflict?
213
+
175
214
  def index_algorithms
176
- { concurrently: 'CONCURRENTLY' }
215
+ { concurrently: "CONCURRENTLY" }
177
216
  end
178
217
 
179
- class StatementPool < ConnectionAdapters::StatementPool
218
+ class StatementPool < ConnectionAdapters::StatementPool # :nodoc:
180
219
  def initialize(connection, max)
181
220
  super(max)
182
221
  @connection = connection
@@ -192,9 +231,9 @@ module ActiveRecord
192
231
  end
193
232
 
194
233
  private
195
-
196
234
  def dealloc(key)
197
235
  @connection.query "DEALLOCATE #{key}" if connection_active?
236
+ rescue PG::Error
198
237
  end
199
238
 
200
239
  def connection_active?
@@ -214,35 +253,27 @@ module ActiveRecord
214
253
  @local_tz = nil
215
254
  @max_identifier_length = nil
216
255
 
217
- connect
256
+ configure_connection
218
257
  add_pg_encoders
219
- @statements = StatementPool.new @connection,
220
- self.class.type_cast_config_to_integer(config[:statement_limit])
221
-
222
- if postgresql_version < 90100
223
- raise "Your version of PostgreSQL (#{postgresql_version}) is too old. Active Record supports PostgreSQL >= 9.1."
224
- end
225
-
226
258
  add_pg_decoders
227
259
 
228
260
  @type_map = Type::HashLookupTypeMap.new
229
- initialize_type_map(type_map)
230
- @local_tz = execute('SHOW TIME ZONE', 'SCHEMA').first["TimeZone"]
261
+ initialize_type_map
262
+ @local_tz = execute("SHOW TIME ZONE", "SCHEMA").first["TimeZone"]
231
263
  @use_insert_returning = @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
232
264
  end
233
265
 
234
- # Clears the prepared statements cache.
235
- def clear_cache!
236
- @statements.clear
237
- end
238
-
239
- def truncate(table_name, name = nil)
240
- exec_query "TRUNCATE TABLE #{quote_table_name(table_name)}", name, []
266
+ def self.database_exists?(config)
267
+ !!ActiveRecord::Base.postgresql_connection(config)
268
+ rescue ActiveRecord::NoDatabaseError
269
+ false
241
270
  end
242
271
 
243
272
  # Is this connection alive and ready for queries?
244
273
  def active?
245
- @connection.query 'SELECT 1'
274
+ @lock.synchronize do
275
+ @connection.query "SELECT 1"
276
+ end
246
277
  true
247
278
  rescue PG::Error
248
279
  false
@@ -250,44 +281,48 @@ module ActiveRecord
250
281
 
251
282
  # Close then reopen the connection.
252
283
  def reconnect!
253
- super
254
- @connection.reset
255
- configure_connection
284
+ @lock.synchronize do
285
+ super
286
+ @connection.reset
287
+ configure_connection
288
+ rescue PG::ConnectionBad
289
+ connect
290
+ end
256
291
  end
257
292
 
258
293
  def reset!
259
- clear_cache!
260
- reset_transaction
261
- unless @connection.transaction_status == ::PG::PQTRANS_IDLE
262
- @connection.query 'ROLLBACK'
294
+ @lock.synchronize do
295
+ clear_cache!
296
+ reset_transaction
297
+ unless @connection.transaction_status == ::PG::PQTRANS_IDLE
298
+ @connection.query "ROLLBACK"
299
+ end
300
+ @connection.query "DISCARD ALL"
301
+ configure_connection
263
302
  end
264
- @connection.query 'DISCARD ALL'
265
- configure_connection
266
303
  end
267
304
 
268
305
  # Disconnects from the database if already connected. Otherwise, this
269
306
  # method does nothing.
270
307
  def disconnect!
308
+ @lock.synchronize do
309
+ super
310
+ @connection.close rescue nil
311
+ end
312
+ end
313
+
314
+ def discard! # :nodoc:
271
315
  super
272
- @connection.close rescue nil
316
+ @connection.socket_io.reopen(IO::NULL) rescue nil
317
+ @connection = nil
273
318
  end
274
319
 
275
320
  def native_database_types #:nodoc:
276
321
  NATIVE_DATABASE_TYPES
277
322
  end
278
323
 
279
- # Returns true, since this connection adapter supports migrations.
280
- def supports_migrations?
281
- true
282
- end
283
-
284
- # Does PostgreSQL support finding primary key on non-Active Record tables?
285
- def supports_primary_key? #:nodoc:
286
- true
287
- end
288
-
289
324
  def set_standard_conforming_strings
290
- execute('SET standard_conforming_strings = on', 'SCHEMA')
325
+ execute("SET standard_conforming_strings = on", "SCHEMA")
291
326
  end
292
327
 
293
328
  def supports_ddl_transactions?
@@ -306,27 +341,50 @@ module ActiveRecord
306
341
  true
307
342
  end
308
343
 
309
- # Range datatypes weren't introduced until PostgreSQL 9.2
310
344
  def supports_ranges?
311
- postgresql_version >= 90200
345
+ true
312
346
  end
347
+ deprecate :supports_ranges?
313
348
 
314
349
  def supports_materialized_views?
315
- postgresql_version >= 90300
350
+ true
351
+ end
352
+
353
+ def supports_foreign_tables?
354
+ true
355
+ end
356
+
357
+ def supports_pgcrypto_uuid?
358
+ database_version >= 90400
359
+ end
360
+
361
+ def supports_optimizer_hints?
362
+ unless defined?(@has_pg_hint_plan)
363
+ @has_pg_hint_plan = extension_available?("pg_hint_plan")
364
+ end
365
+ @has_pg_hint_plan
366
+ end
367
+
368
+ def supports_common_table_expressions?
369
+ true
370
+ end
371
+
372
+ def supports_lazy_transactions?
373
+ true
316
374
  end
317
375
 
318
376
  def get_advisory_lock(lock_id) # :nodoc:
319
377
  unless lock_id.is_a?(Integer) && lock_id.bit_length <= 63
320
- raise(ArgumentError, "Postgres requires advisory lock ids to be a signed 64 bit integer")
378
+ raise(ArgumentError, "PostgreSQL requires advisory lock ids to be a signed 64 bit integer")
321
379
  end
322
- select_value("SELECT pg_try_advisory_lock(#{lock_id});")
380
+ query_value("SELECT pg_try_advisory_lock(#{lock_id})")
323
381
  end
324
382
 
325
383
  def release_advisory_lock(lock_id) # :nodoc:
326
384
  unless lock_id.is_a?(Integer) && lock_id.bit_length <= 63
327
- raise(ArgumentError, "Postgres requires advisory lock ids to be a signed 64 bit integer")
385
+ raise(ArgumentError, "PostgreSQL requires advisory lock ids to be a signed 64 bit integer")
328
386
  end
329
- select_value("SELECT pg_advisory_unlock(#{lock_id})")
387
+ query_value("SELECT pg_advisory_unlock(#{lock_id})")
330
388
  end
331
389
 
332
390
  def enable_extension(name)
@@ -341,52 +399,33 @@ module ActiveRecord
341
399
  }
342
400
  end
343
401
 
402
+ def extension_available?(name)
403
+ query_value("SELECT true FROM pg_available_extensions WHERE name = #{quote(name)}", "SCHEMA")
404
+ end
405
+
344
406
  def extension_enabled?(name)
345
- if supports_extensions?
346
- res = exec_query "SELECT EXISTS(SELECT * FROM pg_available_extensions WHERE name = '#{name}' AND installed_version IS NOT NULL) as enabled",
347
- 'SCHEMA'
348
- res.cast_values.first
349
- end
407
+ query_value("SELECT installed_version IS NOT NULL FROM pg_available_extensions WHERE name = #{quote(name)}", "SCHEMA")
350
408
  end
351
409
 
352
410
  def extensions
353
- if supports_extensions?
354
- exec_query("SELECT extname from pg_extension", "SCHEMA").cast_values
355
- else
356
- super
357
- end
411
+ exec_query("SELECT extname FROM pg_extension", "SCHEMA").cast_values
358
412
  end
359
413
 
360
414
  # Returns the configured supported identifier length supported by PostgreSQL
361
415
  def max_identifier_length
362
- @max_identifier_length ||= query('SHOW max_identifier_length', 'SCHEMA')[0][0].to_i
416
+ @max_identifier_length ||= query_value("SHOW max_identifier_length", "SCHEMA").to_i
363
417
  end
364
- alias table_alias_length max_identifier_length
365
- alias index_name_length max_identifier_length
366
418
 
367
419
  # Set the authorized user for this session
368
420
  def session_auth=(user)
369
421
  clear_cache!
370
- exec_query "SET SESSION AUTHORIZATION #{user}"
422
+ execute("SET SESSION AUTHORIZATION #{user}")
371
423
  end
372
424
 
373
425
  def use_insert_returning?
374
426
  @use_insert_returning
375
427
  end
376
428
 
377
- def valid_type?(type)
378
- !native_database_types[type].nil?
379
- end
380
-
381
- def update_table_definition(table_name, base) #:nodoc:
382
- PostgreSQL::Table.new(table_name, base)
383
- end
384
-
385
- def lookup_cast_type(sql_type) # :nodoc:
386
- oid = execute("SELECT #{quote(sql_type)}::regtype::oid", "SCHEMA").first['oid'].to_i
387
- super(oid)
388
- end
389
-
390
429
  def column_name_for_operation(operation, node) # :nodoc:
391
430
  OPERATION_ALIASES.fetch(operation) { operation.downcase }
392
431
  end
@@ -398,93 +437,135 @@ module ActiveRecord
398
437
  }
399
438
 
400
439
  # Returns the version of the connected PostgreSQL server.
401
- def postgresql_version
440
+ def get_database_version # :nodoc:
402
441
  @connection.server_version
403
442
  end
443
+ alias :postgresql_version :database_version
444
+
445
+ def default_index_type?(index) # :nodoc:
446
+ index.using == :btree || super
447
+ end
404
448
 
405
- protected
449
+ def build_insert_sql(insert) # :nodoc:
450
+ sql = +"INSERT #{insert.into} #{insert.values_list}"
406
451
 
407
- # See http://www.postgresql.org/docs/current/static/errcodes-appendix.html
452
+ if insert.skip_duplicates?
453
+ sql << " ON CONFLICT #{insert.conflict_target} DO NOTHING"
454
+ elsif insert.update_duplicates?
455
+ sql << " ON CONFLICT #{insert.conflict_target} DO UPDATE SET "
456
+ sql << insert.updatable_columns.map { |column| "#{column}=excluded.#{column}" }.join(",")
457
+ end
458
+
459
+ sql << " RETURNING #{insert.returning}" if insert.returning
460
+ sql
461
+ end
462
+
463
+ def check_version # :nodoc:
464
+ if database_version < 90300
465
+ raise "Your version of PostgreSQL (#{database_version}) is too old. Active Record supports PostgreSQL >= 9.3."
466
+ end
467
+ end
468
+
469
+ private
470
+ # See https://www.postgresql.org/docs/current/static/errcodes-appendix.html
408
471
  VALUE_LIMIT_VIOLATION = "22001"
472
+ NUMERIC_VALUE_OUT_OF_RANGE = "22003"
473
+ NOT_NULL_VIOLATION = "23502"
409
474
  FOREIGN_KEY_VIOLATION = "23503"
410
475
  UNIQUE_VIOLATION = "23505"
476
+ SERIALIZATION_FAILURE = "40001"
477
+ DEADLOCK_DETECTED = "40P01"
478
+ LOCK_NOT_AVAILABLE = "55P03"
479
+ QUERY_CANCELED = "57014"
411
480
 
412
- def translate_exception(exception, message)
481
+ def translate_exception(exception, message:, sql:, binds:)
413
482
  return exception unless exception.respond_to?(:result)
414
483
 
415
484
  case exception.result.try(:error_field, PG::PG_DIAG_SQLSTATE)
416
485
  when UNIQUE_VIOLATION
417
- RecordNotUnique.new(message)
486
+ RecordNotUnique.new(message, sql: sql, binds: binds)
418
487
  when FOREIGN_KEY_VIOLATION
419
- InvalidForeignKey.new(message)
488
+ InvalidForeignKey.new(message, sql: sql, binds: binds)
420
489
  when VALUE_LIMIT_VIOLATION
421
- ValueTooLong.new(message)
490
+ ValueTooLong.new(message, sql: sql, binds: binds)
491
+ when NUMERIC_VALUE_OUT_OF_RANGE
492
+ RangeError.new(message, sql: sql, binds: binds)
493
+ when NOT_NULL_VIOLATION
494
+ NotNullViolation.new(message, sql: sql, binds: binds)
495
+ when SERIALIZATION_FAILURE
496
+ SerializationFailure.new(message, sql: sql, binds: binds)
497
+ when DEADLOCK_DETECTED
498
+ Deadlocked.new(message, sql: sql, binds: binds)
499
+ when LOCK_NOT_AVAILABLE
500
+ LockWaitTimeout.new(message, sql: sql, binds: binds)
501
+ when QUERY_CANCELED
502
+ QueryCanceled.new(message, sql: sql, binds: binds)
422
503
  else
423
504
  super
424
505
  end
425
506
  end
426
507
 
427
- private
428
-
429
- def get_oid_type(oid, fmod, column_name, sql_type = '') # :nodoc:
508
+ def get_oid_type(oid, fmod, column_name, sql_type = "")
430
509
  if !type_map.key?(oid)
431
- load_additional_types(type_map, [oid])
510
+ load_additional_types([oid])
432
511
  end
433
512
 
434
513
  type_map.fetch(oid, fmod, sql_type) {
435
514
  warn "unknown OID #{oid}: failed to recognize type of '#{column_name}'. It will be treated as String."
436
- Type::Value.new.tap do |cast_type|
515
+ Type.default_value.tap do |cast_type|
437
516
  type_map.register_type(oid, cast_type)
438
517
  end
439
518
  }
440
519
  end
441
520
 
442
- def initialize_type_map(m) # :nodoc:
443
- register_class_with_limit m, 'int2', Type::Integer
444
- register_class_with_limit m, 'int4', Type::Integer
445
- register_class_with_limit m, 'int8', Type::Integer
446
- m.alias_type 'oid', 'int2'
447
- m.register_type 'float4', Type::Float.new
448
- m.alias_type 'float8', 'float4'
449
- m.register_type 'text', Type::Text.new
450
- register_class_with_limit m, 'varchar', Type::String
451
- m.alias_type 'char', 'varchar'
452
- m.alias_type 'name', 'varchar'
453
- m.alias_type 'bpchar', 'varchar'
454
- m.register_type 'bool', Type::Boolean.new
455
- register_class_with_limit m, 'bit', OID::Bit
456
- register_class_with_limit m, 'varbit', OID::BitVarying
457
- m.alias_type 'timestamptz', 'timestamp'
458
- m.register_type 'date', Type::Date.new
459
-
460
- m.register_type 'money', OID::Money.new
461
- m.register_type 'bytea', OID::Bytea.new
462
- m.register_type 'point', OID::Point.new
463
- m.register_type 'hstore', OID::Hstore.new
464
- m.register_type 'json', OID::Json.new
465
- m.register_type 'jsonb', OID::Jsonb.new
466
- m.register_type 'cidr', OID::Cidr.new
467
- m.register_type 'inet', OID::Inet.new
468
- m.register_type 'uuid', OID::Uuid.new
469
- m.register_type 'xml', OID::Xml.new
470
- m.register_type 'tsvector', OID::SpecializedString.new(:tsvector)
471
- m.register_type 'macaddr', OID::SpecializedString.new(:macaddr)
472
- m.register_type 'citext', OID::SpecializedString.new(:citext)
473
- m.register_type 'ltree', OID::SpecializedString.new(:ltree)
474
- m.register_type 'line', OID::SpecializedString.new(:line)
475
- m.register_type 'lseg', OID::SpecializedString.new(:lseg)
476
- m.register_type 'box', OID::SpecializedString.new(:box)
477
- m.register_type 'path', OID::SpecializedString.new(:path)
478
- m.register_type 'polygon', OID::SpecializedString.new(:polygon)
479
- m.register_type 'circle', OID::SpecializedString.new(:circle)
480
-
481
- # FIXME: why are we keeping these types as strings?
482
- m.alias_type 'interval', 'varchar'
483
-
484
- register_class_with_precision m, 'time', Type::Time
485
- register_class_with_precision m, 'timestamp', OID::DateTime
486
-
487
- m.register_type 'numeric' do |_, fmod, sql_type|
521
+ def initialize_type_map(m = type_map)
522
+ m.register_type "int2", Type::Integer.new(limit: 2)
523
+ m.register_type "int4", Type::Integer.new(limit: 4)
524
+ m.register_type "int8", Type::Integer.new(limit: 8)
525
+ m.register_type "oid", OID::Oid.new
526
+ m.register_type "float4", Type::Float.new
527
+ m.alias_type "float8", "float4"
528
+ m.register_type "text", Type::Text.new
529
+ register_class_with_limit m, "varchar", Type::String
530
+ m.alias_type "char", "varchar"
531
+ m.alias_type "name", "varchar"
532
+ m.alias_type "bpchar", "varchar"
533
+ m.register_type "bool", Type::Boolean.new
534
+ register_class_with_limit m, "bit", OID::Bit
535
+ register_class_with_limit m, "varbit", OID::BitVarying
536
+ m.alias_type "timestamptz", "timestamp"
537
+ m.register_type "date", OID::Date.new
538
+
539
+ m.register_type "money", OID::Money.new
540
+ m.register_type "bytea", OID::Bytea.new
541
+ m.register_type "point", OID::Point.new
542
+ m.register_type "hstore", OID::Hstore.new
543
+ m.register_type "json", Type::Json.new
544
+ m.register_type "jsonb", OID::Jsonb.new
545
+ m.register_type "cidr", OID::Cidr.new
546
+ m.register_type "inet", OID::Inet.new
547
+ m.register_type "uuid", OID::Uuid.new
548
+ m.register_type "xml", OID::Xml.new
549
+ m.register_type "tsvector", OID::SpecializedString.new(:tsvector)
550
+ m.register_type "macaddr", OID::SpecializedString.new(:macaddr)
551
+ m.register_type "citext", OID::SpecializedString.new(:citext)
552
+ m.register_type "ltree", OID::SpecializedString.new(:ltree)
553
+ m.register_type "line", OID::SpecializedString.new(:line)
554
+ m.register_type "lseg", OID::SpecializedString.new(:lseg)
555
+ m.register_type "box", OID::SpecializedString.new(:box)
556
+ m.register_type "path", OID::SpecializedString.new(:path)
557
+ m.register_type "polygon", OID::SpecializedString.new(:polygon)
558
+ m.register_type "circle", OID::SpecializedString.new(:circle)
559
+
560
+ m.register_type "interval" do |_, _, sql_type|
561
+ precision = extract_precision(sql_type)
562
+ OID::SpecializedString.new(:interval, precision: precision)
563
+ end
564
+
565
+ register_class_with_precision m, "time", Type::Time
566
+ register_class_with_precision m, "timestamp", OID::DateTime
567
+
568
+ m.register_type "numeric" do |_, fmod, sql_type|
488
569
  precision = extract_precision(sql_type)
489
570
  scale = extract_scale(sql_type)
490
571
 
@@ -504,78 +585,60 @@ module ActiveRecord
504
585
  end
505
586
  end
506
587
 
507
- load_additional_types(m)
508
- end
509
-
510
- def extract_limit(sql_type) # :nodoc:
511
- case sql_type
512
- when /^bigint/i, /^int8/i
513
- 8
514
- when /^smallint/i
515
- 2
516
- else
517
- super
518
- end
588
+ load_additional_types
519
589
  end
520
590
 
521
591
  # Extracts the value from a PostgreSQL column default definition.
522
- def extract_value_from_default(default) # :nodoc:
592
+ def extract_value_from_default(default)
523
593
  case default
524
594
  # Quoted types
525
- when /\A[\(B]?'(.*)'.*::"?([\w. ]+)"?(?:\[\])?\z/m
526
- # The default 'now'::date is CURRENT_DATE
527
- if $1 == "now".freeze && $2 == "date".freeze
528
- nil
529
- else
530
- $1.gsub("''".freeze, "'".freeze)
531
- end
595
+ when /\A[\(B]?'(.*)'.*::"?([\w. ]+)"?(?:\[\])?\z/m
596
+ # The default 'now'::date is CURRENT_DATE
597
+ if $1 == "now" && $2 == "date"
598
+ nil
599
+ else
600
+ $1.gsub("''", "'")
601
+ end
532
602
  # Boolean types
533
- when 'true'.freeze, 'false'.freeze
534
- default
603
+ when "true", "false"
604
+ default
535
605
  # Numeric types
536
- when /\A\(?(-?\d+(\.\d*)?)\)?(::bigint)?\z/
537
- $1
606
+ when /\A\(?(-?\d+(\.\d*)?)\)?(::bigint)?\z/
607
+ $1
538
608
  # Object identifier types
539
- when /\A-?\d+\z/
540
- $1
541
- else
542
- # Anything else is blank, some user type, or some function
543
- # and we can't know the value of that, so return nil.
544
- nil
609
+ when /\A-?\d+\z/
610
+ $1
611
+ else
612
+ # Anything else is blank, some user type, or some function
613
+ # and we can't know the value of that, so return nil.
614
+ nil
545
615
  end
546
616
  end
547
617
 
548
- def extract_default_function(default_value, default) # :nodoc:
618
+ def extract_default_function(default_value, default)
549
619
  default if has_default_function?(default_value, default)
550
620
  end
551
621
 
552
- def has_default_function?(default_value, default) # :nodoc:
553
- !default_value && (%r{\w+\(.*\)|\(.*\)::\w+} === default)
622
+ def has_default_function?(default_value, default)
623
+ !default_value && %r{\w+\(.*\)|\(.*\)::\w+|CURRENT_DATE|CURRENT_TIMESTAMP}.match?(default)
554
624
  end
555
625
 
556
- def load_additional_types(type_map, oids = nil) # :nodoc:
626
+ def load_additional_types(oids = nil)
557
627
  initializer = OID::TypeMapInitializer.new(type_map)
558
628
 
559
- if supports_ranges?
560
- query = <<-SQL
561
- SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
562
- FROM pg_type as t
563
- LEFT JOIN pg_range as r ON oid = rngtypid
564
- SQL
565
- else
566
- query = <<-SQL
567
- SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, t.typtype, t.typbasetype
568
- FROM pg_type as t
569
- SQL
570
- end
629
+ query = <<~SQL
630
+ SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
631
+ FROM pg_type as t
632
+ LEFT JOIN pg_range as r ON oid = rngtypid
633
+ SQL
571
634
 
572
635
  if oids
573
- query += "WHERE t.oid::integer IN (%s)" % oids.join(", ")
636
+ query += "WHERE t.oid IN (%s)" % oids.join(", ")
574
637
  else
575
- query += initializer.query_conditions_for_initial_load(type_map)
638
+ query += initializer.query_conditions_for_initial_load
576
639
  end
577
640
 
578
- execute_and_clear(query, 'SCHEMA', []) do |records|
641
+ execute_and_clear(query, "SCHEMA", []) do |records|
579
642
  initializer.run(records)
580
643
  end
581
644
  end
@@ -583,6 +646,10 @@ module ActiveRecord
583
646
  FEATURE_NOT_SUPPORTED = "0A000" #:nodoc:
584
647
 
585
648
  def execute_and_clear(sql, name, binds, prepare: false)
649
+ if preventing_writes? && write_query?(sql)
650
+ raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
651
+ end
652
+
586
653
  if without_prepared_statement?(binds)
587
654
  result = exec_no_cache(sql, name, [])
588
655
  elsif !prepare
@@ -596,16 +663,31 @@ module ActiveRecord
596
663
  end
597
664
 
598
665
  def exec_no_cache(sql, name, binds)
666
+ materialize_transactions
667
+
668
+ # make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
669
+ # made since we established the connection
670
+ update_typemap_for_default_timezone
671
+
599
672
  type_casted_binds = type_casted_binds(binds)
600
- log(sql, name, binds, type_casted_binds) { @connection.async_exec(sql, type_casted_binds) }
673
+ log(sql, name, binds, type_casted_binds) do
674
+ ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
675
+ @connection.exec_params(sql, type_casted_binds)
676
+ end
677
+ end
601
678
  end
602
679
 
603
680
  def exec_cache(sql, name, binds)
604
- stmt_key = prepare_statement(sql)
681
+ materialize_transactions
682
+ update_typemap_for_default_timezone
683
+
684
+ stmt_key = prepare_statement(sql, binds)
605
685
  type_casted_binds = type_casted_binds(binds)
606
686
 
607
687
  log(sql, name, binds, type_casted_binds, stmt_key) do
608
- @connection.exec_prepared(stmt_key, type_casted_binds)
688
+ ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
689
+ @connection.exec_prepared(stmt_key, type_casted_binds)
690
+ end
609
691
  end
610
692
  rescue ActiveRecord::StatementInvalid => e
611
693
  raise unless is_cached_plan_failure?(e)
@@ -615,8 +697,10 @@ module ActiveRecord
615
697
  if in_transaction?
616
698
  raise ActiveRecord::PreparedStatementCacheExpired.new(e.cause.message)
617
699
  else
618
- # outside of transactions we can simply flush this query and retry
619
- @statements.delete sql_key(sql)
700
+ @lock.synchronize do
701
+ # outside of transactions we can simply flush this query and retry
702
+ @statements.delete sql_key(sql)
703
+ end
620
704
  retry
621
705
  end
622
706
  end
@@ -629,8 +713,8 @@ module ActiveRecord
629
713
  # ActiveRecord::PreparedStatementCacheExpired
630
714
  #
631
715
  # Check here for more details:
632
- # http://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/cache/plancache.c#l573
633
- CACHED_PLAN_HEURISTIC = 'cached plan must not change result type'.freeze
716
+ # https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/cache/plancache.c#l573
717
+ CACHED_PLAN_HEURISTIC = "cached plan must not change result type"
634
718
  def is_cached_plan_failure?(e)
635
719
  pgerror = e.cause
636
720
  code = pgerror.result.result_error_field(PG::PG_DIAG_SQLSTATE)
@@ -651,20 +735,22 @@ module ActiveRecord
651
735
 
652
736
  # Prepare the statement if it hasn't been prepared, return
653
737
  # the statement key.
654
- def prepare_statement(sql)
655
- sql_key = sql_key(sql)
656
- unless @statements.key? sql_key
657
- nextkey = @statements.next_key
658
- begin
659
- @connection.prepare nextkey, sql
660
- rescue => e
661
- raise translate_exception_class(e, sql)
738
+ def prepare_statement(sql, binds)
739
+ @lock.synchronize do
740
+ sql_key = sql_key(sql)
741
+ unless @statements.key? sql_key
742
+ nextkey = @statements.next_key
743
+ begin
744
+ @connection.prepare nextkey, sql
745
+ rescue => e
746
+ raise translate_exception_class(e, sql, binds)
747
+ end
748
+ # Clear the queue
749
+ @connection.get_last_result
750
+ @statements[sql_key] = nextkey
662
751
  end
663
- # Clear the queue
664
- @connection.get_last_result
665
- @statements[sql_key] = nextkey
752
+ @statements[sql_key]
666
753
  end
667
- @statements[sql_key]
668
754
  end
669
755
 
670
756
  # Connects to a PostgreSQL server and sets up the adapter depending on the
@@ -672,12 +758,8 @@ module ActiveRecord
672
758
  def connect
673
759
  @connection = PG.connect(@connection_parameters)
674
760
  configure_connection
675
- rescue ::PG::Error => error
676
- if error.message.include?("does not exist")
677
- raise ActiveRecord::NoDatabaseError
678
- else
679
- raise
680
- end
761
+ add_pg_encoders
762
+ add_pg_decoders
681
763
  end
682
764
 
683
765
  # Configures the encoding, verbosity, schema search path, and time zone of the connection.
@@ -686,39 +768,36 @@ module ActiveRecord
686
768
  if @config[:encoding]
687
769
  @connection.set_client_encoding(@config[:encoding])
688
770
  end
689
- self.client_min_messages = @config[:min_messages] || 'warning'
771
+ self.client_min_messages = @config[:min_messages] || "warning"
690
772
  self.schema_search_path = @config[:schema_search_path] || @config[:schema_order]
691
773
 
692
774
  # Use standard-conforming strings so we don't have to do the E'...' dance.
693
775
  set_standard_conforming_strings
694
776
 
777
+ variables = @config.fetch(:variables, {}).stringify_keys
778
+
695
779
  # If using Active Record's time zone support configure the connection to return
696
780
  # TIMESTAMP WITH ZONE types in UTC.
697
- # (SET TIME ZONE does not use an equals sign like other SET variables)
698
- if ActiveRecord::Base.default_timezone == :utc
699
- execute("SET time zone 'UTC'", 'SCHEMA')
700
- elsif @local_tz
701
- execute("SET time zone '#{@local_tz}'", 'SCHEMA')
781
+ unless variables["timezone"]
782
+ if ActiveRecord::Base.default_timezone == :utc
783
+ variables["timezone"] = "UTC"
784
+ elsif @local_tz
785
+ variables["timezone"] = @local_tz
786
+ end
702
787
  end
703
788
 
704
789
  # SET statements from :variables config hash
705
- # http://www.postgresql.org/docs/current/static/sql-set.html
706
- variables = @config[:variables] || {}
790
+ # https://www.postgresql.org/docs/current/static/sql-set.html
707
791
  variables.map do |k, v|
708
- if v == ':default' || v == :default
792
+ if v == ":default" || v == :default
709
793
  # Sets the value to the global or compile default
710
- execute("SET SESSION #{k} TO DEFAULT", 'SCHEMA')
794
+ execute("SET SESSION #{k} TO DEFAULT", "SCHEMA")
711
795
  elsif !v.nil?
712
- execute("SET SESSION #{k} TO #{quote(v)}", 'SCHEMA')
796
+ execute("SET SESSION #{k} TO #{quote(v)}", "SCHEMA")
713
797
  end
714
798
  end
715
799
  end
716
800
 
717
- # Returns the current ID of a table's sequence.
718
- def last_insert_id_result(sequence_name) # :nodoc:
719
- exec_query("SELECT currval('#{sequence_name}')", 'SQL')
720
- end
721
-
722
801
  # Returns the list of a table's column names, data types, and default values.
723
802
  #
724
803
  # The underlying query is roughly:
@@ -737,34 +816,38 @@ module ActiveRecord
737
816
  # Query implementation notes:
738
817
  # - format_type includes the column size constraint, e.g. varchar(50)
739
818
  # - ::regclass is a function that gives the id for a table name
740
- def column_definitions(table_name) # :nodoc:
741
- query(<<-end_sql, 'SCHEMA')
819
+ def column_definitions(table_name)
820
+ query(<<~SQL, "SCHEMA")
742
821
  SELECT a.attname, format_type(a.atttypid, a.atttypmod),
743
822
  pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
744
- (SELECT c.collname FROM pg_collation c, pg_type t
745
- WHERE c.oid = a.attcollation AND t.oid = a.atttypid AND a.attcollation <> t.typcollation),
746
- col_description(a.attrelid, a.attnum) AS comment
747
- FROM pg_attribute a LEFT JOIN pg_attrdef d
748
- ON a.attrelid = d.adrelid AND a.attnum = d.adnum
749
- WHERE a.attrelid = '#{quote_table_name(table_name)}'::regclass
823
+ c.collname, col_description(a.attrelid, a.attnum) AS comment
824
+ FROM pg_attribute a
825
+ LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
826
+ LEFT JOIN pg_type t ON a.atttypid = t.oid
827
+ LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation
828
+ WHERE a.attrelid = #{quote(quote_table_name(table_name))}::regclass
750
829
  AND a.attnum > 0 AND NOT a.attisdropped
751
830
  ORDER BY a.attnum
752
- end_sql
831
+ SQL
753
832
  end
754
833
 
755
- def extract_table_ref_from_insert_sql(sql) # :nodoc:
834
+ def extract_table_ref_from_insert_sql(sql)
756
835
  sql[/into\s("[A-Za-z0-9_."\[\]\s]+"|[A-Za-z0-9_."\[\]]+)\s*/im]
757
836
  $1.strip if $1
758
837
  end
759
838
 
760
- def create_table_definition(*args) # :nodoc:
761
- PostgreSQL::TableDefinition.new(*args)
839
+ def arel_visitor
840
+ Arel::Visitors::PostgreSQL.new(self)
841
+ end
842
+
843
+ def build_statement_pool
844
+ StatementPool.new(@connection, self.class.type_cast_config_to_integer(@config[:statement_limit]))
762
845
  end
763
846
 
764
847
  def can_perform_case_insensitive_comparison_for?(column)
765
848
  @case_insensitive_cache ||= {}
766
849
  @case_insensitive_cache[column.sql_type] ||= begin
767
- sql = <<-end_sql
850
+ sql = <<~SQL
768
851
  SELECT exists(
769
852
  SELECT * FROM pg_proc
770
853
  WHERE proname = 'lower'
@@ -776,7 +859,7 @@ module ActiveRecord
776
859
  WHERE proname = 'lower'
777
860
  AND castsource = #{quote column.sql_type}::regtype
778
861
  )
779
- end_sql
862
+ SQL
780
863
  execute_and_clear(sql, "SCHEMA", []) do |result|
781
864
  result.getvalue(0, 0)
782
865
  end
@@ -788,40 +871,65 @@ module ActiveRecord
788
871
  map[Integer] = PG::TextEncoder::Integer.new
789
872
  map[TrueClass] = PG::TextEncoder::Boolean.new
790
873
  map[FalseClass] = PG::TextEncoder::Boolean.new
791
- map[Float] = PG::TextEncoder::Float.new
792
874
  @connection.type_map_for_queries = map
793
875
  end
794
876
 
877
+ def update_typemap_for_default_timezone
878
+ if @default_timezone != ActiveRecord::Base.default_timezone && @timestamp_decoder
879
+ decoder_class = ActiveRecord::Base.default_timezone == :utc ?
880
+ PG::TextDecoder::TimestampUtc :
881
+ PG::TextDecoder::TimestampWithoutTimeZone
882
+
883
+ @timestamp_decoder = decoder_class.new(@timestamp_decoder.to_h)
884
+ @connection.type_map_for_results.add_coder(@timestamp_decoder)
885
+ @default_timezone = ActiveRecord::Base.default_timezone
886
+ end
887
+ end
888
+
795
889
  def add_pg_decoders
890
+ @default_timezone = nil
891
+ @timestamp_decoder = nil
892
+
796
893
  coders_by_name = {
797
- 'int2' => PG::TextDecoder::Integer,
798
- 'int4' => PG::TextDecoder::Integer,
799
- 'int8' => PG::TextDecoder::Integer,
800
- 'oid' => PG::TextDecoder::Integer,
801
- 'float4' => PG::TextDecoder::Float,
802
- 'float8' => PG::TextDecoder::Float,
803
- 'bool' => PG::TextDecoder::Boolean,
894
+ "int2" => PG::TextDecoder::Integer,
895
+ "int4" => PG::TextDecoder::Integer,
896
+ "int8" => PG::TextDecoder::Integer,
897
+ "oid" => PG::TextDecoder::Integer,
898
+ "float4" => PG::TextDecoder::Float,
899
+ "float8" => PG::TextDecoder::Float,
900
+ "bool" => PG::TextDecoder::Boolean,
804
901
  }
902
+
903
+ if defined?(PG::TextDecoder::TimestampUtc)
904
+ # Use native PG encoders available since pg-1.1
905
+ coders_by_name["timestamp"] = PG::TextDecoder::TimestampUtc
906
+ coders_by_name["timestamptz"] = PG::TextDecoder::TimestampWithTimeZone
907
+ end
908
+
805
909
  known_coder_types = coders_by_name.keys.map { |n| quote(n) }
806
- query = <<-SQL % known_coder_types.join(", ")
910
+ query = <<~SQL % known_coder_types.join(", ")
807
911
  SELECT t.oid, t.typname
808
912
  FROM pg_type as t
809
913
  WHERE t.typname IN (%s)
810
914
  SQL
811
915
  coders = execute_and_clear(query, "SCHEMA", []) do |result|
812
916
  result
813
- .map { |row| construct_coder(row, coders_by_name[row['typname']]) }
917
+ .map { |row| construct_coder(row, coders_by_name[row["typname"]]) }
814
918
  .compact
815
919
  end
816
920
 
817
921
  map = PG::TypeMapByOid.new
818
922
  coders.each { |coder| map.add_coder(coder) }
819
923
  @connection.type_map_for_results = map
924
+
925
+ # extract timestamp decoder for use in update_typemap_for_default_timezone
926
+ @timestamp_decoder = coders.find { |coder| coder.name == "timestamp" }
927
+ update_typemap_for_default_timezone
820
928
  end
821
929
 
822
930
  def construct_coder(row, coder_class)
823
931
  return unless coder_class
824
- coder_class.new(oid: row['oid'].to_i, name: row['typname'])
932
+ coder_class.new(oid: row["oid"].to_i, name: row["typname"])
825
933
  end
826
934
 
827
935
  ActiveRecord::Type.add_modifier({ array: true }, OID::Array, adapter: :postgresql)
@@ -830,16 +938,16 @@ module ActiveRecord
830
938
  ActiveRecord::Type.register(:bit_varying, OID::BitVarying, adapter: :postgresql)
831
939
  ActiveRecord::Type.register(:binary, OID::Bytea, adapter: :postgresql)
832
940
  ActiveRecord::Type.register(:cidr, OID::Cidr, adapter: :postgresql)
941
+ ActiveRecord::Type.register(:date, OID::Date, adapter: :postgresql)
833
942
  ActiveRecord::Type.register(:datetime, OID::DateTime, adapter: :postgresql)
834
943
  ActiveRecord::Type.register(:decimal, OID::Decimal, adapter: :postgresql)
835
944
  ActiveRecord::Type.register(:enum, OID::Enum, adapter: :postgresql)
836
945
  ActiveRecord::Type.register(:hstore, OID::Hstore, adapter: :postgresql)
837
946
  ActiveRecord::Type.register(:inet, OID::Inet, adapter: :postgresql)
838
- ActiveRecord::Type.register(:json, OID::Json, adapter: :postgresql)
839
947
  ActiveRecord::Type.register(:jsonb, OID::Jsonb, adapter: :postgresql)
840
948
  ActiveRecord::Type.register(:money, OID::Money, adapter: :postgresql)
841
- ActiveRecord::Type.register(:point, OID::Rails51Point, adapter: :postgresql)
842
- ActiveRecord::Type.register(:legacy_point, OID::Point, adapter: :postgresql)
949
+ ActiveRecord::Type.register(:point, OID::Point, adapter: :postgresql)
950
+ ActiveRecord::Type.register(:legacy_point, OID::LegacyPoint, adapter: :postgresql)
843
951
  ActiveRecord::Type.register(:uuid, OID::Uuid, adapter: :postgresql)
844
952
  ActiveRecord::Type.register(:vector, OID::Vector, adapter: :postgresql)
845
953
  ActiveRecord::Type.register(:xml, OID::Xml, adapter: :postgresql)