activerecord 5.0.7 → 5.1.7

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 (219) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +657 -2080
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/examples/performance.rb +28 -28
  6. data/examples/simple.rb +3 -3
  7. data/lib/active_record/aggregations.rb +244 -244
  8. data/lib/active_record/association_relation.rb +5 -5
  9. data/lib/active_record/associations/alias_tracker.rb +10 -11
  10. data/lib/active_record/associations/association.rb +23 -5
  11. data/lib/active_record/associations/association_scope.rb +95 -81
  12. data/lib/active_record/associations/belongs_to_association.rb +7 -4
  13. data/lib/active_record/associations/builder/belongs_to.rb +30 -16
  14. data/lib/active_record/associations/builder/collection_association.rb +1 -2
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +27 -27
  16. data/lib/active_record/associations/collection_association.rb +36 -205
  17. data/lib/active_record/associations/collection_proxy.rb +132 -63
  18. data/lib/active_record/associations/has_many_association.rb +10 -19
  19. data/lib/active_record/associations/has_many_through_association.rb +12 -4
  20. data/lib/active_record/associations/has_one_association.rb +24 -28
  21. data/lib/active_record/associations/has_one_through_association.rb +5 -1
  22. data/lib/active_record/associations/join_dependency/join_association.rb +4 -28
  23. data/lib/active_record/associations/join_dependency/join_base.rb +1 -1
  24. data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
  25. data/lib/active_record/associations/join_dependency.rb +121 -118
  26. data/lib/active_record/associations/preloader/association.rb +64 -64
  27. data/lib/active_record/associations/preloader/belongs_to.rb +0 -2
  28. data/lib/active_record/associations/preloader/collection_association.rb +6 -6
  29. data/lib/active_record/associations/preloader/has_many.rb +0 -2
  30. data/lib/active_record/associations/preloader/singular_association.rb +6 -8
  31. data/lib/active_record/associations/preloader/through_association.rb +41 -41
  32. data/lib/active_record/associations/preloader.rb +94 -94
  33. data/lib/active_record/associations/singular_association.rb +8 -25
  34. data/lib/active_record/associations/through_association.rb +2 -5
  35. data/lib/active_record/associations.rb +1591 -1562
  36. data/lib/active_record/attribute/user_provided_default.rb +4 -2
  37. data/lib/active_record/attribute.rb +98 -71
  38. data/lib/active_record/attribute_assignment.rb +61 -61
  39. data/lib/active_record/attribute_decorators.rb +35 -13
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
  41. data/lib/active_record/attribute_methods/dirty.rb +229 -46
  42. data/lib/active_record/attribute_methods/primary_key.rb +74 -73
  43. data/lib/active_record/attribute_methods/read.rb +39 -35
  44. data/lib/active_record/attribute_methods/serialization.rb +7 -7
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +35 -58
  46. data/lib/active_record/attribute_methods/write.rb +30 -33
  47. data/lib/active_record/attribute_methods.rb +56 -65
  48. data/lib/active_record/attribute_mutation_tracker.rb +63 -11
  49. data/lib/active_record/attribute_set/builder.rb +27 -33
  50. data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
  51. data/lib/active_record/attribute_set.rb +9 -6
  52. data/lib/active_record/attributes.rb +22 -22
  53. data/lib/active_record/autosave_association.rb +18 -13
  54. data/lib/active_record/base.rb +24 -22
  55. data/lib/active_record/callbacks.rb +56 -14
  56. data/lib/active_record/coders/yaml_column.rb +9 -11
  57. data/lib/active_record/collection_cache_key.rb +3 -4
  58. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +330 -284
  59. data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
  60. data/lib/active_record/connection_adapters/abstract/database_statements.rb +39 -37
  61. data/lib/active_record/connection_adapters/abstract/query_cache.rb +32 -27
  62. data/lib/active_record/connection_adapters/abstract/quoting.rb +62 -51
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +10 -20
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +74 -79
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +120 -100
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +49 -43
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +165 -135
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +404 -424
  70. data/lib/active_record/connection_adapters/column.rb +26 -4
  71. data/lib/active_record/connection_adapters/connection_specification.rb +128 -118
  72. data/lib/active_record/connection_adapters/mysql/column.rb +6 -31
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +36 -49
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +22 -22
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +6 -12
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +16 -19
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -28
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +43 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +7 -6
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +23 -27
  82. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +32 -53
  83. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
  84. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +19 -9
  85. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
  86. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +1 -1
  89. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -3
  90. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +16 -16
  91. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +0 -10
  92. data/lib/active_record/connection_adapters/postgresql/oid/{rails_5_1_point.rb → legacy_point.rb} +9 -16
  93. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  94. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +13 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +28 -8
  96. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +32 -30
  97. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -1
  98. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +51 -51
  99. data/lib/active_record/connection_adapters/postgresql/oid.rb +22 -21
  100. data/lib/active_record/connection_adapters/postgresql/quoting.rb +40 -35
  101. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +15 -0
  102. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +37 -24
  103. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +19 -23
  104. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +182 -222
  105. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +6 -4
  106. data/lib/active_record/connection_adapters/postgresql/utils.rb +7 -5
  107. data/lib/active_record/connection_adapters/postgresql_adapter.rb +198 -167
  108. data/lib/active_record/connection_adapters/schema_cache.rb +16 -7
  109. data/lib/active_record/connection_adapters/sql_type_metadata.rb +3 -3
  110. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +1 -1
  111. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +16 -19
  112. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +1 -8
  113. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +28 -0
  114. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +17 -0
  115. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +32 -0
  116. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +184 -167
  117. data/lib/active_record/connection_adapters/statement_pool.rb +7 -7
  118. data/lib/active_record/connection_handling.rb +14 -26
  119. data/lib/active_record/core.rb +109 -93
  120. data/lib/active_record/counter_cache.rb +60 -13
  121. data/lib/active_record/define_callbacks.rb +20 -0
  122. data/lib/active_record/dynamic_matchers.rb +80 -79
  123. data/lib/active_record/enum.rb +8 -6
  124. data/lib/active_record/errors.rb +64 -15
  125. data/lib/active_record/explain.rb +1 -2
  126. data/lib/active_record/explain_registry.rb +1 -1
  127. data/lib/active_record/explain_subscriber.rb +7 -4
  128. data/lib/active_record/fixture_set/file.rb +11 -8
  129. data/lib/active_record/fixtures.rb +66 -53
  130. data/lib/active_record/gem_version.rb +1 -1
  131. data/lib/active_record/inheritance.rb +93 -79
  132. data/lib/active_record/integration.rb +7 -7
  133. data/lib/active_record/internal_metadata.rb +3 -16
  134. data/lib/active_record/legacy_yaml_adapter.rb +1 -1
  135. data/lib/active_record/locking/optimistic.rb +69 -74
  136. data/lib/active_record/locking/pessimistic.rb +10 -1
  137. data/lib/active_record/log_subscriber.rb +23 -28
  138. data/lib/active_record/migration/command_recorder.rb +94 -94
  139. data/lib/active_record/migration/compatibility.rb +100 -47
  140. data/lib/active_record/migration/join_table.rb +6 -6
  141. data/lib/active_record/migration.rb +153 -155
  142. data/lib/active_record/model_schema.rb +94 -107
  143. data/lib/active_record/nested_attributes.rb +200 -199
  144. data/lib/active_record/null_relation.rb +11 -34
  145. data/lib/active_record/persistence.rb +65 -50
  146. data/lib/active_record/query_cache.rb +2 -6
  147. data/lib/active_record/querying.rb +3 -4
  148. data/lib/active_record/railtie.rb +16 -17
  149. data/lib/active_record/railties/controller_runtime.rb +6 -2
  150. data/lib/active_record/railties/databases.rake +105 -133
  151. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  152. data/lib/active_record/readonly_attributes.rb +2 -2
  153. data/lib/active_record/reflection.rb +154 -108
  154. data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
  155. data/lib/active_record/relation/batches.rb +80 -51
  156. data/lib/active_record/relation/calculations.rb +169 -162
  157. data/lib/active_record/relation/delegation.rb +32 -31
  158. data/lib/active_record/relation/finder_methods.rb +197 -231
  159. data/lib/active_record/relation/merger.rb +58 -62
  160. data/lib/active_record/relation/predicate_builder/array_handler.rb +7 -5
  161. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +23 -23
  162. data/lib/active_record/relation/predicate_builder/base_handler.rb +3 -1
  163. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +0 -8
  164. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +12 -10
  165. data/lib/active_record/relation/predicate_builder/range_handler.rb +0 -8
  166. data/lib/active_record/relation/predicate_builder.rb +92 -89
  167. data/lib/active_record/relation/query_attribute.rb +1 -1
  168. data/lib/active_record/relation/query_methods.rb +255 -293
  169. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  170. data/lib/active_record/relation/spawn_methods.rb +4 -5
  171. data/lib/active_record/relation/where_clause.rb +80 -65
  172. data/lib/active_record/relation/where_clause_factory.rb +47 -8
  173. data/lib/active_record/relation.rb +93 -119
  174. data/lib/active_record/result.rb +41 -32
  175. data/lib/active_record/runtime_registry.rb +3 -3
  176. data/lib/active_record/sanitization.rb +176 -192
  177. data/lib/active_record/schema.rb +3 -3
  178. data/lib/active_record/schema_dumper.rb +15 -38
  179. data/lib/active_record/schema_migration.rb +8 -4
  180. data/lib/active_record/scoping/default.rb +90 -90
  181. data/lib/active_record/scoping/named.rb +11 -11
  182. data/lib/active_record/scoping.rb +6 -6
  183. data/lib/active_record/secure_token.rb +2 -2
  184. data/lib/active_record/statement_cache.rb +13 -15
  185. data/lib/active_record/store.rb +31 -32
  186. data/lib/active_record/suppressor.rb +2 -1
  187. data/lib/active_record/table_metadata.rb +9 -5
  188. data/lib/active_record/tasks/database_tasks.rb +65 -55
  189. data/lib/active_record/tasks/mysql_database_tasks.rb +76 -73
  190. data/lib/active_record/tasks/postgresql_database_tasks.rb +72 -47
  191. data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
  192. data/lib/active_record/timestamp.rb +46 -25
  193. data/lib/active_record/touch_later.rb +1 -2
  194. data/lib/active_record/transactions.rb +97 -109
  195. data/lib/active_record/type/adapter_specific_registry.rb +46 -42
  196. data/lib/active_record/type/decimal_without_scale.rb +13 -0
  197. data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
  198. data/lib/active_record/type/internal/abstract_json.rb +4 -0
  199. data/lib/active_record/type/serialized.rb +14 -8
  200. data/lib/active_record/type/text.rb +9 -0
  201. data/lib/active_record/type/time.rb +0 -1
  202. data/lib/active_record/type/type_map.rb +11 -15
  203. data/lib/active_record/type/unsigned_integer.rb +15 -0
  204. data/lib/active_record/type.rb +17 -13
  205. data/lib/active_record/type_caster/connection.rb +8 -6
  206. data/lib/active_record/type_caster/map.rb +3 -1
  207. data/lib/active_record/type_caster.rb +2 -2
  208. data/lib/active_record/validations/associated.rb +1 -1
  209. data/lib/active_record/validations/presence.rb +2 -2
  210. data/lib/active_record/validations/uniqueness.rb +8 -39
  211. data/lib/active_record/validations.rb +4 -4
  212. data/lib/active_record/version.rb +1 -1
  213. data/lib/active_record.rb +20 -20
  214. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
  215. data/lib/rails/generators/active_record/migration.rb +1 -1
  216. data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
  217. data/lib/rails/generators/active_record.rb +4 -4
  218. metadata +24 -13
  219. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
