activerecord 5.2.8.1 → 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 (294) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +938 -573
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +5 -3
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record/advisory_lock_base.rb +18 -0
  7. data/lib/active_record/aggregations.rb +4 -3
  8. data/lib/active_record/association_relation.rb +10 -8
  9. data/lib/active_record/associations/alias_tracker.rb +0 -1
  10. data/lib/active_record/associations/association.rb +55 -19
  11. data/lib/active_record/associations/association_scope.rb +11 -7
  12. data/lib/active_record/associations/belongs_to_association.rb +36 -42
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
  14. data/lib/active_record/associations/builder/association.rb +14 -18
  15. data/lib/active_record/associations/builder/belongs_to.rb +19 -52
  16. data/lib/active_record/associations/builder/collection_association.rb +3 -13
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -40
  18. data/lib/active_record/associations/builder/has_many.rb +2 -0
  19. data/lib/active_record/associations/builder/has_one.rb +35 -1
  20. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  21. data/lib/active_record/associations/collection_association.rb +19 -23
  22. data/lib/active_record/associations/collection_proxy.rb +14 -17
  23. data/lib/active_record/associations/foreign_association.rb +7 -0
  24. data/lib/active_record/associations/has_many_association.rb +2 -11
  25. data/lib/active_record/associations/has_many_through_association.rb +14 -14
  26. data/lib/active_record/associations/has_one_association.rb +28 -30
  27. data/lib/active_record/associations/has_one_through_association.rb +5 -5
  28. data/lib/active_record/associations/join_dependency/join_association.rb +16 -10
  29. data/lib/active_record/associations/join_dependency/join_part.rb +4 -4
  30. data/lib/active_record/associations/join_dependency.rb +47 -30
  31. data/lib/active_record/associations/preloader/association.rb +61 -41
  32. data/lib/active_record/associations/preloader/through_association.rb +48 -39
  33. data/lib/active_record/associations/preloader.rb +44 -33
  34. data/lib/active_record/associations/singular_association.rb +2 -16
  35. data/lib/active_record/associations/through_association.rb +1 -1
  36. data/lib/active_record/associations.rb +21 -16
  37. data/lib/active_record/attribute_assignment.rb +7 -11
  38. data/lib/active_record/attribute_decorators.rb +0 -2
  39. data/lib/active_record/attribute_methods/before_type_cast.rb +4 -2
  40. data/lib/active_record/attribute_methods/dirty.rb +111 -40
  41. data/lib/active_record/attribute_methods/primary_key.rb +15 -24
  42. data/lib/active_record/attribute_methods/query.rb +2 -3
  43. data/lib/active_record/attribute_methods/read.rb +15 -54
  44. data/lib/active_record/attribute_methods/serialization.rb +1 -2
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -3
  46. data/lib/active_record/attribute_methods/write.rb +17 -25
  47. data/lib/active_record/attribute_methods.rb +28 -100
  48. data/lib/active_record/attributes.rb +13 -1
  49. data/lib/active_record/autosave_association.rb +12 -14
  50. data/lib/active_record/base.rb +2 -3
  51. data/lib/active_record/callbacks.rb +6 -21
  52. data/lib/active_record/coders/yaml_column.rb +15 -6
  53. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +109 -18
  54. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -4
  55. data/lib/active_record/connection_adapters/abstract/database_statements.rb +102 -124
  56. data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -9
  57. data/lib/active_record/connection_adapters/abstract/quoting.rb +77 -17
  58. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +20 -14
  59. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +105 -72
  60. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -3
  61. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +175 -79
  62. data/lib/active_record/connection_adapters/abstract/transaction.rb +96 -57
  63. data/lib/active_record/connection_adapters/abstract_adapter.rb +197 -43
  64. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +149 -217
  65. data/lib/active_record/connection_adapters/column.rb +17 -13
  66. data/lib/active_record/connection_adapters/connection_specification.rb +54 -45
  67. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +6 -10
  68. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  69. data/lib/active_record/connection_adapters/mysql/database_statements.rb +70 -14
  70. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +0 -1
  71. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
  72. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +4 -6
  73. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +40 -32
  74. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +14 -6
  75. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +139 -19
  76. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +6 -10
  77. data/lib/active_record/connection_adapters/mysql2_adapter.rb +26 -10
  78. data/lib/active_record/connection_adapters/postgresql/column.rb +17 -31
  79. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +26 -1
  80. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  81. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  82. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +8 -0
  83. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  84. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
  89. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
  91. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +5 -3
  92. data/lib/active_record/connection_adapters/postgresql/quoting.rb +44 -7
  93. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
  94. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -3
  95. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
  96. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  97. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +63 -75
  98. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +24 -27
  99. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  100. data/lib/active_record/connection_adapters/postgresql_adapter.rb +168 -75
  101. data/lib/active_record/connection_adapters/schema_cache.rb +37 -14
  102. data/lib/active_record/connection_adapters/sql_type_metadata.rb +11 -8
  103. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
  104. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
  105. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -12
  106. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +137 -147
  107. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  108. data/lib/active_record/connection_handling.rb +139 -26
  109. data/lib/active_record/core.rb +108 -67
  110. data/lib/active_record/counter_cache.rb +8 -30
  111. data/lib/active_record/database_configurations/database_config.rb +37 -0
  112. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  113. data/lib/active_record/database_configurations/url_config.rb +78 -0
  114. data/lib/active_record/database_configurations.rb +233 -0
  115. data/lib/active_record/dynamic_matchers.rb +3 -4
  116. data/lib/active_record/enum.rb +44 -7
  117. data/lib/active_record/errors.rb +15 -7
  118. data/lib/active_record/explain.rb +1 -2
  119. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  120. data/lib/active_record/fixture_set/render_context.rb +17 -0
  121. data/lib/active_record/fixture_set/table_row.rb +152 -0
  122. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  123. data/lib/active_record/fixtures.rb +144 -474
  124. data/lib/active_record/gem_version.rb +3 -3
  125. data/lib/active_record/inheritance.rb +13 -6
  126. data/lib/active_record/insert_all.rb +179 -0
  127. data/lib/active_record/integration.rb +68 -16
  128. data/lib/active_record/internal_metadata.rb +11 -3
  129. data/lib/active_record/locking/optimistic.rb +14 -7
  130. data/lib/active_record/locking/pessimistic.rb +3 -3
  131. data/lib/active_record/log_subscriber.rb +8 -27
  132. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  133. data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
  134. data/lib/active_record/middleware/database_selector.rb +74 -0
  135. data/lib/active_record/migration/command_recorder.rb +54 -22
  136. data/lib/active_record/migration/compatibility.rb +79 -52
  137. data/lib/active_record/migration/join_table.rb +0 -1
  138. data/lib/active_record/migration.rb +104 -85
  139. data/lib/active_record/model_schema.rb +62 -11
  140. data/lib/active_record/nested_attributes.rb +2 -4
  141. data/lib/active_record/no_touching.rb +9 -2
  142. data/lib/active_record/null_relation.rb +0 -1
  143. data/lib/active_record/persistence.rb +232 -29
  144. data/lib/active_record/query_cache.rb +11 -4
  145. data/lib/active_record/querying.rb +33 -21
  146. data/lib/active_record/railtie.rb +80 -61
  147. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  148. data/lib/active_record/railties/controller_runtime.rb +30 -35
  149. data/lib/active_record/railties/databases.rake +199 -46
  150. data/lib/active_record/reflection.rb +51 -51
  151. data/lib/active_record/relation/batches.rb +13 -11
  152. data/lib/active_record/relation/calculations.rb +55 -49
  153. data/lib/active_record/relation/delegation.rb +35 -50
  154. data/lib/active_record/relation/finder_methods.rb +23 -28
  155. data/lib/active_record/relation/from_clause.rb +4 -0
  156. data/lib/active_record/relation/merger.rb +12 -17
  157. data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
  158. data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
  159. data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
  160. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  161. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
  162. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  163. data/lib/active_record/relation/predicate_builder.rb +5 -11
  164. data/lib/active_record/relation/query_attribute.rb +13 -8
  165. data/lib/active_record/relation/query_methods.rb +234 -69
  166. data/lib/active_record/relation/spawn_methods.rb +1 -2
  167. data/lib/active_record/relation/where_clause.rb +14 -11
  168. data/lib/active_record/relation/where_clause_factory.rb +1 -2
  169. data/lib/active_record/relation.rb +326 -81
  170. data/lib/active_record/result.rb +30 -12
  171. data/lib/active_record/sanitization.rb +32 -40
  172. data/lib/active_record/schema.rb +2 -11
  173. data/lib/active_record/schema_dumper.rb +22 -7
  174. data/lib/active_record/schema_migration.rb +6 -2
  175. data/lib/active_record/scoping/default.rb +4 -6
  176. data/lib/active_record/scoping/named.rb +25 -16
  177. data/lib/active_record/scoping.rb +8 -9
  178. data/lib/active_record/statement_cache.rb +30 -3
  179. data/lib/active_record/store.rb +87 -8
  180. data/lib/active_record/suppressor.rb +2 -2
  181. data/lib/active_record/table_metadata.rb +23 -15
  182. data/lib/active_record/tasks/database_tasks.rb +194 -25
  183. data/lib/active_record/tasks/mysql_database_tasks.rb +5 -6
  184. data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -8
  185. data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -9
  186. data/lib/active_record/test_databases.rb +23 -0
  187. data/lib/active_record/test_fixtures.rb +243 -0
  188. data/lib/active_record/timestamp.rb +39 -26
  189. data/lib/active_record/touch_later.rb +5 -4
  190. data/lib/active_record/transactions.rb +64 -73
  191. data/lib/active_record/translation.rb +1 -1
  192. data/lib/active_record/type/adapter_specific_registry.rb +3 -13
  193. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  194. data/lib/active_record/type/serialized.rb +0 -1
  195. data/lib/active_record/type/time.rb +10 -0
  196. data/lib/active_record/type/type_map.rb +0 -1
  197. data/lib/active_record/type/unsigned_integer.rb +0 -1
  198. data/lib/active_record/type.rb +3 -5
  199. data/lib/active_record/type_caster/connection.rb +15 -14
  200. data/lib/active_record/type_caster/map.rb +1 -4
  201. data/lib/active_record/validations/associated.rb +0 -1
  202. data/lib/active_record/validations/uniqueness.rb +15 -27
  203. data/lib/active_record/validations.rb +3 -3
  204. data/lib/active_record.rb +10 -2
  205. data/lib/arel/alias_predication.rb +9 -0
  206. data/lib/arel/attributes/attribute.rb +37 -0
  207. data/lib/arel/attributes.rb +22 -0
  208. data/lib/arel/collectors/bind.rb +24 -0
  209. data/lib/arel/collectors/composite.rb +31 -0
  210. data/lib/arel/collectors/plain_string.rb +20 -0
  211. data/lib/arel/collectors/sql_string.rb +20 -0
  212. data/lib/arel/collectors/substitute_binds.rb +28 -0
  213. data/lib/arel/crud.rb +42 -0
  214. data/lib/arel/delete_manager.rb +18 -0
  215. data/lib/arel/errors.rb +9 -0
  216. data/lib/arel/expressions.rb +29 -0
  217. data/lib/arel/factory_methods.rb +49 -0
  218. data/lib/arel/insert_manager.rb +49 -0
  219. data/lib/arel/math.rb +45 -0
  220. data/lib/arel/nodes/and.rb +32 -0
  221. data/lib/arel/nodes/ascending.rb +23 -0
  222. data/lib/arel/nodes/binary.rb +52 -0
  223. data/lib/arel/nodes/bind_param.rb +36 -0
  224. data/lib/arel/nodes/case.rb +55 -0
  225. data/lib/arel/nodes/casted.rb +50 -0
  226. data/lib/arel/nodes/comment.rb +29 -0
  227. data/lib/arel/nodes/count.rb +12 -0
  228. data/lib/arel/nodes/delete_statement.rb +45 -0
  229. data/lib/arel/nodes/descending.rb +23 -0
  230. data/lib/arel/nodes/equality.rb +18 -0
  231. data/lib/arel/nodes/extract.rb +24 -0
  232. data/lib/arel/nodes/false.rb +16 -0
  233. data/lib/arel/nodes/full_outer_join.rb +8 -0
  234. data/lib/arel/nodes/function.rb +44 -0
  235. data/lib/arel/nodes/grouping.rb +8 -0
  236. data/lib/arel/nodes/in.rb +8 -0
  237. data/lib/arel/nodes/infix_operation.rb +80 -0
  238. data/lib/arel/nodes/inner_join.rb +8 -0
  239. data/lib/arel/nodes/insert_statement.rb +37 -0
  240. data/lib/arel/nodes/join_source.rb +20 -0
  241. data/lib/arel/nodes/matches.rb +18 -0
  242. data/lib/arel/nodes/named_function.rb +23 -0
  243. data/lib/arel/nodes/node.rb +50 -0
  244. data/lib/arel/nodes/node_expression.rb +13 -0
  245. data/lib/arel/nodes/outer_join.rb +8 -0
  246. data/lib/arel/nodes/over.rb +15 -0
  247. data/lib/arel/nodes/regexp.rb +16 -0
  248. data/lib/arel/nodes/right_outer_join.rb +8 -0
  249. data/lib/arel/nodes/select_core.rb +67 -0
  250. data/lib/arel/nodes/select_statement.rb +41 -0
  251. data/lib/arel/nodes/sql_literal.rb +16 -0
  252. data/lib/arel/nodes/string_join.rb +11 -0
  253. data/lib/arel/nodes/table_alias.rb +27 -0
  254. data/lib/arel/nodes/terminal.rb +16 -0
  255. data/lib/arel/nodes/true.rb +16 -0
  256. data/lib/arel/nodes/unary.rb +45 -0
  257. data/lib/arel/nodes/unary_operation.rb +20 -0
  258. data/lib/arel/nodes/unqualified_column.rb +22 -0
  259. data/lib/arel/nodes/update_statement.rb +41 -0
  260. data/lib/arel/nodes/values_list.rb +9 -0
  261. data/lib/arel/nodes/window.rb +126 -0
  262. data/lib/arel/nodes/with.rb +11 -0
  263. data/lib/arel/nodes.rb +68 -0
  264. data/lib/arel/order_predications.rb +13 -0
  265. data/lib/arel/predications.rb +256 -0
  266. data/lib/arel/select_manager.rb +271 -0
  267. data/lib/arel/table.rb +110 -0
  268. data/lib/arel/tree_manager.rb +72 -0
  269. data/lib/arel/update_manager.rb +34 -0
  270. data/lib/arel/visitors/depth_first.rb +203 -0
  271. data/lib/arel/visitors/dot.rb +296 -0
  272. data/lib/arel/visitors/ibm_db.rb +34 -0
  273. data/lib/arel/visitors/informix.rb +62 -0
  274. data/lib/arel/visitors/mssql.rb +156 -0
  275. data/lib/arel/visitors/mysql.rb +83 -0
  276. data/lib/arel/visitors/oracle.rb +158 -0
  277. data/lib/arel/visitors/oracle12.rb +65 -0
  278. data/lib/arel/visitors/postgresql.rb +109 -0
  279. data/lib/arel/visitors/sqlite.rb +38 -0
  280. data/lib/arel/visitors/to_sql.rb +888 -0
  281. data/lib/arel/visitors/visitor.rb +45 -0
  282. data/lib/arel/visitors/where_sql.rb +22 -0
  283. data/lib/arel/visitors.rb +20 -0
  284. data/lib/arel/window_predications.rb +9 -0
  285. data/lib/arel.rb +62 -0
  286. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  287. data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
  288. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +1 -1
  289. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -2
  290. data/lib/rails/generators/active_record/migration.rb +14 -2
  291. data/lib/rails/generators/active_record/model/model_generator.rb +1 -1
  292. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  293. metadata +113 -26
  294. data/lib/active_record/collection_cache_key.rb +0 -53
