activerecord 5.2.8.1 → 6.1.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 (316) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +849 -630
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +7 -5
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record/aggregations.rb +5 -4
  7. data/lib/active_record/association_relation.rb +22 -12
  8. data/lib/active_record/associations/alias_tracker.rb +19 -16
  9. data/lib/active_record/associations/association.rb +95 -42
  10. data/lib/active_record/associations/association_scope.rb +21 -21
  11. data/lib/active_record/associations/belongs_to_association.rb +50 -46
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -5
  13. data/lib/active_record/associations/builder/association.rb +23 -21
  14. data/lib/active_record/associations/builder/belongs_to.rb +29 -59
  15. data/lib/active_record/associations/builder/collection_association.rb +8 -17
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
  17. data/lib/active_record/associations/builder/has_many.rb +8 -2
  18. data/lib/active_record/associations/builder/has_one.rb +33 -2
  19. data/lib/active_record/associations/builder/singular_association.rb +3 -1
  20. data/lib/active_record/associations/collection_association.rb +31 -29
  21. data/lib/active_record/associations/collection_proxy.rb +25 -21
  22. data/lib/active_record/associations/foreign_association.rb +20 -0
  23. data/lib/active_record/associations/has_many_association.rb +26 -13
  24. data/lib/active_record/associations/has_many_through_association.rb +24 -18
  25. data/lib/active_record/associations/has_one_association.rb +43 -31
  26. data/lib/active_record/associations/has_one_through_association.rb +5 -5
  27. data/lib/active_record/associations/join_dependency/join_association.rb +41 -20
  28. data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
  29. data/lib/active_record/associations/join_dependency.rb +91 -60
  30. data/lib/active_record/associations/preloader/association.rb +71 -43
  31. data/lib/active_record/associations/preloader/through_association.rb +49 -40
  32. data/lib/active_record/associations/preloader.rb +47 -34
  33. data/lib/active_record/associations/singular_association.rb +3 -17
  34. data/lib/active_record/associations/through_association.rb +1 -1
  35. data/lib/active_record/associations.rb +133 -25
  36. data/lib/active_record/attribute_assignment.rb +17 -19
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -7
  38. data/lib/active_record/attribute_methods/dirty.rb +101 -40
  39. data/lib/active_record/attribute_methods/primary_key.rb +20 -25
  40. data/lib/active_record/attribute_methods/query.rb +4 -8
  41. data/lib/active_record/attribute_methods/read.rb +14 -56
  42. data/lib/active_record/attribute_methods/serialization.rb +12 -7
  43. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
  44. data/lib/active_record/attribute_methods/write.rb +18 -34
  45. data/lib/active_record/attribute_methods.rb +81 -143
  46. data/lib/active_record/attributes.rb +45 -8
  47. data/lib/active_record/autosave_association.rb +57 -42
  48. data/lib/active_record/base.rb +4 -17
  49. data/lib/active_record/callbacks.rb +158 -43
  50. data/lib/active_record/coders/yaml_column.rb +2 -15
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +272 -130
  52. data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -36
  53. data/lib/active_record/connection_adapters/abstract/database_statements.rb +167 -146
  54. data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -14
  55. data/lib/active_record/connection_adapters/abstract/quoting.rb +98 -47
  56. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  57. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -110
  58. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +203 -90
  59. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -4
  60. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +381 -146
  61. data/lib/active_record/connection_adapters/abstract/transaction.rb +155 -68
  62. data/lib/active_record/connection_adapters/abstract_adapter.rb +229 -98
  63. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +243 -275
  64. data/lib/active_record/connection_adapters/column.rb +30 -12
  65. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  66. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
  67. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  68. data/lib/active_record/connection_adapters/mysql/database_statements.rb +86 -32
  69. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  70. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
  71. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
  72. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
  73. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +14 -6
  74. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +139 -19
  75. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
  76. data/lib/active_record/connection_adapters/mysql2_adapter.rb +53 -18
  77. data/lib/active_record/connection_adapters/pool_config.rb +63 -0
  78. data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
  79. data/lib/active_record/connection_adapters/postgresql/column.rb +37 -28
  80. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +38 -54
  81. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  82. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  83. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  84. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
  90. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  92. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
  94. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
  95. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  96. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
  97. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
  98. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  99. data/lib/active_record/connection_adapters/postgresql/quoting.rb +47 -10
  100. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
  101. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +19 -4
  102. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
  103. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  104. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +120 -100
  105. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
  106. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  107. data/lib/active_record/connection_adapters/postgresql_adapter.rb +222 -112
  108. data/lib/active_record/connection_adapters/schema_cache.rb +127 -21
  109. data/lib/active_record/connection_adapters/sql_type_metadata.rb +19 -6
  110. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
  111. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
  112. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  113. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +77 -13
  114. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +174 -186
  115. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  116. data/lib/active_record/connection_adapters.rb +50 -0
  117. data/lib/active_record/connection_handling.rb +285 -33
  118. data/lib/active_record/core.rb +304 -106
  119. data/lib/active_record/counter_cache.rb +8 -30
  120. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  121. data/lib/active_record/database_configurations/database_config.rb +80 -0
  122. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  123. data/lib/active_record/database_configurations/url_config.rb +53 -0
  124. data/lib/active_record/database_configurations.rb +272 -0
  125. data/lib/active_record/delegated_type.rb +209 -0
  126. data/lib/active_record/destroy_association_async_job.rb +36 -0
  127. data/lib/active_record/dynamic_matchers.rb +3 -4
  128. data/lib/active_record/enum.rb +71 -17
  129. data/lib/active_record/errors.rb +62 -19
  130. data/lib/active_record/explain.rb +10 -6
  131. data/lib/active_record/explain_subscriber.rb +1 -1
  132. data/lib/active_record/fixture_set/file.rb +10 -17
  133. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  134. data/lib/active_record/fixture_set/render_context.rb +17 -0
  135. data/lib/active_record/fixture_set/table_row.rb +152 -0
  136. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  137. data/lib/active_record/fixtures.rb +197 -481
  138. data/lib/active_record/gem_version.rb +4 -4
  139. data/lib/active_record/inheritance.rb +53 -24
  140. data/lib/active_record/insert_all.rb +208 -0
  141. data/lib/active_record/integration.rb +67 -17
  142. data/lib/active_record/internal_metadata.rb +26 -9
  143. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  144. data/lib/active_record/locking/optimistic.rb +26 -22
  145. data/lib/active_record/locking/pessimistic.rb +9 -5
  146. data/lib/active_record/log_subscriber.rb +34 -35
  147. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  148. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  149. data/lib/active_record/middleware/database_selector.rb +77 -0
  150. data/lib/active_record/migration/command_recorder.rb +96 -44
  151. data/lib/active_record/migration/compatibility.rb +141 -64
  152. data/lib/active_record/migration/join_table.rb +0 -1
  153. data/lib/active_record/migration.rb +205 -156
  154. data/lib/active_record/model_schema.rb +148 -22
  155. data/lib/active_record/nested_attributes.rb +4 -7
  156. data/lib/active_record/no_touching.rb +8 -1
  157. data/lib/active_record/null_relation.rb +0 -1
  158. data/lib/active_record/persistence.rb +267 -59
  159. data/lib/active_record/query_cache.rb +21 -4
  160. data/lib/active_record/querying.rb +40 -23
  161. data/lib/active_record/railtie.rb +113 -74
  162. data/lib/active_record/railties/controller_runtime.rb +30 -35
  163. data/lib/active_record/railties/databases.rake +402 -78
  164. data/lib/active_record/readonly_attributes.rb +4 -0
  165. data/lib/active_record/reflection.rb +109 -93
  166. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  167. data/lib/active_record/relation/batches.rb +44 -35
  168. data/lib/active_record/relation/calculations.rb +153 -90
  169. data/lib/active_record/relation/delegation.rb +35 -50
  170. data/lib/active_record/relation/finder_methods.rb +64 -39
  171. data/lib/active_record/relation/from_clause.rb +5 -1
  172. data/lib/active_record/relation/merger.rb +32 -40
  173. data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
  174. data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
  175. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  176. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -7
  177. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  178. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  179. data/lib/active_record/relation/predicate_builder.rb +58 -40
  180. data/lib/active_record/relation/query_attribute.rb +13 -8
  181. data/lib/active_record/relation/query_methods.rb +472 -186
  182. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  183. data/lib/active_record/relation/spawn_methods.rb +9 -9
  184. data/lib/active_record/relation/where_clause.rb +108 -58
  185. data/lib/active_record/relation.rb +375 -104
  186. data/lib/active_record/result.rb +64 -38
  187. data/lib/active_record/runtime_registry.rb +2 -2
  188. data/lib/active_record/sanitization.rb +22 -41
  189. data/lib/active_record/schema.rb +2 -11
  190. data/lib/active_record/schema_dumper.rb +54 -9
  191. data/lib/active_record/schema_migration.rb +7 -9
  192. data/lib/active_record/scoping/default.rb +4 -6
  193. data/lib/active_record/scoping/named.rb +17 -24
  194. data/lib/active_record/scoping.rb +8 -9
  195. data/lib/active_record/secure_token.rb +16 -8
  196. data/lib/active_record/serialization.rb +5 -3
  197. data/lib/active_record/signed_id.rb +116 -0
  198. data/lib/active_record/statement_cache.rb +49 -6
  199. data/lib/active_record/store.rb +88 -9
  200. data/lib/active_record/suppressor.rb +2 -2
  201. data/lib/active_record/table_metadata.rb +39 -43
  202. data/lib/active_record/tasks/database_tasks.rb +276 -81
  203. data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
  204. data/lib/active_record/tasks/postgresql_database_tasks.rb +27 -32
  205. data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
  206. data/lib/active_record/test_databases.rb +24 -0
  207. data/lib/active_record/test_fixtures.rb +246 -0
  208. data/lib/active_record/timestamp.rb +43 -32
  209. data/lib/active_record/touch_later.rb +23 -22
  210. data/lib/active_record/transactions.rb +58 -116
  211. data/lib/active_record/translation.rb +1 -1
  212. data/lib/active_record/type/adapter_specific_registry.rb +3 -13
  213. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  214. data/lib/active_record/type/serialized.rb +6 -3
  215. data/lib/active_record/type/time.rb +10 -0
  216. data/lib/active_record/type/type_map.rb +0 -1
  217. data/lib/active_record/type/unsigned_integer.rb +0 -1
  218. data/lib/active_record/type.rb +10 -5
  219. data/lib/active_record/type_caster/connection.rb +15 -15
  220. data/lib/active_record/type_caster/map.rb +8 -8
  221. data/lib/active_record/validations/associated.rb +1 -2
  222. data/lib/active_record/validations/numericality.rb +35 -0
  223. data/lib/active_record/validations/uniqueness.rb +38 -30
  224. data/lib/active_record/validations.rb +4 -3
  225. data/lib/active_record.rb +13 -12
  226. data/lib/arel/alias_predication.rb +9 -0
  227. data/lib/arel/attributes/attribute.rb +41 -0
  228. data/lib/arel/collectors/bind.rb +29 -0
  229. data/lib/arel/collectors/composite.rb +39 -0
  230. data/lib/arel/collectors/plain_string.rb +20 -0
  231. data/lib/arel/collectors/sql_string.rb +27 -0
  232. data/lib/arel/collectors/substitute_binds.rb +35 -0
  233. data/lib/arel/crud.rb +42 -0
  234. data/lib/arel/delete_manager.rb +18 -0
  235. data/lib/arel/errors.rb +9 -0
  236. data/lib/arel/expressions.rb +29 -0
  237. data/lib/arel/factory_methods.rb +49 -0
  238. data/lib/arel/insert_manager.rb +49 -0
  239. data/lib/arel/math.rb +45 -0
  240. data/lib/arel/nodes/and.rb +32 -0
  241. data/lib/arel/nodes/ascending.rb +23 -0
  242. data/lib/arel/nodes/binary.rb +126 -0
  243. data/lib/arel/nodes/bind_param.rb +44 -0
  244. data/lib/arel/nodes/case.rb +55 -0
  245. data/lib/arel/nodes/casted.rb +62 -0
  246. data/lib/arel/nodes/comment.rb +29 -0
  247. data/lib/arel/nodes/count.rb +12 -0
  248. data/lib/arel/nodes/delete_statement.rb +45 -0
  249. data/lib/arel/nodes/descending.rb +23 -0
  250. data/lib/arel/nodes/equality.rb +15 -0
  251. data/lib/arel/nodes/extract.rb +24 -0
  252. data/lib/arel/nodes/false.rb +16 -0
  253. data/lib/arel/nodes/full_outer_join.rb +8 -0
  254. data/lib/arel/nodes/function.rb +44 -0
  255. data/lib/arel/nodes/grouping.rb +11 -0
  256. data/lib/arel/nodes/homogeneous_in.rb +72 -0
  257. data/lib/arel/nodes/in.rb +15 -0
  258. data/lib/arel/nodes/infix_operation.rb +92 -0
  259. data/lib/arel/nodes/inner_join.rb +8 -0
  260. data/lib/arel/nodes/insert_statement.rb +37 -0
  261. data/lib/arel/nodes/join_source.rb +20 -0
  262. data/lib/arel/nodes/matches.rb +18 -0
  263. data/lib/arel/nodes/named_function.rb +23 -0
  264. data/lib/arel/nodes/node.rb +51 -0
  265. data/lib/arel/nodes/node_expression.rb +13 -0
  266. data/lib/arel/nodes/ordering.rb +27 -0
  267. data/lib/arel/nodes/outer_join.rb +8 -0
  268. data/lib/arel/nodes/over.rb +15 -0
  269. data/lib/arel/nodes/regexp.rb +16 -0
  270. data/lib/arel/nodes/right_outer_join.rb +8 -0
  271. data/lib/arel/nodes/select_core.rb +67 -0
  272. data/lib/arel/nodes/select_statement.rb +41 -0
  273. data/lib/arel/nodes/sql_literal.rb +19 -0
  274. data/lib/arel/nodes/string_join.rb +11 -0
  275. data/lib/arel/nodes/table_alias.rb +31 -0
  276. data/lib/arel/nodes/terminal.rb +16 -0
  277. data/lib/arel/nodes/true.rb +16 -0
  278. data/lib/arel/nodes/unary.rb +44 -0
  279. data/lib/arel/nodes/unary_operation.rb +20 -0
  280. data/lib/arel/nodes/unqualified_column.rb +22 -0
  281. data/lib/arel/nodes/update_statement.rb +41 -0
  282. data/lib/arel/nodes/values_list.rb +9 -0
  283. data/lib/arel/nodes/window.rb +126 -0
  284. data/lib/arel/nodes/with.rb +11 -0
  285. data/lib/arel/nodes.rb +70 -0
  286. data/lib/arel/order_predications.rb +13 -0
  287. data/lib/arel/predications.rb +250 -0
  288. data/lib/arel/select_manager.rb +270 -0
  289. data/lib/arel/table.rb +118 -0
  290. data/lib/arel/tree_manager.rb +72 -0
  291. data/lib/arel/update_manager.rb +34 -0
  292. data/lib/arel/visitors/dot.rb +308 -0
  293. data/lib/arel/visitors/mysql.rb +93 -0
  294. data/lib/arel/visitors/postgresql.rb +120 -0
  295. data/lib/arel/visitors/sqlite.rb +38 -0
  296. data/lib/arel/visitors/to_sql.rb +899 -0
  297. data/lib/arel/visitors/visitor.rb +45 -0
  298. data/lib/arel/visitors.rb +13 -0
  299. data/lib/arel/window_predications.rb +9 -0
  300. data/lib/arel.rb +54 -0
  301. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  302. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
  303. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
  304. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
  305. data/lib/rails/generators/active_record/migration.rb +19 -2
  306. data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
  307. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  308. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  309. metadata +120 -35
  310. data/lib/active_record/attribute_decorators.rb +0 -90
  311. data/lib/active_record/collection_cache_key.rb +0 -53
  312. data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
  313. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
  314. data/lib/active_record/define_callbacks.rb +0 -22
  315. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
  316. data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -1,17 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Make sure we're using pg high enough for type casts and Ruby 2.2+ compatibility