@@ -1,20 +1,29 @@
1
1
  # Make sure we're using pg high enough for type casts and Ruby 2.2+ compatibility
2
2
  gem "pg", ">= 0.18", "< 2.0"
3
- require 'pg'
3
+ require "pg"
4
+
5
+ # Use async_exec instead of exec_params on pg versions before 1.1
6
+ class ::PG::Connection
7
+ unless self.public_method_defined?(:async_exec_params)
8
+ remove_method :exec_params
9
+ alias exec_params async_exec
10
+ end
11
+ end
4
12
 
5
13
  require "active_record/connection_adapters/abstract_adapter"
14
+ require "active_record/connection_adapters/statement_pool"
6
15
  require "active_record/connection_adapters/postgresql/column"
7
16
  require "active_record/connection_adapters/postgresql/database_statements"
8
17
  require "active_record/connection_adapters/postgresql/explain_pretty_printer"
9
18
  require "active_record/connection_adapters/postgresql/oid"
10
19
  require "active_record/connection_adapters/postgresql/quoting"
11
20
  require "active_record/connection_adapters/postgresql/referential_integrity"
21
+ require "active_record/connection_adapters/postgresql/schema_creation"
12
22
  require "active_record/connection_adapters/postgresql/schema_definitions"
13
23
  require "active_record/connection_adapters/postgresql/schema_dumper"
