activerecord 5.2.7 → 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 +987 -584
  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 +23 -2
  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 +117 -66
  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 +4 -4
  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 -43
  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 +116 -29
  294. data/lib/active_record/collection_cache_key.rb +0 -53
@@ -22,8 +22,8 @@ module ActiveRecord
22
22
  def create_database(name, options = {})
23
23
  options = { encoding: "utf8" }.merge!(options.symbolize_keys)
24
24
 
25
- option_string = options.inject("") do |memo, (key, value)|
26
- memo += case key
25
+ option_string = options.each_with_object(+"") do |(key, value), memo|
26
+ memo << case key
27
27
  when :owner
28
28
  " OWNER = \"#{value}\""
29
29
  when :template
@@ -68,13 +68,13 @@ module ActiveRecord
68
68
  table = quoted_scope(table_name)
69
69
  index = quoted_scope(index_name)
70
70
 
71
- query_value(<<-SQL, "SCHEMA").to_i > 0
71
+ query_value(<<~SQL, "SCHEMA").to_i > 0
72
72
  SELECT COUNT(*)
73
73
  FROM pg_class t
74
74
  INNER JOIN pg_index d ON t.oid = d.indrelid
75
75
  INNER JOIN pg_class i ON d.indexrelid = i.oid
76
76
  LEFT JOIN pg_namespace n ON n.oid = i.relnamespace
77
- WHERE i.relkind = 'i'
77
+ WHERE i.relkind IN ('i', 'I')
78
78
  AND i.relname = #{index[:name]}
79
79
  AND t.relname = #{table[:name]}
80
80
  AND n.nspname = #{index[:schema]}
@@ -85,14 +85,14 @@ module ActiveRecord
85
85
  def indexes(table_name) # :nodoc:
86
86
  scope = quoted_scope(table_name)
87
87
 
88
- result = query(<<-SQL, "SCHEMA")
88
+ result = query(<<~SQL, "SCHEMA")
89
89
  SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid,
90
90
  pg_catalog.obj_description(i.oid, 'pg_class') AS comment
91
91
  FROM pg_class t
92
92
  INNER JOIN pg_index d ON t.oid = d.indrelid
93
93
  INNER JOIN pg_class i ON d.indexrelid = i.oid
94
94
  LEFT JOIN pg_namespace n ON n.oid = i.relnamespace
95
- WHERE i.relkind = 'i'
95
+ WHERE i.relkind IN ('i', 'I')
96
96
  AND d.indisprimary = 'f'
97
97
  AND t.relname = #{scope[:name]}
98
98
  AND n.nspname = #{scope[:schema]}
@@ -115,7 +115,7 @@ module ActiveRecord
115
115
  if indkey.include?(0)
116
116
  columns = expressions
117
117
  else
118
- columns = Hash[query(<<-SQL.strip_heredoc, "SCHEMA")].values_at(*indkey).compact
118
+ columns = Hash[query(<<~SQL, "SCHEMA")].values_at(*indkey).compact
119
119
  SELECT a.attnum, a.attname
120
120
  FROM pg_attribute a
121
121
  WHERE a.attrelid = #{oid}
@@ -158,7 +158,7 @@ module ActiveRecord
158
158
  def table_comment(table_name) # :nodoc:
159
159
  scope = quoted_scope(table_name, type: "BASE TABLE")
160
160
  if scope[:name]
161
- query_value(<<-SQL.strip_heredoc, "SCHEMA")
161
+ query_value(<<~SQL, "SCHEMA")
162
162
  SELECT pg_catalog.obj_description(c.oid, 'pg_class')
163
163
  FROM pg_catalog.pg_class c
164
164
  LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
@@ -196,7 +196,7 @@ module ActiveRecord
196
196
 
197
197
  # Returns an array of schema names.
198
198
  def schema_names
199
- query_values(<<-SQL, "SCHEMA")
199
+ query_values(<<~SQL, "SCHEMA")
200
200
  SELECT nspname
201
201
  FROM pg_namespace
202
202
  WHERE nspname !~ '^pg_.*'
@@ -287,7 +287,7 @@ module ActiveRecord
287
287
  quoted_sequence = quote_table_name(sequence)
288
288
  max_pk = query_value("SELECT MAX(#{quote_column_name pk}) FROM #{quote_table_name(table)}", "SCHEMA")
289
289
  if max_pk.nil?