@@ -58,25 +58,43 @@ module ActiveRecord
58
58
  end
59
59
 
60
60
  private
61
-
62
61
  def type_cast_single(value)
63
62
  infinity?(value) ? value : @subtype.deserialize(value)
64
63
  end
65
64
 
66
65
  def type_cast_single_for_database(value)
67
- infinity?(value) ? value : @subtype.serialize(value)
66
+ infinity?(value) ? value : @subtype.serialize(@subtype.cast(value))
68
67
  end
69
68
 
70
69
  def extract_bounds(value)
71
- from, to = value[1..-2].split(",")
70
+ from, to = value[1..-2].split(",", 2)
72
71
  {
73
- from: (value[1] == "," || from == "-infinity") ? infinity(negative: true) : from,
74
- to: (value[-2] == "," || to == "infinity") ? infinity : to,
75
- exclude_start: (value[0] == "("),
76
- exclude_end: (value[-1] == ")")
72
+ from: (from == "" || from == "-infinity") ? infinity(negative: true) : unquote(from),
73
+ to: (to == "" || to == "infinity") ? infinity : unquote(to),
74
+ exclude_start: value.start_with?("("),
75
+ exclude_end: value.end_with?(")")
77
76
  }
78
77
  end
79
78
 
79
+ # When formatting the bound values of range types, PostgreSQL quotes
80
+ # the bound value using double-quotes in certain conditions. Within
81
+ # a double-quoted string, literal " and \ characters are themselves
82
+ # escaped. In input, PostgreSQL accepts multiple escape styles for "
83
+ # (either \" or "") but in output always uses "".
84
+ # See:
85
+ # * https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-IO
86
+ # * https://www.postgresql.org/docs/current/rowtypes.html#ROWTYPES-IO-SYNTAX
87
+ def unquote(value)
88
+ if value.start_with?('"') && value.end_with?('"')
89
+ unquoted_value = value[1..-2]
90
+ unquoted_value.gsub!('""', '"')
91
+ unquoted_value.gsub!('\\\\', '\\')
92
+ unquoted_value
93
+ else
94
+ value
95
+ end
96
+ end
97
+
80
98
  def infinity(negative: false)