4
- gem "pg", ">= 0.18", "< 2.0"
3
+ gem "pg", "~> 1.1"
5
4
  require "pg"
6
5
 
7
- # Use async_exec instead of exec_params on pg versions before 1.1
8
- class ::PG::Connection
9
- unless self.public_method_defined?(:async_exec_params)
10
- remove_method :exec_params
11
- alias exec_params async_exec
12
- end
13
- end
14
-
6
+ require "active_support/core_ext/object/try"
15
7
  require "active_record/connection_adapters/abstract_adapter"
16
8
  require "active_record/connection_adapters/statement_pool"
17
9
  require "active_record/connection_adapters/postgresql/column"
@@ -31,9 +23,7 @@ module ActiveRecord
31
23
  module ConnectionHandling # :nodoc:
32
24
  # Establishes a connection to the database that's used by all Active Record objects
33
25
  def postgresql_connection(config)
34
- conn_params = config.symbolize_keys
35
-
36
- conn_params.delete_if { |_, v| v.nil? }
26
+ conn_params = config.symbolize_keys.compact
37
27
 
38
28
  # Map ActiveRecords param names to PGs.
39
29
  conn_params[:user] = conn_params.delete(:username) if conn_params[:username]
@@ -43,14 +33,17 @@ module ActiveRecord
43
33
  valid_conn_param_keys = PG::Connection.conndefaults_hash.keys + [:requiressl]