290
- if postgresql_version >= 100000
290
+ if database_version >= 100000
291
291
  minvalue = query_value("SELECT seqmin FROM pg_sequence WHERE seqrelid = #{quote(quoted_sequence)}::regclass", "SCHEMA")
292
292
  else
293
293
  minvalue = query_value("SELECT min_value FROM #{quoted_sequence}", "SCHEMA")
@@ -302,7 +302,7 @@ module ActiveRecord
302
302
  def pk_and_sequence_for(table) #:nodoc:
303
303
  # First try looking for a sequence with a dependency on the
304
304
  # given table's primary key.
305
- result = query(<<-end_sql, "SCHEMA")[0]
305
+ result = query(<<~SQL, "SCHEMA")[0]
306
306
  SELECT attr.attname, nsp.nspname, seq.relname
307
307
  FROM pg_class seq,
308
308
  pg_attribute attr,
@@ -319,10 +319,10 @@ module ActiveRecord
319
319
  AND cons.contype = 'p'
320
320
  AND dep.classid = 'pg_class'::regclass
321
321
  AND dep.refobjid = #{quote(quote_table_name(table))}::regclass
322
- end_sql
322
+ SQL
323
323
 
324
324
  if result.nil? || result.empty?
325
- result = query(<<-end_sql, "SCHEMA")[0]
325
+ result = query(<<~SQL, "SCHEMA")[0]
326
326
  SELECT attr.attname, nsp.nspname,
327
327
  CASE
328
328
  WHEN pg_get_expr(def.adbin, def.adrelid) !~* 'nextval' THEN NULL
@@ -339,7 +339,7 @@ module ActiveRecord
339
339
  WHERE t.oid = #{quote(quote_table_name(table))}::regclass
340
340
  AND cons.contype = 'p'
341
341
  AND pg_get_expr(def.adbin, def.adrelid) ~* 'nextval|uuid_generate'
342
- end_sql
342
+ SQL
343
343
  end
344
344
 
345
345
  pk = result.shift
@@ -353,7 +353,7 @@ module ActiveRecord
353
353
  end
354
354
 
355
355
  def primary_keys(table_name) # :nodoc:
356
- query_values(<<-SQL.strip_heredoc, "SCHEMA")
356
+ query_values(<<~SQL, "SCHEMA")
357
357
  SELECT a.attname