81
99
  if subtype.respond_to?(:infinity)
82
100
  subtype.infinity(negative: negative)
@@ -9,7 +9,7 @@ module ActiveRecord
9
9
 
10
10
  def initialize(type, **options)
11
11
  @type = type
12
- super(options)
12
+ super(**options)
13
13
  end
14
14
  end
15
15
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/core_ext/array/extract"
4
+
3
5
  module ActiveRecord
4
6
  module ConnectionAdapters
5
7
  module PostgreSQL
@@ -16,12 +18,12 @@ module ActiveRecord
16
18
 
17
19
  def run(records)
18
20
  nodes = records.reject { |row| @store.key? row["oid"].to_i }
19
- mapped, nodes = nodes.partition { |row| @store.key? row["typname"] }
20
- ranges, nodes = nodes.partition { |row| row["typtype"] == "r".freeze }
21
- enums, nodes = nodes.partition { |row| row["typtype"] == "e".freeze }
22
- domains, nodes = nodes.partition { |row| row["typtype"] == "d".freeze }
23
- arrays, nodes = nodes.partition { |row| row["typinput"] == "array_in".freeze }
24
- composites, nodes = nodes.partition { |row| row["typelem"].to_i != 0 }
21
+ mapped = nodes.extract! { |row| @store.key? row["typname"] }
22
+ ranges = nodes.extract! { |row| row["typtype"] == "r" }
23
+ enums = nodes.extract! { |row| row["typtype"] == "e" }
24
+ domains = nodes.extract! { |row| row["typtype"] == "d" }
25
+ arrays = nodes.extract! { |row| row["typinput"] == "array_in" }
26
+ composites = nodes.extract! { |row| row["typelem"].to_i != 0 }
25
27
 