44
34
  conn_params.slice!(*valid_conn_param_keys)
45
35
 
46
- # The postgres drivers don't allow the creation of an unconnected PG::Connection object,
47
- # so just pass a nil connection object for the time being.
48
- ConnectionAdapters::PostgreSQLAdapter.new(nil, logger, conn_params, config)
36
+ ConnectionAdapters::PostgreSQLAdapter.new(
37
+ ConnectionAdapters::PostgreSQLAdapter.new_client(conn_params),
38
+ logger,
39
+ conn_params,
40
+ config,
41
+ )
49
42
  end
50
43
  end
51
44
 
52
45
  module ConnectionAdapters
53
- # The PostgreSQL adapter works with the native C (https://bitbucket.org/ged/ruby-pg) driver.
46
+ # The PostgreSQL adapter works with the native C (https://github.com/ged/ruby-pg) driver.
54
47
  #
55
48
  # Options:
56
49
  #
@@ -78,7 +71,32 @@ module ActiveRecord
78
71
  # In addition, default connection parameters of libpq can be set per environment variables.
79
72
  # See https://www.postgresql.org/docs/current/static/libpq-envars.html .
80
73
  class PostgreSQLAdapter < AbstractAdapter
81
- ADAPTER_NAME = "PostgreSQL".freeze
74
+ ADAPTER_NAME = "PostgreSQL"
75
+
76
+ class << self
77
+ def new_client(conn_params)
78
+ PG.connect(conn_params)
79
+ rescue ::PG::Error => error
80
+ if conn_params && conn_params[:dbname] && error.message.include?(conn_params[:dbname])
81
+ raise ActiveRecord::NoDatabaseError
82
+ else
83
+ raise ActiveRecord::ConnectionNotEstablished, error.message
84
+ end
85
+ end
86
+ end
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
82
100
 