14
24
  require "active_record/connection_adapters/postgresql/schema_statements"
15
25
  require "active_record/connection_adapters/postgresql/type_metadata"
16
26
  require "active_record/connection_adapters/postgresql/utils"
17
- require "active_record/connection_adapters/statement_pool"
18
27
 
19
28
  module ActiveRecord
20
29
  module ConnectionHandling # :nodoc:
@@ -67,10 +76,10 @@ module ActiveRecord
67
76
  # In addition, default connection parameters of libpq can be set per environment variables.
68
77
  # See http://www.postgresql.org/docs/current/static/libpq-envars.html .
69
78
  class PostgreSQLAdapter < AbstractAdapter
70
- ADAPTER_NAME = 'PostgreSQL'.freeze
79
+ ADAPTER_NAME = "PostgreSQL".freeze
71
80
 
72
81
  NATIVE_DATABASE_TYPES = {
73
- primary_key: "serial primary key",
82
+ primary_key: "bigserial primary key",
74
83
  string: { name: "character varying" },
75
84
  text: { name: "text" },
76
85
  integer: { name: "integer" },
@@ -108,6 +117,8 @@ module ActiveRecord
108
117
  bit: { name: "bit" },
109
118
  bit_varying: { name: "bit varying" },
110
119
  money: { name: "money" },
120
+ interval: { name: "interval" },
121
+ oid: { name: "oid" },
111
122
  }
112
123
 
113
124
  OID = PostgreSQL::OID #:nodoc:
@@ -173,7 +184,7 @@ module ActiveRecord
173
184
  end
174
185
 
175
186
  def index_algorithms
176
- { concurrently: 'CONCURRENTLY' }
187
+ { concurrently: "CONCURRENTLY" }
177
188
  end
178
189
 
179
190
  class StatementPool < ConnectionAdapters::StatementPool
@@ -195,6 +206,7 @@ module ActiveRecord
195
206
 
196
207
  def dealloc(key)
197
208
  @connection.query "DEALLOCATE #{key}" if connection_active?
209
+ rescue PG::Error
198
210
  end
199
211
 
200
212
  def connection_active?
@@ -227,13 +239,15 @@ module ActiveRecord
227
239
 
228
240
  @type_map = Type::HashLookupTypeMap.new
229
241
  initialize_type_map(type_map)
230
- @local_tz = execute('SHOW TIME ZONE', 'SCHEMA').first["TimeZone"]
242
+ @local_tz = execute("SHOW TIME ZONE", "SCHEMA").first["TimeZone"]
231
243
  @use_insert_returning = @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
232
244
  end
233
245
 
234
246
  # Clears the prepared statements cache.
235
247
  def clear_cache!
236
- @statements.clear
248
+ @lock.synchronize do
249
+ @statements.clear
250
+ end
237
251
  end
238
252
 
239
253
  def truncate(table_name, name = nil)
@@ -242,7 +256,9 @@ module ActiveRecord
242
256
 
243
257
  # Is this connection alive and ready for queries?
244
258
  def active?
245
- @connection.query 'SELECT 1'
259
+ @lock.synchronize do
260
+ @connection.query "SELECT 1"
261
+ end
246
262
  true
247
263
  rescue PG::Error
248
264
  false
@@ -250,44 +266,40 @@ module ActiveRecord
250
266
 
251
267
  # Close then reopen the connection.
252
268
  def reconnect!
253
- super
254
- @connection.reset
255
- configure_connection
269
+ @lock.synchronize do
270
+ super
271
+ @connection.reset
272
+ configure_connection
273
+ end
256
274
  end
257
275
 
258
276
  def reset!
