activerecord 6.0.1 → 6.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1314 -633
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -4
- data/lib/active_record/aggregations.rb +5 -6
- data/lib/active_record/association_relation.rb +26 -15
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +55 -37
- data/lib/active_record/associations/association_scope.rb +19 -15
- data/lib/active_record/associations/belongs_to_association.rb +23 -10
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -3
- data/lib/active_record/associations/builder/association.rb +32 -5
- data/lib/active_record/associations/builder/belongs_to.rb +10 -7
- data/lib/active_record/associations/builder/collection_association.rb +5 -4
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -3
- data/lib/active_record/associations/builder/has_many.rb +6 -2
- data/lib/active_record/associations/builder/has_one.rb +11 -14
- data/lib/active_record/associations/builder/singular_association.rb +1 -1
- data/lib/active_record/associations/collection_association.rb +38 -13
- data/lib/active_record/associations/collection_proxy.rb +14 -7
- data/lib/active_record/associations/foreign_association.rb +13 -0
- data/lib/active_record/associations/has_many_association.rb +24 -3
- data/lib/active_record/associations/has_many_through_association.rb +10 -4
- data/lib/active_record/associations/has_one_association.rb +15 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +39 -16
- data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
- data/lib/active_record/associations/join_dependency.rb +73 -42
- data/lib/active_record/associations/preloader/association.rb +49 -25
- data/lib/active_record/associations/preloader/through_association.rb +2 -2
- data/lib/active_record/associations/preloader.rb +12 -7
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +119 -12
- data/lib/active_record/attribute_assignment.rb +10 -9
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -10
- data/lib/active_record/attribute_methods/dirty.rb +3 -13
- data/lib/active_record/attribute_methods/primary_key.rb +6 -4
- data/lib/active_record/attribute_methods/query.rb +3 -6
- data/lib/active_record/attribute_methods/read.rb +8 -12
- data/lib/active_record/attribute_methods/serialization.rb +11 -6
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
- data/lib/active_record/attribute_methods/write.rb +12 -21
- data/lib/active_record/attribute_methods.rb +64 -54
- data/lib/active_record/attributes.rb +33 -9
- data/lib/active_record/autosave_association.rb +56 -41
- data/lib/active_record/base.rb +2 -14
- data/lib/active_record/callbacks.rb +153 -24
- data/lib/active_record/coders/yaml_column.rb +24 -3
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +190 -136
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +83 -38
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -9
- data/lib/active_record/connection_adapters/abstract/quoting.rb +34 -34
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +152 -116
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +145 -52
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +267 -105
- data/lib/active_record/connection_adapters/abstract/transaction.rb +94 -36
- data/lib/active_record/connection_adapters/abstract_adapter.rb +63 -77
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +136 -111
- data/lib/active_record/connection_adapters/column.rb +15 -1
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +30 -36
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +18 -3
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -7
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +5 -2
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +20 -13
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -13
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +21 -56
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -6
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +7 -3
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +72 -54
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +80 -66
- data/lib/active_record/connection_adapters/schema_cache.rb +130 -15
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +38 -12
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +38 -5
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +57 -57
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_adapters.rb +52 -0
- data/lib/active_record/connection_handling.rb +218 -87
- data/lib/active_record/core.rb +269 -68
- data/lib/active_record/counter_cache.rb +4 -1
- data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
- data/lib/active_record/database_configurations/database_config.rb +52 -9
- data/lib/active_record/database_configurations/hash_config.rb +54 -8
- data/lib/active_record/database_configurations/url_config.rb +15 -41
- data/lib/active_record/database_configurations.rb +125 -85
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +2 -3
- data/lib/active_record/enum.rb +80 -38
- data/lib/active_record/errors.rb +47 -12
- data/lib/active_record/explain.rb +9 -5
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +10 -17
- data/lib/active_record/fixture_set/model_metadata.rb +1 -2
- data/lib/active_record/fixture_set/render_context.rb +1 -1
- data/lib/active_record/fixture_set/table_row.rb +2 -3
- data/lib/active_record/fixture_set/table_rows.rb +0 -1
- data/lib/active_record/fixtures.rb +58 -12
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +40 -21
- data/lib/active_record/insert_all.rb +42 -9
- data/lib/active_record/integration.rb +3 -5
- data/lib/active_record/internal_metadata.rb +18 -7
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +33 -18
- data/lib/active_record/locking/pessimistic.rb +6 -2
- data/lib/active_record/log_subscriber.rb +28 -9
- data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +6 -2
- data/lib/active_record/middleware/database_selector.rb +4 -2
- data/lib/active_record/migration/command_recorder.rb +53 -45
- data/lib/active_record/migration/compatibility.rb +75 -21
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/migration.rb +115 -85
- data/lib/active_record/model_schema.rb +117 -15
- data/lib/active_record/nested_attributes.rb +2 -5
- data/lib/active_record/no_touching.rb +1 -1
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +50 -46
- data/lib/active_record/query_cache.rb +15 -5
- data/lib/active_record/querying.rb +12 -7
- data/lib/active_record/railtie.rb +65 -45
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/databases.rake +280 -99
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +77 -63
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/batches.rb +38 -32
- data/lib/active_record/relation/calculations.rb +106 -45
- data/lib/active_record/relation/delegation.rb +9 -7
- data/lib/active_record/relation/finder_methods.rb +45 -16
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +27 -26
- data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +4 -5
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +59 -40
- data/lib/active_record/relation/query_methods.rb +339 -188
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +8 -8
- data/lib/active_record/relation/where_clause.rb +111 -62
- data/lib/active_record/relation.rb +116 -83
- data/lib/active_record/result.rb +41 -34
- data/lib/active_record/runtime_registry.rb +2 -2
- data/lib/active_record/sanitization.rb +6 -17
- data/lib/active_record/schema_dumper.rb +34 -4
- data/lib/active_record/schema_migration.rb +2 -8
- data/lib/active_record/scoping/default.rb +1 -4
- data/lib/active_record/scoping/named.rb +7 -18
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/secure_token.rb +16 -8
- data/lib/active_record/serialization.rb +5 -3
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +20 -4
- data/lib/active_record/store.rb +9 -4
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +42 -36
- data/lib/active_record/tasks/database_tasks.rb +140 -113
- data/lib/active_record/tasks/mysql_database_tasks.rb +34 -36
- data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -27
- data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -10
- data/lib/active_record/test_databases.rb +5 -4
- data/lib/active_record/test_fixtures.rb +87 -20
- data/lib/active_record/timestamp.rb +4 -7
- data/lib/active_record/touch_later.rb +20 -21
- data/lib/active_record/transactions.rb +25 -72
- data/lib/active_record/type/adapter_specific_registry.rb +2 -5
- data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
- data/lib/active_record/type/serialized.rb +6 -3
- data/lib/active_record/type/time.rb +10 -0
- data/lib/active_record/type/type_map.rb +0 -1
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +8 -2
- data/lib/active_record/type_caster/connection.rb +0 -1
- data/lib/active_record/type_caster/map.rb +8 -5
- data/lib/active_record/validations/associated.rb +1 -2
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +24 -4
- data/lib/active_record/validations.rb +3 -3
- data/lib/active_record.rb +7 -13
- data/lib/arel/attributes/attribute.rb +4 -0
- data/lib/arel/collectors/bind.rb +5 -0
- data/lib/arel/collectors/composite.rb +8 -0
- data/lib/arel/collectors/sql_string.rb +7 -0
- data/lib/arel/collectors/substitute_binds.rb +7 -0
- data/lib/arel/nodes/binary.rb +82 -8
- data/lib/arel/nodes/bind_param.rb +8 -0
- data/lib/arel/nodes/casted.rb +21 -9
- data/lib/arel/nodes/equality.rb +6 -9
- data/lib/arel/nodes/grouping.rb +3 -0
- data/lib/arel/nodes/homogeneous_in.rb +76 -0
- data/lib/arel/nodes/in.rb +8 -1
- data/lib/arel/nodes/infix_operation.rb +13 -1
- data/lib/arel/nodes/join_source.rb +1 -1
- data/lib/arel/nodes/node.rb +7 -6
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/sql_literal.rb +3 -0
- data/lib/arel/nodes/table_alias.rb +7 -3
- data/lib/arel/nodes/unary.rb +0 -1
- data/lib/arel/nodes.rb +3 -1
- data/lib/arel/predications.rb +17 -24
- data/lib/arel/select_manager.rb +1 -2
- data/lib/arel/table.rb +13 -5
- data/lib/arel/visitors/dot.rb +14 -3
- data/lib/arel/visitors/mysql.rb +11 -1
- data/lib/arel/visitors/postgresql.rb +15 -5
- data/lib/arel/visitors/sqlite.rb +0 -1
- data/lib/arel/visitors/to_sql.rb +89 -79
- data/lib/arel/visitors/visitor.rb +0 -1
- data/lib/arel/visitors.rb +0 -7
- data/lib/arel.rb +5 -9
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
- data/lib/rails/generators/active_record/migration.rb +6 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +38 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- metadata +30 -29
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
- data/lib/active_record/relation/where_clause_factory.rb +0 -33
- data/lib/arel/attributes.rb +0 -22
- data/lib/arel/visitors/depth_first.rb +0 -204
- data/lib/arel/visitors/ibm_db.rb +0 -34
- data/lib/arel/visitors/informix.rb +0 -62
- data/lib/arel/visitors/mssql.rb +0 -157
- data/lib/arel/visitors/oracle.rb +0 -159
- data/lib/arel/visitors/oracle12.rb +0 -66
- data/lib/arel/visitors/where_sql.rb +0 -23
@@ -54,7 +54,8 @@ module ActiveRecord
|
|
54
54
|
execute "DROP DATABASE IF EXISTS #{quote_table_name(name)}"
|
55
55
|
end
|
56
56
|
|
57
|
-
def drop_table(table_name, options
|
57
|
+
def drop_table(table_name, **options) # :nodoc:
|
58
|
+
schema_cache.clear_data_source_cache!(table_name.to_s)
|
58
59
|
execute "DROP TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}#{' CASCADE' if options[:force] == :cascade}"
|
59
60
|
end
|
60
61
|
|
@@ -74,7 +75,7 @@ module ActiveRecord
|
|
74
75
|
INNER JOIN pg_index d ON t.oid = d.indrelid
|
75
76
|
INNER JOIN pg_class i ON d.indexrelid = i.oid
|
76
77
|
LEFT JOIN pg_namespace n ON n.oid = i.relnamespace
|
77
|
-
WHERE i.relkind
|
78
|
+
WHERE i.relkind IN ('i', 'I')
|
78
79
|
AND i.relname = #{index[:name]}
|
79
80
|
AND t.relname = #{table[:name]}
|
80
81
|
AND n.nspname = #{index[:schema]}
|
@@ -92,7 +93,7 @@ module ActiveRecord
|
|
92
93
|
INNER JOIN pg_index d ON t.oid = d.indrelid
|
93
94
|
INNER JOIN pg_class i ON d.indexrelid = i.oid
|
94
95
|
LEFT JOIN pg_namespace n ON n.oid = i.relnamespace
|
95
|
-
WHERE i.relkind
|
96
|
+
WHERE i.relkind IN ('i', 'I')
|
96
97
|
AND d.indisprimary = 'f'
|
97
98
|
AND t.relname = #{scope[:name]}
|
98
99
|
AND n.nspname = #{scope[:schema]}
|
@@ -211,7 +212,7 @@ module ActiveRecord
|
|
211
212
|
end
|
212
213
|
|
213
214
|
# Drops the schema for the given schema name.
|
214
|
-
def drop_schema(schema_name, options
|
215
|
+
def drop_schema(schema_name, **options)
|
215
216
|
execute "DROP SCHEMA#{' IF EXISTS' if options[:if_exists]} #{quote_schema_name(schema_name)} CASCADE"
|
216
217
|
end
|
217
218
|
|
@@ -376,6 +377,8 @@ module ActiveRecord
|
|
376
377
|
# rename_table('octopuses', 'octopi')
|
377
378
|
def rename_table(table_name, new_name)
|
378
379
|
clear_cache!
|
380
|
+
schema_cache.clear_data_source_cache!(table_name.to_s)
|
381
|
+
schema_cache.clear_data_source_cache!(new_name.to_s)
|
379
382
|
execute "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}"
|
380
383
|
pk, seq = pk_and_sequence_for(new_name)
|
381
384
|
if pk
|
@@ -390,15 +393,15 @@ module ActiveRecord
|
|
390
393
|
rename_table_indexes(table_name, new_name)
|
391
394
|
end
|
392
395
|
|
393
|
-
def add_column(table_name, column_name, type, options
|
396
|
+
def add_column(table_name, column_name, type, **options) #:nodoc:
|
394
397
|
clear_cache!
|
395
398
|
super
|
396
399
|
change_column_comment(table_name, column_name, options[:comment]) if options.key?(:comment)
|
397
400
|
end
|
398
401
|
|
399
|
-
def change_column(table_name, column_name, type, options
|
402
|
+
def change_column(table_name, column_name, type, **options) #:nodoc:
|
400
403
|
clear_cache!
|
401
|
-
sqls, procs = Array(change_column_for_alter(table_name, column_name, type, options)).partition { |v| v.is_a?(String) }
|
404
|
+
sqls, procs = Array(change_column_for_alter(table_name, column_name, type, **options)).partition { |v| v.is_a?(String) }
|
402
405
|
execute "ALTER TABLE #{quote_table_name(table_name)} #{sqls.join(", ")}"
|
403
406
|
procs.each(&:call)
|
404
407
|
end
|
@@ -434,21 +437,24 @@ module ActiveRecord
|
|
434
437
|
# Renames a column in a table.
|
435
438
|
def rename_column(table_name, column_name, new_column_name) #:nodoc:
|
436
439
|
clear_cache!
|
437
|
-
execute
|
440
|
+
execute("ALTER TABLE #{quote_table_name(table_name)} #{rename_column_sql(table_name, column_name, new_column_name)}")
|
438
441
|
rename_column_indexes(table_name, column_name, new_column_name)
|
439
442
|
end
|
440
443
|
|
441
|
-
def add_index(table_name, column_name, options
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
444
|
+
def add_index(table_name, column_name, **options) #:nodoc:
|
445
|
+
index, algorithm, if_not_exists = add_index_options(table_name, column_name, **options)
|
446
|
+
|
447
|
+
create_index = CreateIndexDefinition.new(index, algorithm, if_not_exists)
|
448
|
+
result = execute schema_creation.accept(create_index)
|
449
|
+
|
450
|
+
execute "COMMENT ON INDEX #{quote_column_name(index.name)} IS #{quote(index.comment)}" if index.comment
|
451
|
+
result
|
446
452
|
end
|
447
453
|
|
448
|
-
def remove_index(table_name,
|
454
|
+
def remove_index(table_name, column_name = nil, **options) # :nodoc:
|
449
455
|
table = Utils.extract_schema_qualified_name(table_name.to_s)
|
450
456
|
|
451
|
-
if options.
|
457
|
+
if options.key?(:name)
|
452
458
|
provided_index = Utils.extract_schema_qualified_name(options[:name].to_s)
|
453
459
|
|
454
460
|
options[:name] = provided_index.identifier
|
@@ -459,14 +465,11 @@ module ActiveRecord
|
|
459
465
|
end
|
460
466
|
end
|
461
467
|
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
end
|
468
|
-
end
|
469
|
-
execute "DROP INDEX #{algorithm} #{quote_table_name(index_to_remove)}"
|
468
|
+
return if options[:if_exists] && !index_exists?(table_name, column_name, **options)
|
469
|
+
|
470
|
+
index_to_remove = PostgreSQL::Name.new(table.schema, index_name_for_remove(table.to_s, column_name, options))
|
471
|
+
|
472
|
+
execute "DROP INDEX #{index_algorithm(options[:algorithm])} #{quote_table_name(index_to_remove)}"
|
470
473
|
end
|
471
474
|
|
472
475
|
# Renames an index of a table. Raises error if length of new
|
@@ -516,6 +519,28 @@ module ActiveRecord
|
|
516
519
|
query_values(data_source_sql(table_name, type: "FOREIGN TABLE"), "SCHEMA").any? if table_name.present?
|
517
520
|
end
|
518
521
|
|
522
|
+
def check_constraints(table_name) # :nodoc:
|
523
|
+
scope = quoted_scope(table_name)
|
524
|
+
|
525
|
+
check_info = exec_query(<<-SQL, "SCHEMA")
|
526
|
+
SELECT conname, pg_get_constraintdef(c.oid) AS constraintdef, c.convalidated AS valid
|
527
|
+
FROM pg_constraint c
|
528
|
+
JOIN pg_class t ON c.conrelid = t.oid
|
529
|
+
WHERE c.contype = 'c'
|
530
|
+
AND t.relname = #{scope[:name]}
|
531
|
+
SQL
|
532
|
+
|
533
|
+
check_info.map do |row|
|
534
|
+
options = {
|
535
|
+
name: row["conname"],
|
536
|
+
validate: row["valid"]
|
537
|
+
}
|
538
|
+
expression = row["constraintdef"][/CHECK \({2}(.+)\){2}/, 1]
|
539
|
+
|
540
|
+
CheckConstraintDefinition.new(table_name, expression, options)
|
541
|
+
end
|
542
|
+
end
|
543
|
+
|
519
544
|
# Maps logical Rails types to PostgreSQL-specific data types.
|
520
545
|
def type_to_sql(type, limit: nil, precision: nil, scale: nil, array: nil, **) # :nodoc:
|
521
546
|
sql = \
|
@@ -552,13 +577,13 @@ module ActiveRecord
|
|
552
577
|
# PostgreSQL requires the ORDER BY columns in the select list for distinct queries, and
|
553
578
|
# requires that the ORDER BY include the distinct column.
|
554
579
|
def columns_for_distinct(columns, orders) #:nodoc:
|
555
|
-
order_columns = orders.
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
580
|
+
order_columns = orders.compact_blank.map { |s|
|
581
|
+
# Convert Arel node to string
|
582
|
+
s = visitor.compile(s) unless s.is_a?(String)
|
583
|
+
# Remove any ASC/DESC modifiers
|
584
|
+
s.gsub(/\s+(?:ASC|DESC)\b/i, "")
|
585
|
+
.gsub(/\s+NULLS\s+(?:FIRST|LAST)\b/i, "")
|
586
|
+
}.compact_blank.map.with_index { |column, i| "#{column} AS alias_#{i}" }
|
562
587
|
|
563
588
|
(order_columns << super).join(", ")
|
564
589
|
end
|
@@ -577,8 +602,6 @@ module ActiveRecord
|
|
577
602
|
#
|
578
603
|
# validate_constraint :accounts, :constraint_name
|
579
604
|
def validate_constraint(table_name, constraint_name)
|
580
|
-
return unless supports_validate_constraints?
|
581
|
-
|
582
605
|
at = create_alter_table table_name
|
583
606
|
at.validate_constraint constraint_name
|
584
607
|
|
@@ -601,20 +624,29 @@ module ActiveRecord
|
|
601
624
|
#
|
602
625
|
# The +options+ hash accepts the same keys as SchemaStatements#add_foreign_key.
|
603
626
|
def validate_foreign_key(from_table, to_table = nil, **options)
|
604
|
-
return unless supports_validate_constraints?
|
605
|
-
|
606
627
|
fk_name_to_validate = foreign_key_for!(from_table, to_table: to_table, **options).name
|
607
628
|
|
608
629
|
validate_constraint from_table, fk_name_to_validate
|
609
630
|
end
|
610
631
|
|
632
|
+
# Validates the given check constraint.
|
633
|
+
#
|
634
|
+
# validate_check_constraint :products, name: "price_check"
|
635
|
+
#
|
636
|
+
# The +options+ hash accepts the same keys as add_check_constraint[rdoc-ref:ConnectionAdapters::SchemaStatements#add_check_constraint].
|
637
|
+
def validate_check_constraint(table_name, **options)
|
638
|
+
chk_name_to_validate = check_constraint_for!(table_name, **options).name
|
639
|
+
|
640
|
+
validate_constraint table_name, chk_name_to_validate
|
641
|
+
end
|
642
|
+
|
611
643
|
private
|
612
644
|
def schema_creation
|
613
645
|
PostgreSQL::SchemaCreation.new(self)
|
614
646
|
end
|
615
647
|
|
616
|
-
def create_table_definition(
|
617
|
-
PostgreSQL::TableDefinition.new(self,
|
648
|
+
def create_table_definition(name, **options)
|
649
|
+
PostgreSQL::TableDefinition.new(self, name, **options)
|
618
650
|
end
|
619
651
|
|
620
652
|
def create_alter_table(name)
|
@@ -679,14 +711,14 @@ module ActiveRecord
|
|
679
711
|
end
|
680
712
|
end
|
681
713
|
|
682
|
-
def add_column_for_alter(table_name, column_name, type, options
|
714
|
+
def add_column_for_alter(table_name, column_name, type, **options)
|
683
715
|
return super unless options.key?(:comment)
|
684
716
|
[super, Proc.new { change_column_comment(table_name, column_name, options[:comment]) }]
|
685
717
|
end
|
686
718
|
|
687
|
-
def change_column_for_alter(table_name, column_name, type, options
|
719
|
+
def change_column_for_alter(table_name, column_name, type, **options)
|
688
720
|
td = create_table_definition(table_name)
|
689
|
-
cd = td.new_column_definition(column_name, type, options)
|
721
|
+
cd = td.new_column_definition(column_name, type, **options)
|
690
722
|
sqls = [schema_creation.accept(ChangeColumnDefinition.new(cd, column_name))]
|
691
723
|
sqls << Proc.new { change_column_comment(table_name, column_name, options[:comment]) } if options.key?(:comment)
|
692
724
|
sqls
|
@@ -711,20 +743,6 @@ module ActiveRecord
|
|
711
743
|
"ALTER COLUMN #{quote_column_name(column_name)} #{null ? 'DROP' : 'SET'} NOT NULL"
|
712
744
|
end
|
713
745
|
|
714
|
-
def add_timestamps_for_alter(table_name, options = {})
|
715
|
-
options[:null] = false if options[:null].nil?
|
716
|
-
|
717
|
-
if !options.key?(:precision) && supports_datetime_with_precision?
|
718
|
-
options[:precision] = 6
|
719
|
-
end
|
720
|
-
|
721
|
-
[add_column_for_alter(table_name, :created_at, :datetime, options), add_column_for_alter(table_name, :updated_at, :datetime, options)]
|
722
|
-
end
|
723
|
-
|
724
|
-
def remove_timestamps_for_alter(table_name, options = {})
|
725
|
-
[remove_column_for_alter(table_name, :updated_at), remove_column_for_alter(table_name, :created_at)]
|
726
|
-
end
|
727
|
-
|
728
746
|
def add_index_opclass(quoted_columns, **options)
|
729
747
|
opclasses = options_for_index_columns(options[:opclass])
|
730
748
|
quoted_columns.each do |name, column|
|
@@ -733,7 +751,7 @@ module ActiveRecord
|
|
733
751
|
end
|
734
752
|
|
735
753
|
def add_options_for_index_columns(quoted_columns, **options)
|
736
|
-
quoted_columns = add_index_opclass(quoted_columns, options)
|
754
|
+
quoted_columns = add_index_opclass(quoted_columns, **options)
|
737
755
|
super
|
738
756
|
end
|
739
757
|
|
@@ -7,6 +7,8 @@ module ActiveRecord
|
|
7
7
|
class TypeMetadata < DelegateClass(SqlTypeMetadata)
|
8
8
|
undef to_yaml if method_defined?(:to_yaml)
|
9
9
|
|
10
|
+
include Deduplicable
|
11
|
+
|
10
12
|
attr_reader :oid, :fmod
|
11
13
|
|
12
14
|
def initialize(type_metadata, oid: nil, fmod: nil)
|
@@ -29,6 +31,12 @@ module ActiveRecord
|
|
29
31
|
oid.hash ^
|
30
32
|
fmod.hash
|
31
33
|
end
|
34
|
+
|
35
|
+
private
|
36
|
+
def deduplicated
|
37
|
+
__setobj__(__getobj__.deduplicate)
|
38
|
+
super
|
39
|
+
end
|
32
40
|
end
|
33
41
|
end
|
34
42
|
PostgreSQLTypeMetadata = PostgreSQL::TypeMetadata
|
@@ -1,17 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
gem "pg", ">= 0.18", "< 2.0"
|
3
|
+
gem "pg", "~> 1.1"
|
5
4
|
require "pg"
|
6
5
|
|
7
|
-
|
8
|
-
class ::PG::Connection # :nodoc:
|
9
|
-
unless self.public_method_defined?(:async_exec_params)
|
10
|
-
remove_method :exec_params
|
11
|
-
alias exec_params async_exec
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
6
|
+
require "active_support/core_ext/object/try"
|
15
7
|
require "active_record/connection_adapters/abstract_adapter"
|
16
8
|
require "active_record/connection_adapters/statement_pool"
|
17
9
|
require "active_record/connection_adapters/postgresql/column"
|
@@ -31,9 +23,7 @@ module ActiveRecord
|
|
31
23
|
module ConnectionHandling # :nodoc:
|
32
24
|
# Establishes a connection to the database that's used by all Active Record objects
|
33
25
|
def postgresql_connection(config)
|
34
|
-
conn_params = config.symbolize_keys
|
35
|
-
|
36
|
-
conn_params.delete_if { |_, v| v.nil? }
|
26
|
+
conn_params = config.symbolize_keys.compact
|
37
27
|
|
38
28
|
# Map ActiveRecords param names to PGs.
|
39
29
|
conn_params[:user] = conn_params.delete(:username) if conn_params[:username]
|
@@ -43,19 +33,17 @@ module ActiveRecord
|
|
43
33
|
valid_conn_param_keys = PG::Connection.conndefaults_hash.keys + [:requiressl]
|
44
34
|
conn_params.slice!(*valid_conn_param_keys)
|
45
35
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
raise
|
53
|
-
end
|
36
|
+
ConnectionAdapters::PostgreSQLAdapter.new(
|
37
|
+
ConnectionAdapters::PostgreSQLAdapter.new_client(conn_params),
|
38
|
+
logger,
|
39
|
+
conn_params,
|
40
|
+
config,
|
41
|
+
)
|
54
42
|
end
|
55
43
|
end
|
56
44
|
|
57
45
|
module ConnectionAdapters
|
58
|
-
# The PostgreSQL adapter works with the native C (https://
|
46
|
+
# The PostgreSQL adapter works with the native C (https://github.com/ged/ruby-pg) driver.
|
59
47
|
#
|
60
48
|
# Options:
|
61
49
|
#
|
@@ -85,6 +73,18 @@ module ActiveRecord
|
|
85
73
|
class PostgreSQLAdapter < AbstractAdapter
|
86
74
|
ADAPTER_NAME = "PostgreSQL"
|
87
75
|
|
76
|
+
class << self
|
77
|
+
def new_client(conn_params)
|
78
|
+
PG.connect(**conn_params)
|
79
|
+
rescue ::PG::Error => error
|
80
|
+
if conn_params && conn_params[:dbname] && error.message.include?(conn_params[:dbname])
|
81
|
+
raise ActiveRecord::NoDatabaseError
|
82
|
+
else
|
83
|
+
raise ActiveRecord::ConnectionNotEstablished, error.message
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
88
|
##
|
89
89
|
# :singleton-method:
|
90
90
|
# PostgreSQL allows the creation of "unlogged" tables, which do not record
|
@@ -156,6 +156,10 @@ module ActiveRecord
|
|
156
156
|
true
|
157
157
|
end
|
158
158
|
|
159
|
+
def supports_partitioned_indexes?
|
160
|
+
database_version >= 110_000
|
161
|
+
end
|
162
|
+
|
159
163
|
def supports_partial_index?
|
160
164
|
true
|
161
165
|
end
|
@@ -172,6 +176,10 @@ module ActiveRecord
|
|
172
176
|
true
|
173
177
|
end
|
174
178
|
|
179
|
+
def supports_check_constraints?
|
180
|
+
true
|
181
|
+
end
|
182
|
+
|
175
183
|
def supports_validate_constraints?
|
176
184
|
true
|
177
185
|
end
|
@@ -219,11 +227,7 @@ module ActiveRecord
|
|
219
227
|
end
|
220
228
|
|
221
229
|
def next_key
|
222
|
-
"a#{@counter
|
223
|
-
end
|
224
|
-
|
225
|
-
def []=(sql, key)
|
226
|
-
super.tap { @counter += 1 }
|
230
|
+
"a#{@counter += 1}"
|
227
231
|
end
|
228
232
|
|
229
233
|
private
|
@@ -243,7 +247,7 @@ module ActiveRecord
|
|
243
247
|
def initialize(connection, logger, connection_parameters, config)
|
244
248
|
super(connection, logger, config)
|
245
249
|
|
246
|
-
@connection_parameters = connection_parameters
|
250
|
+
@connection_parameters = connection_parameters || {}
|
247
251
|
|
248
252
|
# @local_tz is initialized as nil to avoid warnings when connect tries to use it
|
249
253
|
@local_tz = nil
|
@@ -337,11 +341,6 @@ module ActiveRecord
|
|
337
341
|
true
|
338
342
|
end
|
339
343
|
|
340
|
-
def supports_ranges?
|
341
|
-
true
|
342
|
-
end
|
343
|
-
deprecate :supports_ranges?
|
344
|
-
|
345
344
|
def supports_materialized_views?
|
346
345
|
true
|
347
346
|
end
|
@@ -422,16 +421,6 @@ module ActiveRecord
|
|
422
421
|
@use_insert_returning
|
423
422
|
end
|
424
423
|
|
425
|
-
def column_name_for_operation(operation, node) # :nodoc:
|
426
|
-
OPERATION_ALIASES.fetch(operation) { operation.downcase }
|
427
|
-
end
|
428
|
-
|
429
|
-
OPERATION_ALIASES = { # :nodoc:
|
430
|
-
"maximum" => "max",
|
431
|
-
"minimum" => "min",
|
432
|
-
"average" => "avg",
|
433
|
-
}
|
434
|
-
|
435
424
|
# Returns the version of the connected PostgreSQL server.
|
436
425
|
def get_database_version # :nodoc:
|
437
426
|
@connection.server_version
|
@@ -449,6 +438,7 @@ module ActiveRecord
|
|
449
438
|
sql << " ON CONFLICT #{insert.conflict_target} DO NOTHING"
|
450
439
|
elsif insert.update_duplicates?
|
451
440
|
sql << " ON CONFLICT #{insert.conflict_target} DO UPDATE SET "
|
441
|
+
sql << insert.touch_model_timestamps_unless { |column| "#{insert.model.quoted_table_name}.#{column} IS NOT DISTINCT FROM excluded.#{column}" }
|
452
442
|
sql << insert.updatable_columns.map { |column| "#{column}=excluded.#{column}" }.join(",")
|
453
443
|
end
|
454
444
|
|
@@ -463,7 +453,6 @@ module ActiveRecord
|
|
463
453
|
end
|
464
454
|
|
465
455
|
private
|
466
|
-
|
467
456
|
# See https://www.postgresql.org/docs/current/static/errcodes-appendix.html
|
468
457
|
VALUE_LIMIT_VIOLATION = "22001"
|
469
458
|
NUMERIC_VALUE_OUT_OF_RANGE = "22003"
|
@@ -472,6 +461,7 @@ module ActiveRecord
|
|
472
461
|
UNIQUE_VIOLATION = "23505"
|
473
462
|
SERIALIZATION_FAILURE = "40001"
|
474
463
|
DEADLOCK_DETECTED = "40P01"
|
464
|
+
DUPLICATE_DATABASE = "42P04"
|
475
465
|
LOCK_NOT_AVAILABLE = "55P03"
|
476
466
|
QUERY_CANCELED = "57014"
|
477
467
|
|
@@ -479,6 +469,12 @@ module ActiveRecord
|
|
479
469
|
return exception unless exception.respond_to?(:result)
|
480
470
|
|
481
471
|
case exception.result.try(:error_field, PG::PG_DIAG_SQLSTATE)
|
472
|
+
when nil
|
473
|
+
if exception.message.match?(/connection is closed/i)
|
474
|
+
ConnectionNotEstablished.new(exception)
|
475
|
+
else
|
476
|
+
super
|
477
|
+
end
|
482
478
|
when UNIQUE_VIOLATION
|
483
479
|
RecordNotUnique.new(message, sql: sql, binds: binds)
|
484
480
|
when FOREIGN_KEY_VIOLATION
|
@@ -493,6 +489,8 @@ module ActiveRecord
|
|
493
489
|
SerializationFailure.new(message, sql: sql, binds: binds)
|
494
490
|
when DEADLOCK_DETECTED
|
495
491
|
Deadlocked.new(message, sql: sql, binds: binds)
|
492
|
+
when DUPLICATE_DATABASE
|
493
|
+
DatabaseAlreadyExists.new(message, sql: sql, binds: binds)
|
496
494
|
when LOCK_NOT_AVAILABLE
|
497
495
|
LockWaitTimeout.new(message, sql: sql, binds: binds)
|
498
496
|
when QUERY_CANCELED
|
@@ -544,7 +542,7 @@ module ActiveRecord
|
|
544
542
|
m.register_type "uuid", OID::Uuid.new
|
545
543
|
m.register_type "xml", OID::Xml.new
|
546
544
|
m.register_type "tsvector", OID::SpecializedString.new(:tsvector)
|
547
|
-
m.register_type "macaddr", OID::
|
545
|
+
m.register_type "macaddr", OID::Macaddr.new
|
548
546
|
m.register_type "citext", OID::SpecializedString.new(:citext)
|
549
547
|
m.register_type "ltree", OID::SpecializedString.new(:ltree)
|
550
548
|
m.register_type "line", OID::SpecializedString.new(:line)
|
@@ -554,11 +552,6 @@ module ActiveRecord
|
|
554
552
|
m.register_type "polygon", OID::SpecializedString.new(:polygon)
|
555
553
|
m.register_type "circle", OID::SpecializedString.new(:circle)
|
556
554
|
|
557
|
-
m.register_type "interval" do |_, _, sql_type|
|
558
|
-
precision = extract_precision(sql_type)
|
559
|
-
OID::SpecializedString.new(:interval, precision: precision)
|
560
|
-
end
|
561
|
-
|
562
555
|
register_class_with_precision m, "time", Type::Time
|
563
556
|
register_class_with_precision m, "timestamp", OID::DateTime
|
564
557
|
|
@@ -582,6 +575,11 @@ module ActiveRecord
|
|
582
575
|
end
|
583
576
|
end
|
584
577
|
|
578
|
+
m.register_type "interval" do |*args, sql_type|
|
579
|
+
precision = extract_precision(sql_type)
|
580
|
+
OID::Interval.new(precision: precision)
|
581
|
+
end
|
582
|
+
|
585
583
|
load_additional_types
|
586
584
|
end
|
587
585
|
|
@@ -630,7 +628,7 @@ module ActiveRecord
|
|
630
628
|
SQL
|
631
629
|
|
632
630
|
if oids
|
633
|
-
query += "WHERE t.oid
|
631
|
+
query += "WHERE t.oid IN (%s)" % oids.join(", ")
|
634
632
|
else
|
635
633
|
query += initializer.query_conditions_for_initial_load
|
636
634
|
end
|
@@ -647,20 +645,22 @@ module ActiveRecord
|
|
647
645
|
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
648
646
|
end
|
649
647
|
|
650
|
-
if without_prepared_statement?(binds)
|
651
|
-
result = exec_no_cache(sql, name, [])
|
652
|
-
elsif !prepare
|
648
|
+
if !prepare || without_prepared_statement?(binds)
|
653
649
|
result = exec_no_cache(sql, name, binds)
|
654
650
|
else
|
655
651
|
result = exec_cache(sql, name, binds)
|
656
652
|
end
|
657
|
-
|
658
|
-
|
653
|
+
begin
|
654
|
+
ret = yield result
|
655
|
+
ensure
|
656
|
+
result.clear
|
657
|
+
end
|
659
658
|
ret
|
660
659
|
end
|
661
660
|
|
662
661
|
def exec_no_cache(sql, name, binds)
|
663
662
|
materialize_transactions
|
663
|
+
mark_transaction_written_if_write(sql)
|
664
664
|
|
665
665
|
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
|
666
666
|
# made since we established the connection
|
@@ -676,6 +676,7 @@ module ActiveRecord
|
|
676
676
|
|
677
677
|
def exec_cache(sql, name, binds)
|
678
678
|
materialize_transactions
|
679
|
+
mark_transaction_written_if_write(sql)
|
679
680
|
update_typemap_for_default_timezone
|
680
681
|
|
681
682
|
stmt_key = prepare_statement(sql, binds)
|
@@ -711,11 +712,10 @@ module ActiveRecord
|
|
711
712
|
#
|
712
713
|
# Check here for more details:
|
713
714
|
# https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/cache/plancache.c#l573
|
714
|
-
CACHED_PLAN_HEURISTIC = "cached plan must not change result type"
|
715
715
|
def is_cached_plan_failure?(e)
|
716
716
|
pgerror = e.cause
|
717
|
-
|
718
|
-
|
717
|
+
pgerror.result.result_error_field(PG::PG_DIAG_SQLSTATE) == FEATURE_NOT_SUPPORTED &&
|
718
|
+
pgerror.result.result_error_field(PG::PG_DIAG_SOURCE_FUNCTION) == "RevalidateCachedQuery"
|
719
719
|
rescue
|
720
720
|
false
|
721
721
|
end
|
@@ -753,7 +753,7 @@ module ActiveRecord
|
|
753
753
|
# Connects to a PostgreSQL server and sets up the adapter depending on the
|
754
754
|
# connected server's characteristics.
|
755
755
|
def connect
|
756
|
-
@connection =
|
756
|
+
@connection = self.class.new_client(@connection_parameters)
|
757
757
|
configure_connection
|
758
758
|
add_pg_encoders
|
759
759
|
add_pg_decoders
|
@@ -783,6 +783,9 @@ module ActiveRecord
|
|
783
783
|
end
|
784
784
|
end
|
785
785
|
|
786
|
+
# Set interval output format to ISO 8601 for ease of parsing by ActiveSupport::Duration.parse
|
787
|
+
execute("SET intervalstyle = iso_8601", "SCHEMA")
|
788
|
+
|
786
789
|
# SET statements from :variables config hash
|
787
790
|
# https://www.postgresql.org/docs/current/static/sql-set.html
|
788
791
|
variables.map do |k, v|
|
@@ -894,15 +897,12 @@ module ActiveRecord
|
|
894
897
|
"oid" => PG::TextDecoder::Integer,
|
895
898
|
"float4" => PG::TextDecoder::Float,
|
896
899
|
"float8" => PG::TextDecoder::Float,
|
900
|
+
"numeric" => PG::TextDecoder::Numeric,
|
897
901
|
"bool" => PG::TextDecoder::Boolean,
|
902
|
+
"timestamp" => PG::TextDecoder::TimestampUtc,
|
903
|
+
"timestamptz" => PG::TextDecoder::TimestampWithTimeZone,
|
898
904
|
}
|
899
905
|
|
900
|
-
if defined?(PG::TextDecoder::TimestampUtc)
|
901
|
-
# Use native PG encoders available since pg-1.1
|
902
|
-
coders_by_name["timestamp"] = PG::TextDecoder::TimestampUtc
|
903
|
-
coders_by_name["timestamptz"] = PG::TextDecoder::TimestampWithTimeZone
|
904
|
-
end
|
905
|
-
|
906
906
|
known_coder_types = coders_by_name.keys.map { |n| quote(n) }
|
907
907
|
query = <<~SQL % known_coder_types.join(", ")
|
908
908
|
SELECT t.oid, t.typname
|
@@ -919,6 +919,11 @@ module ActiveRecord
|
|
919
919
|
coders.each { |coder| map.add_coder(coder) }
|
920
920
|
@connection.type_map_for_results = map
|
921
921
|
|
922
|
+
@type_map_for_results = PG::TypeMapByOid.new
|
923
|
+
@type_map_for_results.default_type_map = map
|
924
|
+
@type_map_for_results.add_coder(PG::TextDecoder::Bytea.new(oid: 17, name: "bytea"))
|
925
|
+
@type_map_for_results.add_coder(MoneyDecoder.new(oid: 790, name: "money"))
|
926
|
+
|
922
927
|
# extract timestamp decoder for use in update_typemap_for_default_timezone
|
923
928
|
@timestamp_decoder = coders.find { |coder| coder.name == "timestamp" }
|
924
929
|
update_typemap_for_default_timezone
|
@@ -929,6 +934,14 @@ module ActiveRecord
|
|
929
934
|
coder_class.new(oid: row["oid"].to_i, name: row["typname"])
|
930
935
|
end
|
931
936
|
|
937
|
+
class MoneyDecoder < PG::SimpleDecoder # :nodoc:
|
938
|
+
TYPE = OID::Money.new
|
939
|
+
|
940
|
+
def decode(value, tuple = nil, field = nil)
|
941
|
+
TYPE.deserialize(value)
|
942
|
+
end
|
943
|
+
end
|
944
|
+
|
932
945
|
ActiveRecord::Type.add_modifier({ array: true }, OID::Array, adapter: :postgresql)
|
933
946
|
ActiveRecord::Type.add_modifier({ range: true }, OID::Range, adapter: :postgresql)
|
934
947
|
ActiveRecord::Type.register(:bit, OID::Bit, adapter: :postgresql)
|
@@ -941,6 +954,7 @@ module ActiveRecord
|
|
941
954
|
ActiveRecord::Type.register(:enum, OID::Enum, adapter: :postgresql)
|
942
955
|
ActiveRecord::Type.register(:hstore, OID::Hstore, adapter: :postgresql)
|
943
956
|
ActiveRecord::Type.register(:inet, OID::Inet, adapter: :postgresql)
|
957
|
+
ActiveRecord::Type.register(:interval, OID::Interval, adapter: :postgresql)
|
944
958
|
ActiveRecord::Type.register(:jsonb, OID::Jsonb, adapter: :postgresql)
|
945
959
|
ActiveRecord::Type.register(:money, OID::Money, adapter: :postgresql)
|
946
960
|
ActiveRecord::Type.register(:point, OID::Point, adapter: :postgresql)
|