83
101
  NATIVE_DATABASE_TYPES = {
84
102
  primary_key: "bigserial primary key",
@@ -138,6 +156,10 @@ module ActiveRecord
138
156
  true
139
157
  end
140
158
 
159
+ def supports_partitioned_indexes?
160
+ database_version >= 110_000
161
+ end
162
+
141
163
  def supports_partial_index?
142
164
  true
143
165
  end
@@ -154,6 +176,10 @@ module ActiveRecord
154
176
  true
155
177
  end
156
178
 
179
+ def supports_check_constraints?
180
+ true
181
+ end
182
+
157
183
  def supports_validate_constraints?
158
184
  true
159
185
  end
@@ -167,7 +193,7 @@ module ActiveRecord
167
193
  end
168
194
 
169
195
  def supports_json?
170
- postgresql_version >= 90200
196
+ true
171
197
  end
172
198
 
173
199
  def supports_comments?
@@ -178,6 +204,17 @@ module ActiveRecord
178
204
  true
179
205
  end
180
206
 
207
+ def supports_insert_returning?
208
+ true
209
+ end
210
+
211
+ def supports_insert_on_conflict?
212
+ database_version >= 90500
213
+ end
214
+ alias supports_insert_on_duplicate_skip? supports_insert_on_conflict?
215
+ alias supports_insert_on_duplicate_update? supports_insert_on_conflict?
216
+ alias supports_insert_conflict_target? supports_insert_on_conflict?
217
+
181
218
  def index_algorithms
182
219
  { concurrently: "CONCURRENTLY" }
183
220
  end
@@ -220,15 +257,8 @@ module ActiveRecord
220
257
  @local_tz = nil
221
258
  @max_identifier_length = nil
222
259
 
223
- connect
260
+ configure_connection
224
261
  add_pg_encoders
225
- @statements = StatementPool.new @connection,
226
- self.class.type_cast_config_to_integer(config[:statement_limit])
227
-
228
- if postgresql_version < 90100
229
- raise "Your version of PostgreSQL (#{postgresql_version}) is too old. Active Record supports PostgreSQL >= 9.1."
230
- end
231
-
232
262
  add_pg_decoders
233
263
 
234
264
  @type_map = Type::HashLookupTypeMap.new
@@ -237,15 +267,10 @@ module ActiveRecord
237
267
  @use_insert_returning = @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
238
268
  end
239
269
 
240
- # Clears the prepared statements cache.
241
- def clear_cache!
242
- @lock.synchronize do
243
- @statements.clear
244
- end
245
- end
246
-
247
- def truncate(table_name, name = nil)
248
- exec_query "TRUNCATE TABLE #{quote_table_name(table_name)}", name, []
270
+ def self.database_exists?(config)
271
+ !!ActiveRecord::Base.postgresql_connection(config)
272
+ rescue ActiveRecord::NoDatabaseError
273
+ false
249
274
  end
250
275
 
251
276
  # Is this connection alive and ready for queries?
@@ -264,6 +289,8 @@ module ActiveRecord
264
289
  super
265
290
  @connection.reset
266
291
  configure_connection
292
+ rescue PG::ConnectionBad
293
+ connect
267
294
  end
268
295
  end
269
296
 
@@ -289,6 +316,7 @@ module ActiveRecord
289
316
  end
290
317
 
291
318
  def discard! # :nodoc:
319
+ super
292
320
  @connection.socket_io.reopen(IO::NULL) rescue nil
293
321
  @connection = nil
294
322
  end
@@ -317,21 +345,31 @@ module ActiveRecord
317
345
  true
318
346
  end
319
347
 
320
- def supports_ranges?
321
- # Range datatypes weren't introduced until PostgreSQL 9.2
322
- postgresql_version >= 90200
323
- end
324
-
325
348
  def supports_materialized_views?
326
- postgresql_version >= 90300
349
+ true
327
350
  end
328
351
 
329
352
  def supports_foreign_tables?
330
- postgresql_version >= 90300
353
+ true
331
354
  end
332
355
 
333
356
  def supports_pgcrypto_uuid?
334
- postgresql_version >= 90400
357
+ database_version >= 90400
358
+ end
359
+
360
+ def supports_optimizer_hints?
361
+ unless defined?(@has_pg_hint_plan)
362
+ @has_pg_hint_plan = extension_available?("pg_hint_plan")
363
+ end
364
+ @has_pg_hint_plan
365
+ end
366
+
367
+ def supports_common_table_expressions?
368
+ true
369
+ end
370
+
371
+ def supports_lazy_transactions?
372
+ true
335
373
  end
336
374
 
337
375
  def get_advisory_lock(lock_id) # :nodoc:
@@ -360,9 +398,12 @@ module ActiveRecord
360
398
  }