259
- clear_cache!
260
- reset_transaction
261
- unless @connection.transaction_status == ::PG::PQTRANS_IDLE
262
- @connection.query 'ROLLBACK'
277
+ @lock.synchronize do
278
+ clear_cache!
279
+ reset_transaction
280
+ unless @connection.transaction_status == ::PG::PQTRANS_IDLE
281
+ @connection.query "ROLLBACK"
282
+ end
283
+ @connection.query "DISCARD ALL"
284
+ configure_connection
263
285
  end
264
- @connection.query 'DISCARD ALL'
265
- configure_connection
266
286
  end
267
287
 
268
288
  # Disconnects from the database if already connected. Otherwise, this
269
289
  # method does nothing.
270
290
  def disconnect!
271
- super
272
- @connection.close rescue nil
291
+ @lock.synchronize do
292
+ super
293
+ @connection.close rescue nil
294
+ end
273
295
  end
274
296
 
275
297
  def native_database_types #:nodoc:
276
298
  NATIVE_DATABASE_TYPES
277
299
  end
278
300
 
279
- # Returns true, since this connection adapter supports migrations.
280
- def supports_migrations?
281
- true
282
- end
283
-
284
- # Does PostgreSQL support finding primary key on non-Active Record tables?
285
- def supports_primary_key? #:nodoc:
286
- true
287
- end
288
-
289
301
  def set_standard_conforming_strings
290
- execute('SET standard_conforming_strings = on', 'SCHEMA')
302
+ execute("SET standard_conforming_strings = on", "SCHEMA")
291
303
  end
292
304
 
293
305
  def supports_ddl_transactions?
@@ -315,18 +327,22 @@ module ActiveRecord
315
327
  postgresql_version >= 90300
316
328
  end
317
329
 
330
+ def supports_pgcrypto_uuid?
331
+ postgresql_version >= 90400
332
+ end
333
+
318
334
  def get_advisory_lock(lock_id) # :nodoc:
319
335
  unless lock_id.is_a?(Integer) && lock_id.bit_length <= 63
320
336
  raise(ArgumentError, "Postgres requires advisory lock ids to be a signed 64 bit integer")
321
337
  end
322
- select_value("SELECT pg_try_advisory_lock(#{lock_id});")
338
+ query_value("SELECT pg_try_advisory_lock(#{lock_id})")
323
339
  end
324
340
 
325
341
  def release_advisory_lock(lock_id) # :nodoc:
326
342
  unless lock_id.is_a?(Integer) && lock_id.bit_length <= 63
327
343
  raise(ArgumentError, "Postgres requires advisory lock ids to be a signed 64 bit integer")
328
344
  end
329
- select_value("SELECT pg_advisory_unlock(#{lock_id})")
345
+ query_value("SELECT pg_advisory_unlock(#{lock_id})")
330
346
  end
331
347
 
332
348
  def enable_extension(name)
@@ -343,15 +359,14 @@ module ActiveRecord
343
359
 
344
360
  def extension_enabled?(name)
345
361
  if supports_extensions?
346
- res = exec_query "SELECT EXISTS(SELECT * FROM pg_available_extensions WHERE name = '#{name}' AND installed_version IS NOT NULL) as enabled",
347
- 'SCHEMA'
362
+ res = exec_query("SELECT EXISTS(SELECT * FROM pg_available_extensions WHERE name = '#{name}' AND installed_version IS NOT NULL) as enabled", "SCHEMA")
348
363
  res.cast_values.first
349
364
  end
350
365
  end
351
366
 
352
367
  def extensions
353
368
  if supports_extensions?
354
- exec_query("SELECT extname from pg_extension", "SCHEMA").cast_values
369
+ exec_query("SELECT extname FROM pg_extension", "SCHEMA").cast_values
355
370
  else
356
371
  super
357
372
  end
@@ -359,7 +374,7 @@ module ActiveRecord
359
374
 
360
375
  # Returns the configured supported identifier length supported by PostgreSQL
361
376
  def max_identifier_length
362
- @max_identifier_length ||= query('SHOW max_identifier_length', 'SCHEMA')[0][0].to_i
377
+ @max_identifier_length ||= query_value("SHOW max_identifier_length", "SCHEMA").to_i
363
378
  end
364
379
  alias table_alias_length max_identifier_length
365
380
  alias index_name_length max_identifier_length
@@ -367,26 +382,17 @@ module ActiveRecord
367
382
  # Set the authorized user for this session
368
383
  def session_auth=(user)
369
384
  clear_cache!
370
- exec_query "SET SESSION AUTHORIZATION #{user}"
385
+ execute("SET SESSION AUTHORIZATION #{user}")
371
386
  end
372
387
 
373
388
  def use_insert_returning?
374
389
  @use_insert_returning
375
390
  end
376
391
 
377
- def valid_type?(type)
378
- !native_database_types[type].nil?
379
- end
380
-
381
392
  def update_table_definition(table_name, base) #:nodoc:
382
393
  PostgreSQL::Table.new(table_name, base)
383
394
  end
384
395
 
385
- def lookup_cast_type(sql_type) # :nodoc:
386
- oid = execute("SELECT #{quote(sql_type)}::regtype::oid", "SCHEMA").first['oid'].to_i
387
- super(oid)
388
- end
389
-
390
396
  def column_name_for_operation(operation, node) # :nodoc:
391
397
  OPERATION_ALIASES.fetch(operation) { operation.downcase }
392
398
  end
@@ -402,12 +408,20 @@ module ActiveRecord
402
408
  @connection.server_version
403
409
  end
404
410
 