358
358
  FROM (
359
359
  SELECT indrelid, indkey, generate_subscripts(indkey, 1) idx
@@ -368,31 +368,6 @@ module ActiveRecord
368
368
  SQL
369
369
  end
370
370
 
371
- def bulk_change_table(table_name, operations)
372
- sql_fragments = []
373
- non_combinable_operations = []
374
-
375
- operations.each do |command, args|
376
- table, arguments = args.shift, args
377
- method = :"#{command}_for_alter"
378
-
379
- if respond_to?(method, true)
380
- sqls, procs = Array(send(method, table, *arguments)).partition { |v| v.is_a?(String) }
381
- sql_fragments << sqls
382
- non_combinable_operations.concat(procs)
383
- else
384
- execute "ALTER TABLE #{quote_table_name(table_name)} #{sql_fragments.join(", ")}" unless sql_fragments.empty?
385
- non_combinable_operations.each(&:call)
386
- sql_fragments = []
387
- non_combinable_operations = []
388
- send(command, table, *arguments)
389
- end
390
- end
391
-
392
- execute "ALTER TABLE #{quote_table_name(table_name)} #{sql_fragments.join(", ")}" unless sql_fragments.empty?
393
- non_combinable_operations.each(&:call)
394
- end
395
-
396
371
  # Renames a table.
397
372
  # Also renames a table's primary key sequence if the sequence name exists and
398
373
  # matches the Active Record default.
@@ -415,7 +390,7 @@ module ActiveRecord
415
390
  rename_table_indexes(table_name, new_name)
416
391
  end
417
392
 
418
- def add_column(table_name, column_name, type, options = {}) #:nodoc:
393
+ def add_column(table_name, column_name, type, **options) #:nodoc:
419
394
  clear_cache!
420
395
  super
421
396
  change_column_comment(table_name, column_name, options[:comment]) if options.key?(:comment)
@@ -443,14 +418,16 @@ module ActiveRecord
443
418
  end
444
419
 
445
420
  # Adds comment for given table column or drops it if +comment+ is a +nil+
446
- def change_column_comment(table_name, column_name, comment) # :nodoc:
421
+ def change_column_comment(table_name, column_name, comment_or_changes) # :nodoc:
447
422
  clear_cache!
423
+ comment = extract_new_comment_value(comment_or_changes)
448
424
  execute "COMMENT ON COLUMN #{quote_table_name(table_name)}.#{quote_column_name(column_name)} IS #{quote(comment)}"
449
425
  end
450
426
 
451
427
  # Adds comment for given table or drops it if +comment+ is a +nil+
452
- def change_table_comment(table_name, comment) # :nodoc:
428
+ def change_table_comment(table_name, comment_or_changes) # :nodoc:
453
429
  clear_cache!
430
+ comment = extract_new_comment_value(comment_or_changes)
454
431
  execute "COMMENT ON TABLE #{quote_table_name(table_name)} IS #{quote(comment)}"
455
432
  end
456
433
 
@@ -462,7 +439,7 @@ module ActiveRecord
462
439
  end
463
440
 
464
441
  def add_index(table_name, column_name, options = {}) #:nodoc:
465
- index_name, index_type, index_columns_and_opclasses, index_options, index_algorithm, index_using, comment = add_index_options(table_name, column_name, options)
442
+ index_name, index_type, index_columns_and_opclasses, index_options, index_algorithm, index_using, comment = add_index_options(table_name, column_name, **options)
466
443
  execute("CREATE #{index_type} INDEX #{index_algorithm} #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} #{index_using} (#{index_columns_and_opclasses})#{index_options}").tap do
467
444
  execute "COMMENT ON INDEX #{quote_column_name(index_name)} IS #{quote(comment)}" if comment
468
445
  end
@@ -502,7 +479,7 @@ module ActiveRecord
502
479
 
503
480
  def foreign_keys(table_name)
504
481
  scope = quoted_scope(table_name)
505
- fk_info = exec_query(<<-SQL.strip_heredoc, "SCHEMA")
482
+ fk_info = exec_query(<<~SQL, "SCHEMA")
506
483
  SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete, c.convalidated AS valid
507
484
  FROM pg_constraint c
508
485
  JOIN pg_class t1 ON c.conrelid = t1.oid
@@ -548,21 +525,21 @@ module ActiveRecord
548
525
  # The hard limit is 1GB, because of a 32-bit size field, and TOAST.
549
526
  case limit
550
527
  when nil, 0..0x3fffffff; super(type)
551
- else raise(ActiveRecordError, "No binary type has byte size #{limit}.")
528
+ else raise ArgumentError, "No binary type has byte size #{limit}. The limit on binary can be at most 1GB - 1byte."
552
529
  end
553
530
  when "text"
554
531
  # PostgreSQL doesn't support limits on text columns.
555
532
  # The hard limit is 1GB, according to section 8.3 in the manual.
556
533
  case limit
557
534
  when nil, 0..0x3fffffff; super(type)
558
- else raise(ActiveRecordError, "The limit on text can be at most 1GB - 1byte.")
535
+ else raise ArgumentError, "No text type has byte size #{limit}. The limit on text can be at most 1GB - 1byte."
559
536
  end
560
537
  when "integer"
561
538
  case limit
562
539
  when 1, 2; "smallint"
563
540
  when nil, 3, 4; "integer"
564
541
  when 5..8; "bigint"
565
- else raise(ActiveRecordError, "No integer type has byte size #{limit}. Use a numeric with scale 0 instead.")
542
+ else raise ArgumentError, "No integer type has byte size #{limit}. Use a numeric with scale 0 instead."
566
543
  end
567
544
  else
568
545
  super
@@ -576,12 +553,12 @@ module ActiveRecord
576
553
  # requires that the ORDER BY include the distinct column.
577
554
  def columns_for_distinct(columns, orders) #:nodoc:
578
555
  order_columns = orders.reject(&:blank?).map { |s|
579
- # Convert Arel node to string
580
- s = s.to_sql unless s.is_a?(String)
581
- # Remove any ASC/DESC modifiers
582
- s.gsub(/\s+(?:ASC|DESC)\b/i, "")
583
- .gsub(/\s+NULLS\s+(?:FIRST|LAST)\b/i, "")
584
- }.reject(&:blank?).map.with_index { |column, i| "#{column} AS alias_#{i}" }
556
+ # Convert Arel node to string
557
+ s = visitor.compile(s) unless s.is_a?(String)
558
+ # Remove any ASC/DESC modifiers
559
+ s.gsub(/\s+(?:ASC|DESC)\b/i, "")
560
+ .gsub(/\s+NULLS\s+(?:FIRST|LAST)\b/i, "")
561
+ }.reject(&:blank?).map.with_index { |column, i| "#{column} AS alias_#{i}" }
585
562
 