361
399
  end
362
400
 
401
+ def extension_available?(name)
402
+ query_value("SELECT true FROM pg_available_extensions WHERE name = #{quote(name)}", "SCHEMA")
403
+ end
404
+
363
405
  def extension_enabled?(name)
364
- res = exec_query("SELECT EXISTS(SELECT * FROM pg_available_extensions WHERE name = '#{name}' AND installed_version IS NOT NULL) as enabled", "SCHEMA")
365
- res.cast_values.first
406
+ query_value("SELECT installed_version IS NOT NULL FROM pg_available_extensions WHERE name = #{quote(name)}", "SCHEMA")
366
407
  end
367
408
 
368
409
  def extensions
@@ -373,8 +414,6 @@ module ActiveRecord
373
414
  def max_identifier_length
374
415
  @max_identifier_length ||= query_value("SHOW max_identifier_length", "SCHEMA").to_i
375
416
  end
376
- alias table_alias_length max_identifier_length
377
- alias index_name_length max_identifier_length
378
417
 
379
418
  # Set the authorized user for this session
380
419
  def session_auth=(user)
@@ -386,25 +425,37 @@ module ActiveRecord
386
425
  @use_insert_returning
387
426
  end
388
427
 
389
- def column_name_for_operation(operation, node) # :nodoc:
390
- OPERATION_ALIASES.fetch(operation) { operation.downcase }
391
- end
392
-
393
- OPERATION_ALIASES = { # :nodoc:
394
- "maximum" => "max",
395
- "minimum" => "min",
396
- "average" => "avg",
397
- }
398
-
399
428
  # Returns the version of the connected PostgreSQL server.
400
- def postgresql_version
429
+ def get_database_version # :nodoc:
401
430
  @connection.server_version
402
431
  end
432
+ alias :postgresql_version :database_version
403
433
 
404
434
  def default_index_type?(index) # :nodoc:
405
435
  index.using == :btree || super
406
436
  end
407
437
 
438
+ def build_insert_sql(insert) # :nodoc:
439
+ sql = +"INSERT #{insert.into} #{insert.values_list}"
440
+
441
+ if insert.skip_duplicates?
442
+ sql << " ON CONFLICT #{insert.conflict_target} DO NOTHING"
443
+ elsif insert.update_duplicates?
444
+ sql << " ON CONFLICT #{insert.conflict_target} DO UPDATE SET "
445
+ sql << insert.touch_model_timestamps_unless { |column| "#{insert.model.quoted_table_name}.#{column} IS NOT DISTINCT FROM excluded.#{column}" }
446
+ sql << insert.updatable_columns.map { |column| "#{column}=excluded.#{column}" }.join(",")
447
+ end
448
+
449
+ sql << " RETURNING #{insert.returning}" if insert.returning
450
+ sql
451
+ end
452
+
453
+ def check_version # :nodoc:
454
+ if database_version < 90300
455
+ raise "Your version of PostgreSQL (#{database_version}) is too old. Active Record supports PostgreSQL >= 9.3."
456
+ end
457
+ end
458
+
408
459
  private
409
460
  # See https://www.postgresql.org/docs/current/static/errcodes-appendix.html
410
461
  VALUE_LIMIT_VIOLATION = "22001"
@@ -414,37 +465,46 @@ module ActiveRecord
414
465
  UNIQUE_VIOLATION = "23505"
415
466
  SERIALIZATION_FAILURE = "40001"
416
467
  DEADLOCK_DETECTED = "40P01"
468
+ DUPLICATE_DATABASE = "42P04"
417
469
  LOCK_NOT_AVAILABLE = "55P03"
418
470
  QUERY_CANCELED = "57014"
419
471
 