405
- protected
411
+ def default_index_type?(index) # :nodoc:
412
+ index.using == :btree || super
413
+ end
414
+
415
+ private
406
416
 
407
417
  # See http://www.postgresql.org/docs/current/static/errcodes-appendix.html
408
418
  VALUE_LIMIT_VIOLATION = "22001"
419
+ NUMERIC_VALUE_OUT_OF_RANGE = "22003"
420
+ NOT_NULL_VIOLATION = "23502"
409
421
  FOREIGN_KEY_VIOLATION = "23503"
410
422
  UNIQUE_VIOLATION = "23505"
423
+ SERIALIZATION_FAILURE = "40001"
424
+ DEADLOCK_DETECTED = "40P01"
411
425
 
412
426
  def translate_exception(exception, message)
413
427
  return exception unless exception.respond_to?(:result)
@@ -419,72 +433,80 @@ module ActiveRecord
419
433
  InvalidForeignKey.new(message)
420
434
  when VALUE_LIMIT_VIOLATION
421
435
  ValueTooLong.new(message)
436
+ when NUMERIC_VALUE_OUT_OF_RANGE
437
+ RangeError.new(message)
438
+ when NOT_NULL_VIOLATION
439
+ NotNullViolation.new(message)
440
+ when SERIALIZATION_FAILURE
441
+ SerializationFailure.new(message)
442
+ when DEADLOCK_DETECTED
443
+ Deadlocked.new(message)
422
444
  else
423
445
  super
424
446
  end
425
447
  end
426
448
 
427
- private
428
-
429
- def get_oid_type(oid, fmod, column_name, sql_type = '') # :nodoc:
449
+ def get_oid_type(oid, fmod, column_name, sql_type = "".freeze)
430
450
  if !type_map.key?(oid)
431
451
  load_additional_types(type_map, [oid])
432
452
  end
433
453
 
434
454
  type_map.fetch(oid, fmod, sql_type) {
435
455
  warn "unknown OID #{oid}: failed to recognize type of '#{column_name}'. It will be treated as String."
436
- Type::Value.new.tap do |cast_type|
456
+ Type.default_value.tap do |cast_type|
437
457
  type_map.register_type(oid, cast_type)
438
458
  end
439
459
  }
440
460
  end
441
461
 
442
- def initialize_type_map(m) # :nodoc:
443
- register_class_with_limit m, 'int2', Type::Integer
444
- register_class_with_limit m, 'int4', Type::Integer
445
- register_class_with_limit m, 'int8', Type::Integer
446
- m.alias_type 'oid', 'int2'
447
- m.register_type 'float4', Type::Float.new
448
- m.alias_type 'float8', 'float4'
449
- m.register_type 'text', Type::Text.new
450
- register_class_with_limit m, 'varchar', Type::String
451
- m.alias_type 'char', 'varchar'
452
- m.alias_type 'name', 'varchar'
453
- m.alias_type 'bpchar', 'varchar'
454
- m.register_type 'bool', Type::Boolean.new
455
- register_class_with_limit m, 'bit', OID::Bit
456
- register_class_with_limit m, 'varbit', OID::BitVarying
457
- m.alias_type 'timestamptz', 'timestamp'
458
- m.register_type 'date', Type::Date.new
459
-
460
- m.register_type 'money', OID::Money.new
461
- m.register_type 'bytea', OID::Bytea.new
462
- m.register_type 'point', OID::Point.new
463
- m.register_type 'hstore', OID::Hstore.new
464
- m.register_type 'json', OID::Json.new
465
- m.register_type 'jsonb', OID::Jsonb.new
466
- m.register_type 'cidr', OID::Cidr.new
467
- m.register_type 'inet', OID::Inet.new
468
- m.register_type 'uuid', OID::Uuid.new
469
- m.register_type 'xml', OID::Xml.new
470
- m.register_type 'tsvector', OID::SpecializedString.new(:tsvector)
471
- m.register_type 'macaddr', OID::SpecializedString.new(:macaddr)
472
- m.register_type 'citext', OID::SpecializedString.new(:citext)
473
- m.register_type 'ltree', OID::SpecializedString.new(:ltree)
474
- m.register_type 'line', OID::SpecializedString.new(:line)
475
- m.register_type 'lseg', OID::SpecializedString.new(:lseg)
476
- m.register_type 'box', OID::SpecializedString.new(:box)
477
- m.register_type 'path', OID::SpecializedString.new(:path)
478
- m.register_type 'polygon', OID::SpecializedString.new(:polygon)
479
- m.register_type 'circle', OID::SpecializedString.new(:circle)
480
-
481
- # FIXME: why are we keeping these types as strings?
482
- m.alias_type 'interval', 'varchar'
483
-
484
- register_class_with_precision m, 'time', Type::Time
485
- register_class_with_precision m, 'timestamp', OID::DateTime
486
-
487
- m.register_type 'numeric' do |_, fmod, sql_type|
462
+ def initialize_type_map(m)
463
+ register_class_with_limit m, "int2", Type::Integer
464
+ register_class_with_limit m, "int4", Type::Integer
465
+ register_class_with_limit m, "int8", Type::Integer
466
+ m.register_type "oid", OID::Oid.new
467
+ m.register_type "float4", Type::Float.new
468
+ m.alias_type "float8", "float4"
469
+ m.register_type "text", Type::Text.new
470
+ register_class_with_limit m, "varchar", Type::String
471
+ m.alias_type "char", "varchar"
472
+ m.alias_type "name", "varchar"
473
+ m.alias_type "bpchar", "varchar"
474
+ m.register_type "bool", Type::Boolean.new
475
+ register_class_with_limit m, "bit", OID::Bit
476
+ register_class_with_limit m, "varbit", OID::BitVarying
477
+ m.alias_type "timestamptz", "timestamp"
478
+ m.register_type "date", Type::Date.new
479
+
480
+ m.register_type "money", OID::Money.new
481
+ m.register_type "bytea", OID::Bytea.new
482
+ m.register_type "point", OID::Point.new
483
+ m.register_type "hstore", OID::Hstore.new
484
+ m.register_type "json", OID::Json.new
485
+ m.register_type "jsonb", OID::Jsonb.new
486
+ m.register_type "cidr", OID::Cidr.new
487
+ m.register_type "inet", OID::Inet.new
488
+ m.register_type "uuid", OID::Uuid.new
489
+ m.register_type "xml", OID::Xml.new
490
+ m.register_type "tsvector", OID::SpecializedString.new(:tsvector)
491
+ m.register_type "macaddr", OID::SpecializedString.new(:macaddr)
492
+ m.register_type "citext", OID::SpecializedString.new(:citext)
493
+ m.register_type "ltree", OID::SpecializedString.new(:ltree)
494
+ m.register_type "line", OID::SpecializedString.new(:line)
495
+ m.register_type "lseg", OID::SpecializedString.new(:lseg)
496
+ m.register_type "box", OID::SpecializedString.new(:box)
497
+ m.register_type "path", OID::SpecializedString.new(:path)
498
+ m.register_type "polygon", OID::SpecializedString.new(:polygon)
499
+ m.register_type "circle", OID::SpecializedString.new(:circle)
500
+
501
+ m.register_type "interval" do |_, _, sql_type|
502
+ precision = extract_precision(sql_type)
503
+ OID::SpecializedString.new(:interval, precision: precision)
504
+ end
505
+
506
+ register_class_with_precision m, "time", Type::Time
507
+ register_class_with_precision m, "timestamp", OID::DateTime
508
+
509
+ m.register_type "numeric" do |_, fmod, sql_type|
488
510
  precision = extract_precision(sql_type)