26
28
  mapped.each { |row| register_mapped_type(row) }
27
29
  enums.each { |row| register_enum_type(row) }
@@ -34,7 +36,7 @@ module ActiveRecord
34
36
  def query_conditions_for_initial_load
35
37
  known_type_names = @store.keys.map { |n| "'#{n}'" }
36
38
  known_type_types = %w('r' 'e' 'd')
37
- <<-SQL % [known_type_names.join(", "), known_type_types.join(", ")]
39
+ <<~SQL % [known_type_names.join(", "), known_type_types.join(", ")]
38
40
  WHERE
39
41
  t.typname IN (%s)
40
42
  OR t.typtype IN (%s)
@@ -13,9 +13,11 @@ module ActiveRecord
13
13
  :uuid
14
14
  end
15
15
 
16
- def cast(value)
17
- value.to_s[ACCEPTABLE_UUID, 0]
18
- end
16
+ private
17
+ def cast_value(value)
18
+ casted = value.to_s
19
+ casted if casted.match?(ACCEPTABLE_UUID)
20
+ end
19
21
  end
20
22
  end
21
23
  end
@@ -30,7 +30,7 @@ module ActiveRecord
30
30
  # - "schema.name".table_name
31
31
  # - "schema.name"."table.name"
32
32
  def quote_table_name(name) # :nodoc:
33
- @quoted_table_names[name] ||= Utils.extract_schema_qualified_name(name.to_s).quoted.freeze
33
+ self.class.quoted_table_names[name] ||= Utils.extract_schema_qualified_name(name.to_s).quoted.freeze
34
34
  end
35
35
 
36
36
  # Quotes schema names for use in SQL queries.
@@ -44,7 +44,7 @@ module ActiveRecord
44
44
 
45
45
  # Quotes column names for use in SQL queries.
46
46
  def quote_column_name(name) # :nodoc:
47
- @quoted_column_names[name] ||= PG::Connection.quote_ident(super).freeze
47
+ self.class.quoted_column_names[name] ||= PG::Connection.quote_ident(super).freeze
48
48
  end
49
49
 
50
50
  # Quote date/time values for use in SQL input.
@@ -78,6 +78,43 @@ module ActiveRecord
78
78
  type_map.lookup(column.oid, column.fmod, column.sql_type)
79
79
  end
80
80
 
81
+ def column_name_matcher
82
+ COLUMN_NAME
83
+ end
84
+
85
+ def column_name_with_order_matcher
86
+ COLUMN_NAME_WITH_ORDER
87
+ end
88
+
89
+ COLUMN_NAME = /
90
+ \A
91
+ (
92
+ (?:
93
+ # "table_name"."column_name"::type_name | function(one or no argument)::type_name
94
+ ((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")(?:::\w+)?) | \w+\((?:|\g<2>)\)(?:::\w+)?
95
+ )
96
+ (?:\s+AS\s+(?:\w+|"\w+"))?
97
+ )
98
+ (?:\s*,\s*\g<1>)*
99
+ \z
100
+ /ix
101
+
102
+ COLUMN_NAME_WITH_ORDER = /
103
+ \A
104
+ (
105
+ (?:
106
+ # "table_name"."column_name"::type_name | function(one or no argument)::type_name
107
+ ((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")(?:::\w+)?) | \w+\((?:|\g<2>)\)(?:::\w+)?
108
+ )
109
+ (?:\s+ASC|\s+DESC)?
110
+ (?:\s+NULLS\s+(?:FIRST|LAST))?
111
+ )
112
+ (?:\s*,\s*\g<1>)*
113
+ \z
114
+ /ix
115
+
116
+ private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
117
+
81
118
  private
82
119
  def lookup_cast_type(sql_type)
83
120
  super(query_value("SELECT #{quote(sql_type)}::regtype::oid", "SCHEMA").to_i)
@@ -93,11 +130,11 @@ module ActiveRecord
93
130
  elsif value.hex?
94
131
  "X'#{value}'"
95
132
  end
96
- when Float
97
- if value.infinite? || value.nan?
98
- "'#{value}'"
99
- else
133
+ when Numeric
134
+ if value.finite?
100
135
  super
136
+ else
137
+ "'#{value}'"
101
138
  end
102
139
  when OID::Array::Data
103
140
  _quote(encode_array(value))
@@ -138,7 +175,7 @@ module ActiveRecord
138
175
  end
139
176
 
140
177
  def encode_range(range)
141
- "[#{type_cast_range_value(range.first)},#{type_cast_range_value(range.last)}#{range.exclude_end? ? ')' : ']'}"
178
+ "[#{type_cast_range_value(range.begin)},#{type_cast_range_value(range.end)}#{range.exclude_end? ? ')' : ']'}"
142
179
  end
143
180
 
144
181
  def determine_encoding_of_strings_in_array(value)
@@ -26,7 +26,7 @@ Rails needs superuser privileges to disable referential integrity.
26
26
 
27
27
  cause: #{original_exception.try(:message)}
28
28
 
29
- WARNING
29
+ WARNING
30
30
  raise e
31
31
  end
32
32
 
@@ -19,10 +19,10 @@ module ActiveRecord
19
19
 
20
20
  def visit_ChangeColumnDefinition(o)
21
21
  column = o.column
22
- column.sql_type = type_to_sql(column.type, column.options)
22
+ column.sql_type = type_to_sql(column.type, **column.options)
23
23
  quoted_column_name = quote_column_name(o.name)
24
24
 
25
- change_column_sql = "ALTER COLUMN #{quoted_column_name} TYPE #{column.sql_type}".dup
25
+ change_column_sql = +"ALTER COLUMN #{quoted_column_name} TYPE #{column.sql_type}"
26
26
 
27
27
  options = column_options(column)
28
28
 
@@ -33,7 +33,7 @@ module ActiveRecord
33
33
  if options[:using]
34
34
  change_column_sql << " USING #{options[:using]}"
35
35
  elsif options[:cast_as]
36
- cast_as_type = type_to_sql(options[:cast_as], options)
36
+ cast_as_type = type_to_sql(options[:cast_as], **options)
37
37
  change_column_sql << " USING CAST(#{quoted_column_name} AS #{cast_as_type})"
38
38
  end
39
39
 
@@ -59,6 +59,17 @@ module ActiveRecord
59
59
  end
60
60
  super
61
61
  end
62
+
63
+ # Returns any SQL string to go between CREATE and TABLE. May be nil.
64
+ def table_modifier_in_create(o)
65
+ # A table cannot be both TEMPORARY and UNLOGGED, since all TEMPORARY
66
+ # tables are already UNLOGGED.
67
+ if o.temporary
68
+ " TEMPORARY"
69
+ elsif o.unlogged
70
+ " UNLOGGED"
71
+ end
72
+ end
62
73
  end
63
74
  end
64
75
  end
@@ -4,6 +4,8 @@ module ActiveRecord
4
4
  module ConnectionAdapters
5
5
  module PostgreSQL
6
6
  module ColumnMethods
7
+ extend ActiveSupport::Concern
8
+
7
9
  # Defines the primary key field.
8
10
  # Use of the native PostgreSQL UUID type is supported, and can be used
9
11
  # by defining your tables as such:
@@ -13,10 +15,10 @@ module ActiveRecord
13
15
  # t.timestamps
14
16
  # end
15
17
  #
16
- # By default, this will use the +gen_random_uuid()+ function from the
18
+ # By default, this will use the <tt>gen_random_uuid()</tt> function from the
17
19
  # +pgcrypto+ extension. As that extension is only available in
18
20
  # PostgreSQL 9.4+, for earlier versions an explicit default can be set
19
- # to use +uuid_generate_v4()+ from the +uuid-ossp+ extension instead:
21
+ # to use <tt>uuid_generate_v4()</tt> from the +uuid-ossp+ extension instead:
20
22
  #
21
23
  # create_table :stuffs, id: false do |t|
22
24
  # t.primary_key :id, :uuid, default: "uuid_generate_v4()"
@@ -51,130 +53,144 @@ module ActiveRecord
51
53
  super
52
54
  end
53
55
 
54
- def bigserial(*args, **options)
55
- args.each { |name| column(name, :bigserial, options) }
56
- end
56
+ ##
57
+ # :method: bigserial
58
+ # :call-seq: bigserial(*names, **options)
57
59
 
58
- def bit(*args, **options)
59
- args.each { |name| column(name, :bit, options) }
60
- end
60
+ ##
61
+ # :method: bit
62
+ # :call-seq: bit(*names, **options)
61
63
 
62
- def bit_varying(*args, **options)
63
- args.each { |name| column(name, :bit_varying, options) }
64
- end
64
+ ##
65
+ # :method: bit_varying
66
+ # :call-seq: bit_varying(*names, **options)
65
67
 
66
- def cidr(*args, **options)
67
- args.each { |name| column(name, :cidr, options) }
68
- end
68
+ ##
69
+ # :method: cidr
70
+ # :call-seq: cidr(*names, **options)
69
71
 
70
- def citext(*args, **options)
71
- args.each { |name| column(name, :citext, options) }
72
- end
72
+ ##
73
+ # :method: citext
74
+ # :call-seq: citext(*names, **options)
73
75
 
74
- def daterange(*args, **options)
75
- args.each { |name| column(name, :daterange, options) }
76
- end
76
+ ##
77
+ # :method: daterange
78
+ # :call-seq: daterange(*names, **options)
77
79
 
78
- def hstore(*args, **options)
79
- args.each { |name| column(name, :hstore, options) }
80
- end
80
+ ##
81
+ # :method: hstore
82
+ # :call-seq: hstore(*names, **options)
81
83
 
82
- def inet(*args, **options)
83
- args.each { |name| column(name, :inet, options) }
84
- end
84
+ ##
85
+ # :method: inet
86
+ # :call-seq: inet(*names, **options)
85
87
 
86
- def interval(*args, **options)
87
- args.each { |name| column(name, :interval, options) }
88
- end
88
+ ##
89
+ # :method: interval
90
+ # :call-seq: interval(*names, **options)
89
91
 
90
- def int4range(*args, **options)
91
- args.each { |name| column(name, :int4range, options) }
92
- end
92
+ ##
93
+ # :method: int4range
94
+ # :call-seq: int4range(*names, **options)
93
95
 
94
- def int8range(*args, **options)
95
- args.each { |name| column(name, :int8range, options) }
96
- end
96
+ ##
97
+ # :method: int8range
98
+ # :call-seq: int8range(*names, **options)
97
99
 
98
- def jsonb(*args, **options)
99
- args.each { |name| column(name, :jsonb, options) }
100
- end
100
+ ##
101
+ # :method: jsonb
102
+ # :call-seq: jsonb(*names, **options)
101
103
 
102
- def ltree(*args, **options)
103
- args.each { |name| column(name, :ltree, options) }
104
- end
104
+ ##
105
+ # :method: ltree
106
+ # :call-seq: ltree(*names, **options)
105
107
 
106
- def macaddr(*args, **options)
107
- args.each { |name| column(name, :macaddr, options) }
108
- end
108
+ ##
109
+ # :method: macaddr
110
+ # :call-seq: macaddr(*names, **options)
109
111
 
110
- def money(*args, **options)
111
- args.each { |name| column(name, :money, options) }
112
- end
112
+ ##
113
+ # :method: money
114
+ # :call-seq: money(*names, **options)
113
115
 
114
- def numrange(*args, **options)
115
- args.each { |name| column(name, :numrange, options) }
116
- end
116
+ ##
117
+ # :method: numrange
118
+ # :call-seq: numrange(*names, **options)
117
119
 
118
- def oid(*args, **options)
119
- args.each { |name| column(name, :oid, options) }
120
- end
120
+ ##
121
+ # :method: oid
122
+ # :call-seq: oid(*names, **options)
121
123
 
122
- def point(*args, **options)
123
- args.each { |name| column(name, :point, options) }
124
- end
124
+ ##
125
+ # :method: point
126
+ # :call-seq: point(*names, **options)
125
127
 
126
- def line(*args, **options)
127
- args.each { |name| column(name, :line, options) }
128
- end
128
+ ##
129
+ # :method: line
130
+ # :call-seq: line(*names, **options)
129
131
 
130
- def lseg(*args, **options)
131
- args.each { |name| column(name, :lseg, options) }
132
- end
132
+ ##
133
+ # :method: lseg
134
+ # :call-seq: lseg(*names, **options)
133
135
 
134
- def box(*args, **options)
135
- args.each { |name| column(name, :box, options) }
136
- end
136
+ ##
137
+ # :method: box
138
+ # :call-seq: box(*names, **options)
137
139
 
138
- def path(*args, **options)
139
- args.each { |name| column(name, :path, options) }
140
- end
140
+ ##
141
+ # :method: path
142
+ # :call-seq: path(*names, **options)
141
143
 
142
- def polygon(*args, **options)
143
- args.each { |name| column(name, :polygon, options) }
144
- end
144
+ ##
145
+ # :method: polygon
146
+ # :call-seq: polygon(*names, **options)
145
147
 
146
- def circle(*args, **options)
147
- args.each { |name| column(name, :circle, options) }
148
- end
148
+ ##
149
+ # :method: circle
150
+ # :call-seq: circle(*names, **options)
149
151
 
150
- def serial(*args, **options)
151
- args.each { |name| column(name, :serial, options) }
152
- end
152
+ ##
153
+ # :method: serial
154
+ # :call-seq: serial(*names, **options)
153
155
 
154
- def tsrange(*args, **options)
155
- args.each { |name| column(name, :tsrange, options) }
156
- end
156
+ ##
157
+ # :method: tsrange
158
+ # :call-seq: tsrange(*names, **options)
157
159
 
158
- def tstzrange(*args, **options)
159
- args.each { |name| column(name, :tstzrange, options) }
160
- end
160
+ ##
161
+ # :method: tstzrange
162
+ # :call-seq: tstzrange(*names, **options)
161
163
 
162
- def tsvector(*args, **options)
163
- args.each { |name| column(name, :tsvector, options) }
164
- end
164
+ ##
165
+ # :method: tsvector
166
+ # :call-seq: tsvector(*names, **options)
165
167
 
166
- def uuid(*args, **options)
167
- args.each { |name| column(name, :uuid, options) }
168
- end
168
+ ##
169
+ # :method: uuid
170
+ # :call-seq: uuid(*names, **options)
171
+
172
+ ##
173
+ # :method: xml
174
+ # :call-seq: xml(*names, **options)
169
175
 
170
- def xml(*args, **options)
171
- args.each { |name| column(name, :xml, options) }
176
+ included do
177
+ define_column_methods :bigserial, :bit, :bit_varying, :cidr, :citext, :daterange,
178
+ :hstore, :inet, :interval, :int4range, :int8range, :jsonb, :ltree, :macaddr,
179
+ :money, :numrange, :oid, :point, :line, :lseg, :box, :path, :polygon, :circle,
180
+ :serial, :tsrange, :tstzrange, :tsvector, :uuid, :xml
172
181
  end
173
182
  end
174
183
 
175
184
  class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
176
185
  include ColumnMethods
177
186
 
187
+ attr_reader :unlogged
188
+
189
+ def initialize(*, **)
190
+ super
191
+ @unlogged = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.create_unlogged_tables
192
+ end
193
+
178
194
  private
179
195
  def integer_like_primary_key_type(type, options)
180
196
  if type == :bigint || options[:limit] == 8
@@ -5,7 +5,6 @@ module ActiveRecord
5
5
  module PostgreSQL
6
6
  class SchemaDumper < ConnectionAdapters::SchemaDumper # :nodoc:
7
7
  private
8
-
9
8
  def extensions(stream)
10
9
  extensions = @connection.extensions
11
10
  if extensions.any?