420
- def translate_exception(exception, message)
472
+ def translate_exception(exception, message:, sql:, binds:)
421
473
  return exception unless exception.respond_to?(:result)
422
474
 
423
475
  case exception.result.try(:error_field, PG::PG_DIAG_SQLSTATE)
476
+ when nil
477
+ if exception.message.match?(/connection is closed/i)
478
+ ConnectionNotEstablished.new(exception)
479
+ else
480
+ super
481
+ end
424
482
  when UNIQUE_VIOLATION
425
- RecordNotUnique.new(message)
483
+ RecordNotUnique.new(message, sql: sql, binds: binds)
426
484
  when FOREIGN_KEY_VIOLATION
427
- InvalidForeignKey.new(message)
485
+ InvalidForeignKey.new(message, sql: sql, binds: binds)
428
486
  when VALUE_LIMIT_VIOLATION
429
- ValueTooLong.new(message)
487
+ ValueTooLong.new(message, sql: sql, binds: binds)
430
488
  when NUMERIC_VALUE_OUT_OF_RANGE
431
- RangeError.new(message)
489
+ RangeError.new(message, sql: sql, binds: binds)
432
490
  when NOT_NULL_VIOLATION
433
- NotNullViolation.new(message)
491
+ NotNullViolation.new(message, sql: sql, binds: binds)
434
492
  when SERIALIZATION_FAILURE
435
- SerializationFailure.new(message)
493
+ SerializationFailure.new(message, sql: sql, binds: binds)
436
494
  when DEADLOCK_DETECTED
437
- Deadlocked.new(message)
495
+ Deadlocked.new(message, sql: sql, binds: binds)
496
+ when DUPLICATE_DATABASE
497
+ DatabaseAlreadyExists.new(message, sql: sql, binds: binds)
438
498
  when LOCK_NOT_AVAILABLE
439
- LockWaitTimeout.new(message)
499
+ LockWaitTimeout.new(message, sql: sql, binds: binds)
440
500
  when QUERY_CANCELED
441
- QueryCanceled.new(message)
501
+ QueryCanceled.new(message, sql: sql, binds: binds)
442
502
  else
443
503
  super
444
504
  end
445
505
  end
446
506
 
447
- def get_oid_type(oid, fmod, column_name, sql_type = "".freeze)
507
+ def get_oid_type(oid, fmod, column_name, sql_type = "")
448
508
  if !type_map.key?(oid)
449
509
  load_additional_types([oid])
450
510
  end
@@ -486,7 +546,7 @@ module ActiveRecord
486
546
  m.register_type "uuid", OID::Uuid.new
487
547
  m.register_type "xml", OID::Xml.new
488
548
  m.register_type "tsvector", OID::SpecializedString.new(:tsvector)
489
- m.register_type "macaddr", OID::SpecializedString.new(:macaddr)
549
+ m.register_type "macaddr", OID::Macaddr.new
490
550
  m.register_type "citext", OID::SpecializedString.new(:citext)
491
551
  m.register_type "ltree", OID::SpecializedString.new(:ltree)
492
552
  m.register_type "line", OID::SpecializedString.new(:line)
@@ -496,11 +556,6 @@ module ActiveRecord
496
556
  m.register_type "polygon", OID::SpecializedString.new(:polygon)
497
557
  m.register_type "circle", OID::SpecializedString.new(:circle)
498
558
 
499
- m.register_type "interval" do |_, _, sql_type|
500
- precision = extract_precision(sql_type)
501
- OID::SpecializedString.new(:interval, precision: precision)
502
- end
503
-
504
559
  register_class_with_precision m, "time", Type::Time
505
560
  register_class_with_precision m, "timestamp", OID::DateTime
506
561
 
@@ -524,6 +579,11 @@ module ActiveRecord
524
579
  end
525
580
  end
526
581
 
582
+ m.register_type "interval" do |*args, sql_type|
583
+ precision = extract_precision(sql_type)
584
+ OID::Interval.new(precision: precision)
585
+ end
586
+
527
587
  load_additional_types
528
588
  end
529
589
 
@@ -533,13 +593,13 @@ module ActiveRecord
533
593
  # Quoted types