489
511
  scale = extract_scale(sql_type)
490
512
 
@@ -507,7 +529,7 @@ module ActiveRecord
507
529
  load_additional_types(m)
508
530
  end
509
531
 
510
- def extract_limit(sql_type) # :nodoc:
532
+ def extract_limit(sql_type)
511
533
  case sql_type
512
534
  when /^bigint/i, /^int8/i
513
535
  8
@@ -519,41 +541,41 @@ module ActiveRecord
519
541
  end
520
542
 
521
543
  # Extracts the value from a PostgreSQL column default definition.
522
- def extract_value_from_default(default) # :nodoc:
544
+ def extract_value_from_default(default)
523
545
  case default
524
546
  # Quoted types
525
- when /\A[\(B]?'(.*)'.*::"?([\w. ]+)"?(?:\[\])?\z/m
526
- # The default 'now'::date is CURRENT_DATE
527
- if $1 == "now".freeze && $2 == "date".freeze
528
- nil
529
- else
530
- $1.gsub("''".freeze, "'".freeze)
531
- end
547
+ when /\A[\(B]?'(.*)'.*::"?([\w. ]+)"?(?:\[\])?\z/m
548
+ # The default 'now'::date is CURRENT_DATE
549
+ if $1 == "now".freeze && $2 == "date".freeze
550
+ nil
551
+ else
552
+ $1.gsub("''".freeze, "'".freeze)
553
+ end
532
554
  # Boolean types
533
- when 'true'.freeze, 'false'.freeze
534
- default
555
+ when "true".freeze, "false".freeze
556
+ default
535
557
  # Numeric types
536
- when /\A\(?(-?\d+(\.\d*)?)\)?(::bigint)?\z/
537
- $1
558
+ when /\A\(?(-?\d+(\.\d*)?)\)?(::bigint)?\z/
559
+ $1
538
560
  # Object identifier types
539
- when /\A-?\d+\z/
540
- $1
541
- else
542
- # Anything else is blank, some user type, or some function
543
- # and we can't know the value of that, so return nil.
544
- nil
561
+ when /\A-?\d+\z/
562
+ $1
563
+ else
564
+ # Anything else is blank, some user type, or some function
565
+ # and we can't know the value of that, so return nil.
566
+ nil
545
567
  end
546
568
  end
547
569
 
548
- def extract_default_function(default_value, default) # :nodoc:
570
+ def extract_default_function(default_value, default)
549
571
  default if has_default_function?(default_value, default)
550
572
  end
551
573
 
552
- def has_default_function?(default_value, default) # :nodoc:
553
- !default_value && (%r{\w+\(.*\)|\(.*\)::\w+} === default)
574
+ def has_default_function?(default_value, default)
575
+ !default_value && %r{\w+\(.*\)|\(.*\)::\w+|CURRENT_DATE|CURRENT_TIMESTAMP}.match?(default)
554
576
  end
555
577
 
556
- def load_additional_types(type_map, oids = nil) # :nodoc:
578
+ def load_additional_types(type_map, oids = nil)
557
579
  initializer = OID::TypeMapInitializer.new(type_map)
558
580
 
559
581
  if supports_ranges?
@@ -575,7 +597,7 @@ module ActiveRecord
575
597
  query += initializer.query_conditions_for_initial_load(type_map)
576
598
  end
577
599
 
578
- execute_and_clear(query, 'SCHEMA', []) do |records|
600
+ execute_and_clear(query, "SCHEMA", []) do |records|
579
601
  initializer.run(records)
580
602
  end
581
603
  end
@@ -597,7 +619,11 @@ module ActiveRecord
597
619
 
598
620
  def exec_no_cache(sql, name, binds)
599
621
  type_casted_binds = type_casted_binds(binds)
600
- log(sql, name, binds, type_casted_binds) { @connection.async_exec(sql, type_casted_binds) }
622
+ log(sql, name, binds, type_casted_binds) do
623
+ ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
624
+ @connection.exec_params(sql, type_casted_binds)
625
+ end
626
+ end
601
627
  end
602
628
 
603
629
  def exec_cache(sql, name, binds)
@@ -605,7 +631,9 @@ module ActiveRecord
605
631
  type_casted_binds = type_casted_binds(binds)
606
632
 
607
633
  log(sql, name, binds, type_casted_binds, stmt_key) do
608
- @connection.exec_prepared(stmt_key, type_casted_binds)
634
+ ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
635
+ @connection.exec_prepared(stmt_key, type_casted_binds)
636
+ end
609
637
  end
610
638
  rescue ActiveRecord::StatementInvalid => e
611
639
  raise unless is_cached_plan_failure?(e)
@@ -615,8 +643,10 @@ module ActiveRecord
615
643
  if in_transaction?
616
644
  raise ActiveRecord::PreparedStatementCacheExpired.new(e.cause.message)
617
645
  else
618
- # outside of transactions we can simply flush this query and retry
619
- @statements.delete sql_key(sql)
646
+ @lock.synchronize do
647
+ # outside of transactions we can simply flush this query and retry
648
+ @statements.delete sql_key(sql)
649
+ end
620
650
  retry
621
651
  end
622
652
  end
@@ -630,7 +660,7 @@ module ActiveRecord
630
660
  #
631
661
  # Check here for more details:
632
662
  # http://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/cache/plancache.c#l573
633
- CACHED_PLAN_HEURISTIC = 'cached plan must not change result type'.freeze
663
+ CACHED_PLAN_HEURISTIC = "cached plan must not change result type".freeze
634
664
  def is_cached_plan_failure?(e)
635
665
  pgerror = e.cause
636
666
  code = pgerror.result.result_error_field(PG::PG_DIAG_SQLSTATE)
@@ -652,19 +682,21 @@ module ActiveRecord
652
682
  # Prepare the statement if it hasn't been prepared, return
653
683
  # the statement key.
654
684
  def prepare_statement(sql)
655
- sql_key = sql_key(sql)
656
- unless @statements.key? sql_key
657
- nextkey = @statements.next_key
658
- begin
659
- @connection.prepare nextkey, sql
660
- rescue => e
661
- raise translate_exception_class(e, sql)
685
+ @lock.synchronize do
686
+ sql_key = sql_key(sql)
687
+ unless @statements.key? sql_key
688
+ nextkey = @statements.next_key
689
+ begin
690
+ @connection.prepare nextkey, sql
691
+ rescue => e
692
+ raise translate_exception_class(e, sql)
693
+ end
694
+ # Clear the queue
695
+ @connection.get_last_result
696
+ @statements[sql_key] = nextkey
662
697
  end
663
- # Clear the queue
664
- @connection.get_last_result
665
- @statements[sql_key] = nextkey
698
+ @statements[sql_key]
666
699
  end
667
- @statements[sql_key]
668
700
  end
669
701
 
670
702
  # Connects to a PostgreSQL server and sets up the adapter depending on the
@@ -686,7 +718,7 @@ module ActiveRecord
686
718
  if @config[:encoding]
687
719
  @connection.set_client_encoding(@config[:encoding])
688
720
  end
689
- self.client_min_messages = @config[:min_messages] || 'warning'
721
+ self.client_min_messages = @config[:min_messages] || "warning"
690
722
  self.schema_search_path = @config[:schema_search_path] || @config[:schema_order]
691
723
 
692
724
  # Use standard-conforming strings so we don't have to do the E'...' dance.
@@ -696,27 +728,27 @@ module ActiveRecord
696
728
  # TIMESTAMP WITH ZONE types in UTC.
697
729
  # (SET TIME ZONE does not use an equals sign like other SET variables)
698
730
  if ActiveRecord::Base.default_timezone == :utc
699
- execute("SET time zone 'UTC'", 'SCHEMA')
731
+ execute("SET time zone 'UTC'", "SCHEMA")
700
732
  elsif @local_tz
701
- execute("SET time zone '#{@local_tz}'", 'SCHEMA')
733
+ execute("SET time zone '#{@local_tz}'", "SCHEMA")
702
734
  end
703
735
 
704
736
  # SET statements from :variables config hash
705
737
  # http://www.postgresql.org/docs/current/static/sql-set.html
706
738
  variables = @config[:variables] || {}
707
739
  variables.map do |k, v|
708
- if v == ':default' || v == :default
740
+ if v == ":default" || v == :default
709
741
  # Sets the value to the global or compile default
710
- execute("SET SESSION #{k} TO DEFAULT", 'SCHEMA')
742
+ execute("SET SESSION #{k} TO DEFAULT", "SCHEMA")
711
743
  elsif !v.nil?
712
- execute("SET SESSION #{k} TO #{quote(v)}", 'SCHEMA')
744
+ execute("SET SESSION #{k} TO #{quote(v)}", "SCHEMA")
713
745
  end
714
746
  end
715
747
  end
716
748
 
717
749
  # Returns the current ID of a table's sequence.
718
- def last_insert_id_result(sequence_name) # :nodoc:
719
- exec_query("SELECT currval('#{sequence_name}')", 'SQL')
750
+ def last_insert_id_result(sequence_name)
751
+ exec_query("SELECT currval('#{sequence_name}')", "SQL")
720
752
  end
721
753
 
722
754
  # Returns the list of a table's column names, data types, and default values.
@@ -737,27 +769,27 @@ module ActiveRecord
737
769
  # Query implementation notes:
738
770
  # - format_type includes the column size constraint, e.g. varchar(50)
739
771
  # - ::regclass is a function that gives the id for a table name
740
- def column_definitions(table_name) # :nodoc:
741
- query(<<-end_sql, 'SCHEMA')
772
+ def column_definitions(table_name)
773
+ query(<<-end_sql, "SCHEMA")
742
774
  SELECT a.attname, format_type(a.atttypid, a.atttypmod),
743
775
  pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
744
- (SELECT c.collname FROM pg_collation c, pg_type t
745
- WHERE c.oid = a.attcollation AND t.oid = a.atttypid AND a.attcollation <> t.typcollation),
746
- col_description(a.attrelid, a.attnum) AS comment
747
- FROM pg_attribute a LEFT JOIN pg_attrdef d
748
- ON a.attrelid = d.adrelid AND a.attnum = d.adnum
749
- WHERE a.attrelid = '#{quote_table_name(table_name)}'::regclass
776
+ c.collname, col_description(a.attrelid, a.attnum) AS comment
777
+ FROM pg_attribute a
778
+ LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
779
+ LEFT JOIN pg_type t ON a.atttypid = t.oid
780
+ LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation
781
+ WHERE a.attrelid = #{quote(quote_table_name(table_name))}::regclass
750
782
  AND a.attnum > 0 AND NOT a.attisdropped
751
783
  ORDER BY a.attnum
752
784
  end_sql
753
785
  end
754
786
 
755
- def extract_table_ref_from_insert_sql(sql) # :nodoc:
787
+ def extract_table_ref_from_insert_sql(sql)
756
788
  sql[/into\s("[A-Za-z0-9_."\[\]\s]+"|[A-Za-z0-9_."\[\]]+)\s*/im]