586
563
  (order_columns << super).join(", ")
587
564
  end
@@ -623,10 +600,10 @@ module ActiveRecord
623
600
  # validate_foreign_key :accounts, name: :special_fk_name
624
601
  #
625
602
  # The +options+ hash accepts the same keys as SchemaStatements#add_foreign_key.
626
- def validate_foreign_key(from_table, options_or_to_table = {})
603
+ def validate_foreign_key(from_table, to_table = nil, **options)
627
604
  return unless supports_validate_constraints?
628
605
 
629
- fk_name_to_validate = foreign_key_for!(from_table, options_or_to_table).name
606
+ fk_name_to_validate = foreign_key_for!(from_table, to_table: to_table, **options).name
630
607
 
631
608
  validate_constraint from_table, fk_name_to_validate
632
609
  end
@@ -636,8 +613,8 @@ module ActiveRecord
636
613
  PostgreSQL::SchemaCreation.new(self)
637
614
  end
638
615
 
639
- def create_table_definition(*args)
640
- PostgreSQL::TableDefinition.new(*args)
616
+ def create_table_definition(*args, **options)
617
+ PostgreSQL::TableDefinition.new(self, *args, **options)
641
618
  end
642
619
 
643
620
  def create_alter_table(name)
@@ -650,16 +627,19 @@ module ActiveRecord
650
627
  default_value = extract_value_from_default(default)
651
628
  default_function = extract_default_function(default_value, default)
652
629
 
653
- PostgreSQLColumn.new(
630
+ if match = default_function&.match(/\Anextval\('"?(?<sequence_name>.+_(?<suffix>seq\d*))"?'::regclass\)\z/)
631
+ serial = sequence_name_from_parts(table_name, column_name, match[:suffix]) == match[:sequence_name]
632
+ end
633
+
634
+ PostgreSQL::Column.new(
654
635
  column_name,
655
636
  default_value,
656
637
  type_metadata,
657
638
  !notnull,
658
- table_name,
659
639
  default_function,
660
- collation,
640
+ collation: collation,
661
641
  comment: comment.presence,
662
- max_identifier_length: max_identifier_length
642
+ serial: serial
663
643
  )
664
644
  end
665
645
 
@@ -672,7 +652,23 @@ module ActiveRecord
672
652
  precision: cast_type.precision,
673
653
  scale: cast_type.scale,
674
654
  )
675
- PostgreSQLTypeMetadata.new(simple_type, oid: oid, fmod: fmod)
655
+ PostgreSQL::TypeMetadata.new(simple_type, oid: oid, fmod: fmod)
656
+ end
657
+
658
+ def sequence_name_from_parts(table_name, column_name, suffix)
659
+ over_length = [table_name, column_name, suffix].sum(&:length) + 2 - max_identifier_length
660
+
661
+ if over_length > 0
662
+ column_name_length = [(max_identifier_length - suffix.length - 2) / 2, column_name.length].min
663
+ over_length -= column_name.length - column_name_length
664
+ column_name = column_name[0, column_name_length - [over_length, 0].min]
665
+ end
666
+
667
+ if over_length > 0
668
+ table_name = table_name[0, table_name.length - over_length]
669
+ end
670
+
671
+ "#{table_name}_#{column_name}_#{suffix}"
676
672
  end
677
673
 
678
674
  def extract_foreign_key_action(specifier)
@@ -683,14 +679,14 @@ module ActiveRecord
683
679
  end
684
680
  end
685
681
 
686
- def add_column_for_alter(table_name, column_name, type, options = {})
682
+ def add_column_for_alter(table_name, column_name, type, **options)
687
683
  return super unless options.key?(:comment)
688
684
  [super, Proc.new { change_column_comment(table_name, column_name, options[:comment]) }]
689
685
  end
690
686
 
691
687
  def change_column_for_alter(table_name, column_name, type, options = {})
692
688
  td = create_table_definition(table_name)
693
- cd = td.new_column_definition(column_name, type, options)
689
+ cd = td.new_column_definition(column_name, type, **options)
694
690
  sqls = [schema_creation.accept(ChangeColumnDefinition.new(cd, column_name))]