534
594
  when /\A[\(B]?'(.*)'.*::"?([\w. ]+)"?(?:\[\])?\z/m
535
595
  # The default 'now'::date is CURRENT_DATE
536
- if $1 == "now".freeze && $2 == "date".freeze
596
+ if $1 == "now" && $2 == "date"
537
597
  nil
538
598
  else
539
- $1.gsub("''".freeze, "'".freeze)
599
+ $1.gsub("''", "'")
540
600
  end
541
601
  # Boolean types
542
- when "true".freeze, "false".freeze
602
+ when "true", "false"
543
603
  default
544
604
  # Numeric types
545
605
  when /\A\(?(-?\d+(\.\d*)?)\)?(::bigint)?\z/
@@ -565,21 +625,14 @@ module ActiveRecord
565
625
  def load_additional_types(oids = nil)
566
626
  initializer = OID::TypeMapInitializer.new(type_map)
567
627
 
568
- if supports_ranges?
569
- query = <<-SQL
570
- SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
571
- FROM pg_type as t
572
- LEFT JOIN pg_range as r ON oid = rngtypid
573
- SQL
574
- else
575
- query = <<-SQL
576
- SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, t.typtype, t.typbasetype
577
- FROM pg_type as t
578
- SQL
579
- end
628
+ query = <<~SQL
629
+ SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
630
+ FROM pg_type as t
631
+ LEFT JOIN pg_range as r ON oid = rngtypid
632
+ SQL
580
633
 
581
634
  if oids
582
- query += "WHERE t.oid::integer IN (%s)" % oids.join(", ")
635
+ query += "WHERE t.oid IN (%s)" % oids.join(", ")
583
636
  else
584
637
  query += initializer.query_conditions_for_initial_load
585
638
  end
@@ -592,6 +645,10 @@ module ActiveRecord
592
645
  FEATURE_NOT_SUPPORTED = "0A000" #:nodoc:
593
646
 
594
647
  def execute_and_clear(sql, name, binds, prepare: false)
648
+ if preventing_writes? && write_query?(sql)
649
+ raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
650
+ end
651
+
595
652
  if without_prepared_statement?(binds)
596
653
  result = exec_no_cache(sql, name, [])
597
654
  elsif !prepare
@@ -599,12 +656,22 @@ module ActiveRecord
599
656
  else
600
657
  result = exec_cache(sql, name, binds)
601
658
  end
602
- ret = yield result
603
- result.clear
659
+ begin
660
+ ret = yield result
661
+ ensure
662
+ result.clear
663
+ end
604
664
  ret
605
665
  end
606
666
 
607
667
  def exec_no_cache(sql, name, binds)
668
+ materialize_transactions
669
+ mark_transaction_written_if_write(sql)
670
+
671
+ # make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
672
+ # made since we established the connection
673
+ update_typemap_for_default_timezone
674
+
608
675
  type_casted_binds = type_casted_binds(binds)
609
676
  log(sql, name, binds, type_casted_binds) do
610
677
  ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
@@ -614,7 +681,11 @@ module ActiveRecord
614
681
  end
615
682
 
616
683
  def exec_cache(sql, name, binds)
617
- stmt_key = prepare_statement(sql)
684
+ materialize_transactions
685
+ mark_transaction_written_if_write(sql)
686
+ update_typemap_for_default_timezone
687
+
688
+ stmt_key = prepare_statement(sql, binds)
618
689
  type_casted_binds = type_casted_binds(binds)
619
690
 
620
691
  log(sql, name, binds, type_casted_binds, stmt_key) do
@@ -647,11 +718,10 @@ module ActiveRecord
647
718
  #
648
719
  # Check here for more details:
649
720
  # https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/cache/plancache.c#l573
650
- CACHED_PLAN_HEURISTIC = "cached plan must not change result type".freeze
651
721
  def is_cached_plan_failure?(e)
652
722
  pgerror = e.cause
653
- code = pgerror.result.result_error_field(PG::PG_DIAG_SQLSTATE)
654
- code == FEATURE_NOT_SUPPORTED && pgerror.message.include?(CACHED_PLAN_HEURISTIC)
723
+ pgerror.result.result_error_field(PG::PG_DIAG_SQLSTATE) == FEATURE_NOT_SUPPORTED &&
724
+ pgerror.result.result_error_field(PG::PG_DIAG_SOURCE_FUNCTION) == "RevalidateCachedQuery"
655
725
  rescue
656
726
  false
657
727
  end
@@ -668,7 +738,7 @@ module ActiveRecord
668
738
 
669
739
  # Prepare the statement if it hasn't been prepared, return
670
740
  # the statement key.
671
- def prepare_statement(sql)
741
+ def prepare_statement(sql, binds)
672
742
  @lock.synchronize do
673
743
  sql_key = sql_key(sql)
674
744
  unless @statements.key? sql_key
@@ -676,7 +746,7 @@ module ActiveRecord
676
746
  begin
677
747
  @connection.prepare nextkey, sql
678
748
  rescue => e
679
- raise translate_exception_class(e, sql)
749
+ raise translate_exception_class(e, sql, binds)
680
750
  end
681
751
  # Clear the queue
682
752
  @connection.get_last_result
@@ -689,14 +759,10 @@ module ActiveRecord
689
759
  # Connects to a PostgreSQL server and sets up the adapter depending on the
690
760
  # connected server's characteristics.
691
761
  def connect
692
- @connection = PG.connect(@connection_parameters)
762
+ @connection = self.class.new_client(@connection_parameters)
693
763
  configure_connection
694
- rescue ::PG::Error => error
695
- if error.message.include?("does not exist")
696
- raise ActiveRecord::NoDatabaseError
697
- else
698
- raise
699
- end
764
+ add_pg_encoders
765
+ add_pg_decoders
700
766
  end
701
767
 
702
768
  # Configures the encoding, verbosity, schema search path, and time zone of the connection.
@@ -723,6 +789,9 @@ module ActiveRecord
723
789
  end
724
790
  end
725
791
 
792
+ # Set interval output format to ISO 8601 for ease of parsing by ActiveSupport::Duration.parse
793
+ execute("SET intervalstyle = iso_8601", "SCHEMA")
794
+
726
795
  # SET statements from :variables config hash
727
796
  # https://www.postgresql.org/docs/current/static/sql-set.html
728
797
  variables.map do |k, v|
@@ -754,7 +823,7 @@ module ActiveRecord
754
823
  # - format_type includes the column size constraint, e.g. varchar(50)
755
824
  # - ::regclass is a function that gives the id for a table name
756
825
  def column_definitions(table_name)
757
- query(<<-end_sql, "SCHEMA")
826
+ query(<<~SQL, "SCHEMA")
758
827
  SELECT a.attname, format_type(a.atttypid, a.atttypmod),
759
828
  pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
760
829
  c.collname, col_description(a.attrelid, a.attnum) AS comment
@@ -765,7 +834,7 @@ module ActiveRecord
765
834
  WHERE a.attrelid = #{quote(quote_table_name(table_name))}::regclass
766
835
  AND a.attnum > 0 AND NOT a.attisdropped
767
836
  ORDER BY a.attnum
768
- end_sql
837
+ SQL
769
838
  end
770
839
 
771
840
  def extract_table_ref_from_insert_sql(sql)
@@ -777,10 +846,14 @@ module ActiveRecord
777
846
  Arel::Visitors::PostgreSQL.new(self)
778
847
  end
779
848
 
849
+ def build_statement_pool
850
+ StatementPool.new(@connection, self.class.type_cast_config_to_integer(@config[:statement_limit]))
851
+ end
852
+
780
853
  def can_perform_case_insensitive_comparison_for?(column)
781
854
  @case_insensitive_cache ||= {}
782
855
  @case_insensitive_cache[column.sql_type] ||= begin
783
- sql = <<-end_sql
856
+ sql = <<~SQL
784
857
  SELECT exists(
785
858
  SELECT * FROM pg_proc
786
859
  WHERE proname = 'lower'
@@ -792,7 +865,7 @@ module ActiveRecord
792
865
  WHERE proname = 'lower'
793
866
  AND castsource = #{quote column.sql_type}::regtype
794
867
  )
795
- end_sql
868
+ SQL
796
869
  execute_and_clear(sql, "SCHEMA", []) do |result|
797
870
  result.getvalue(0, 0)
798
871
  end
@@ -807,7 +880,22 @@ module ActiveRecord
807
880
  @connection.type_map_for_queries = map
808
881
  end
809
882
 
883
+ def update_typemap_for_default_timezone
884
+ if @default_timezone != ActiveRecord::Base.default_timezone && @timestamp_decoder
885
+ decoder_class = ActiveRecord::Base.default_timezone == :utc ?
886
+ PG::TextDecoder::TimestampUtc :
887
+ PG::TextDecoder::TimestampWithoutTimeZone
888
+
889
+ @timestamp_decoder = decoder_class.new(@timestamp_decoder.to_h)
890
+ @connection.type_map_for_results.add_coder(@timestamp_decoder)
891
+ @default_timezone = ActiveRecord::Base.default_timezone
892
+ end
893
+ end
894
+
810
895
  def add_pg_decoders
896
+ @default_timezone = nil
897
+ @timestamp_decoder = nil
898
+
811
899
  coders_by_name = {
812
900
  "int2" => PG::TextDecoder::Integer,
813
901
  "int4" => PG::TextDecoder::Integer,
@@ -815,10 +903,14 @@ module ActiveRecord
815
903
  "oid" => PG::TextDecoder::Integer,
816
904
  "float4" => PG::TextDecoder::Float,
817
905
  "float8" => PG::TextDecoder::Float,
906
+ "numeric" => PG::TextDecoder::Numeric,
818
907
  "bool" => PG::TextDecoder::Boolean,
908
+ "timestamp" => PG::TextDecoder::TimestampUtc,
909
+ "timestamptz" => PG::TextDecoder::TimestampWithTimeZone,
819
910
  }
911
+
820
912
  known_coder_types = coders_by_name.keys.map { |n| quote(n) }
821
- query = <<-SQL % known_coder_types.join(", ")
913
+ query = <<~SQL % known_coder_types.join(", ")
822
914
  SELECT t.oid, t.typname
823
915
  FROM pg_type as t
824
916
  WHERE t.typname IN (%s)
@@ -832,6 +924,15 @@ module ActiveRecord
832
924
  map = PG::TypeMapByOid.new
833
925
  coders.each { |coder| map.add_coder(coder) }
834
926
  @connection.type_map_for_results = map
927
+
928
+ @type_map_for_results = PG::TypeMapByOid.new
929
+ @type_map_for_results.default_type_map = map
930
+ @type_map_for_results.add_coder(PG::TextDecoder::Bytea.new(oid: 17, name: "bytea"))
931
+ @type_map_for_results.add_coder(MoneyDecoder.new(oid: 790, name: "money"))
932
+
933
+ # extract timestamp decoder for use in update_typemap_for_default_timezone
934
+ @timestamp_decoder = coders.find { |coder| coder.name == "timestamp" }
935
+ update_typemap_for_default_timezone
835
936
  end
836
937
 
837
938
  def construct_coder(row, coder_class)
@@ -839,6 +940,14 @@ module ActiveRecord
839
940
  coder_class.new(oid: row["oid"].to_i, name: row["typname"])
840
941
  end
841
942
 
943
+ class MoneyDecoder < PG::SimpleDecoder # :nodoc:
944
+ TYPE = OID::Money.new
945
+
946
+ def decode(value, tuple = nil, field = nil)
947
+ TYPE.deserialize(value)
948
+ end
949
+ end
950
+
842
951
  ActiveRecord::Type.add_modifier({ array: true }, OID::Array, adapter: :postgresql)
843
952
  ActiveRecord::Type.add_modifier({ range: true }, OID::Range, adapter: :postgresql)
844
953
  ActiveRecord::Type.register(:bit, OID::Bit, adapter: :postgresql)
@@ -851,6 +960,7 @@ module ActiveRecord
851
960
  ActiveRecord::Type.register(:enum, OID::Enum, adapter: :postgresql)
852
961
  ActiveRecord::Type.register(:hstore, OID::Hstore, adapter: :postgresql)
853
962
  ActiveRecord::Type.register(:inet, OID::Inet, adapter: :postgresql)
963
+ ActiveRecord::Type.register(:interval, OID::Interval, adapter: :postgresql)
854
964
  ActiveRecord::Type.register(:jsonb, OID::Jsonb, adapter: :postgresql)
855
965
  ActiveRecord::Type.register(:money, OID::Money, adapter: :postgresql)
856
966
  ActiveRecord::Type.register(:point, OID::Point, adapter: :postgresql)