757
789
  $1.strip if $1
758
790
  end
759
791
 
760
- def create_table_definition(*args) # :nodoc:
792
+ def create_table_definition(*args)
761
793
  PostgreSQL::TableDefinition.new(*args)
762
794
  end
763
795
 
@@ -788,19 +820,18 @@ module ActiveRecord
788
820
  map[Integer] = PG::TextEncoder::Integer.new
789
821
  map[TrueClass] = PG::TextEncoder::Boolean.new
790
822
  map[FalseClass] = PG::TextEncoder::Boolean.new
791
- map[Float] = PG::TextEncoder::Float.new
792
823
  @connection.type_map_for_queries = map
793
824
  end
794
825
 
795
826
  def add_pg_decoders
796
827
  coders_by_name = {
797
- 'int2' => PG::TextDecoder::Integer,
798
- 'int4' => PG::TextDecoder::Integer,
799
- 'int8' => PG::TextDecoder::Integer,
800
- 'oid' => PG::TextDecoder::Integer,
801
- 'float4' => PG::TextDecoder::Float,
802
- 'float8' => PG::TextDecoder::Float,
803
- 'bool' => PG::TextDecoder::Boolean,
828
+ "int2" => PG::TextDecoder::Integer,
829
+ "int4" => PG::TextDecoder::Integer,
830
+ "int8" => PG::TextDecoder::Integer,
831
+ "oid" => PG::TextDecoder::Integer,
832
+ "float4" => PG::TextDecoder::Float,
833
+ "float8" => PG::TextDecoder::Float,
834
+ "bool" => PG::TextDecoder::Boolean,
804
835
  }