695
691
  sqls << Proc.new { change_column_comment(table_name, column_name, options[:comment]) } if options.key?(:comment)
696
692
  sqls
@@ -715,14 +711,6 @@ module ActiveRecord
715
711
  "ALTER COLUMN #{quote_column_name(column_name)} #{null ? 'DROP' : 'SET'} NOT NULL"
716
712
  end
717
713
 
718
- def add_timestamps_for_alter(table_name, options = {})
719
- [add_column_for_alter(table_name, :created_at, :datetime, options), add_column_for_alter(table_name, :updated_at, :datetime, options)]
720
- end
721
-
722
- def remove_timestamps_for_alter(table_name, options = {})
723
- [remove_column_for_alter(table_name, :updated_at), remove_column_for_alter(table_name, :created_at)]
724
- end
725
-
726
714
  def add_index_opclass(quoted_columns, **options)
727
715
  opclasses = options_for_index_columns(options[:opclass])
728
716
  quoted_columns.each do |name, column|
@@ -731,7 +719,7 @@ module ActiveRecord
731
719
  end
732
720
 
733
721
  def add_options_for_index_columns(quoted_columns, **options)
734
- quoted_columns = add_index_opclass(quoted_columns, options)
722
+ quoted_columns = add_index_opclass(quoted_columns, **options)
735
723
  super
736
724
  end
737
725
 
@@ -739,7 +727,7 @@ module ActiveRecord
739
727
  scope = quoted_scope(name, type: type)
740
728
  scope[:type] ||= "'r','v','m','p','f'" # (r)elation/table, (v)iew, (m)aterialized view, (p)artitioned table, (f)oreign table
741
729
 
742
- sql = "SELECT c.relname FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace".dup
730
+ sql = +"SELECT c.relname FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace"
743
731
  sql << " WHERE n.nspname = #{scope[:schema]}"
744
732
  sql << " AND c.relname = #{scope[:name]}" if scope[:name]
745
733
  sql << " AND c.relkind IN (#{scope[:type]})"
@@ -1,39 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecord
4
+ # :stopdoc:
4
5
  module ConnectionAdapters
5
- class PostgreSQLTypeMetadata < DelegateClass(SqlTypeMetadata)
6
- undef to_yaml if method_defined?(:to_yaml)
6
+ module PostgreSQL
7
+ class TypeMetadata < DelegateClass(SqlTypeMetadata)
8
+ undef to_yaml if method_defined?(:to_yaml)
7
9
 
8
- attr_reader :oid, :fmod, :array
10
+ attr_reader :oid, :fmod
9
11
 
10
- def initialize(type_metadata, oid: nil, fmod: nil)
11
- super(type_metadata)
12
- @type_metadata = type_metadata
13
- @oid = oid
14
- @fmod = fmod
15
- @array = /\[\]$/.match?(type_metadata.sql_type)
16
- end
17
-
18
- def sql_type
19
- super.gsub(/\[\]$/, "".freeze)
20
- end
21
-
22
- def ==(other)
23
- other.is_a?(PostgreSQLTypeMetadata) &&
24
- attributes_for_hash == other.attributes_for_hash
25
- end
26
- alias eql? ==
27
-
28
- def hash
29
- attributes_for_hash.hash
30
- end
12
+ def initialize(type_metadata, oid: nil, fmod: nil)
13
+ super(type_metadata)
14
+ @oid = oid
15
+ @fmod = fmod
16
+ end
31
17
 
32
- protected
18
+ def ==(other)
19
+ other.is_a?(TypeMetadata) &&
20
+ __getobj__ == other.__getobj__ &&
21
+ oid == other.oid &&
22
+ fmod == other.fmod
23
+ end
24
+ alias eql? ==
33
25
 
34
- def attributes_for_hash
35
- [self.class, @type_metadata, oid, fmod]
26
+ def hash
27
+ TypeMetadata.hash ^
28
+ __getobj__.hash ^
29
+ oid.hash ^
30
+ fmod.hash
36
31
  end
32
+ end
37
33
  end
34
+ PostgreSQLTypeMetadata = PostgreSQL::TypeMetadata
38
35
  end
39
36
  end
@@ -37,7 +37,6 @@ module ActiveRecord
37
37
  end
38
38
 
39
39
  protected
40
-
41
40
  def parts
42
41
  @parts ||= [@schema, @identifier].compact
43
42
  end