805
836
  known_coder_types = coders_by_name.keys.map { |n| quote(n) }
806
837
  query = <<-SQL % known_coder_types.join(", ")
@@ -810,7 +841,7 @@ module ActiveRecord
810
841
  SQL
811
842
  coders = execute_and_clear(query, "SCHEMA", []) do |result|
812
843
  result
813
- .map { |row| construct_coder(row, coders_by_name[row['typname']]) }
844
+ .map { |row| construct_coder(row, coders_by_name[row["typname"]]) }
814
845
  .compact
815
846
  end
816
847
 
@@ -821,7 +852,7 @@ module ActiveRecord
821
852
 
822
853
  def construct_coder(row, coder_class)
823
854
  return unless coder_class
824
- coder_class.new(oid: row['oid'].to_i, name: row['typname'])
855
+ coder_class.new(oid: row["oid"].to_i, name: row["typname"])
825
856
  end
826
857
 
827
858
  ActiveRecord::Type.add_modifier({ array: true }, OID::Array, adapter: :postgresql)
@@ -838,8 +869,8 @@ module ActiveRecord
838
869
  ActiveRecord::Type.register(:json, OID::Json, adapter: :postgresql)
839
870
  ActiveRecord::Type.register(:jsonb, OID::Jsonb, adapter: :postgresql)
840
871
  ActiveRecord::Type.register(:money, OID::Money, adapter: :postgresql)
841
- ActiveRecord::Type.register(:point, OID::Rails51Point, adapter: :postgresql)
842
- ActiveRecord::Type.register(:legacy_point, OID::Point, adapter: :postgresql)
872
+ ActiveRecord::Type.register(:point, OID::Point, adapter: :postgresql)
873
+ ActiveRecord::Type.register(:legacy_point, OID::LegacyPoint, adapter: :postgresql)
843
874
  ActiveRecord::Type.register(:uuid, OID::Uuid, adapter: :postgresql)
844
875
  ActiveRecord::Type.register(:vector, OID::Vector, adapter: :postgresql)
845
876
  ActiveRecord::Type.register(:xml, OID::Xml, adapter: :postgresql)