activerecord 5.0.7.2 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +844 -1944
- data/MIT-LICENSE +3 -1
- data/README.rdoc +9 -7
- data/examples/performance.rb +31 -29
- data/examples/simple.rb +5 -3
- data/lib/active_record/advisory_lock_base.rb +18 -0
- data/lib/active_record/aggregations.rb +249 -247
- data/lib/active_record/association_relation.rb +18 -14
- data/lib/active_record/associations/alias_tracker.rb +24 -34
- data/lib/active_record/associations/association.rb +113 -55
- data/lib/active_record/associations/association_scope.rb +102 -96
- data/lib/active_record/associations/belongs_to_association.rb +58 -42
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
- data/lib/active_record/associations/builder/association.rb +18 -25
- data/lib/active_record/associations/builder/belongs_to.rb +43 -54
- data/lib/active_record/associations/builder/collection_association.rb +7 -18
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +41 -62
- data/lib/active_record/associations/builder/has_many.rb +4 -0
- data/lib/active_record/associations/builder/has_one.rb +37 -1
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +93 -254
- data/lib/active_record/associations/collection_proxy.rb +159 -122
- data/lib/active_record/associations/foreign_association.rb +9 -0
- data/lib/active_record/associations/has_many_association.rb +23 -30
- data/lib/active_record/associations/has_many_through_association.rb +58 -44
- data/lib/active_record/associations/has_one_association.rb +59 -54
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +43 -85
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
- data/lib/active_record/associations/join_dependency.rb +152 -177
- data/lib/active_record/associations/preloader/association.rb +101 -97
- data/lib/active_record/associations/preloader/through_association.rb +77 -76
- data/lib/active_record/associations/preloader.rb +94 -103
- data/lib/active_record/associations/singular_association.rb +12 -45
- data/lib/active_record/associations/through_association.rb +27 -15
- data/lib/active_record/associations.rb +1603 -1592
- data/lib/active_record/attribute_assignment.rb +54 -61
- data/lib/active_record/attribute_decorators.rb +38 -17
- data/lib/active_record/attribute_methods/before_type_cast.rb +12 -8
- data/lib/active_record/attribute_methods/dirty.rb +179 -109
- data/lib/active_record/attribute_methods/primary_key.rb +85 -92
- data/lib/active_record/attribute_methods/query.rb +4 -3
- data/lib/active_record/attribute_methods/read.rb +20 -49
- data/lib/active_record/attribute_methods/serialization.rb +29 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -66
- data/lib/active_record/attribute_methods/write.rb +34 -33
- data/lib/active_record/attribute_methods.rb +66 -106
- data/lib/active_record/attributes.rb +38 -25
- data/lib/active_record/autosave_association.rb +58 -39
- data/lib/active_record/base.rb +27 -24
- data/lib/active_record/callbacks.rb +64 -35
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +34 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +558 -323
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +23 -5
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +215 -94
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +59 -35
- data/lib/active_record/connection_adapters/abstract/quoting.rb +128 -75
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +33 -28
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +233 -147
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +400 -213
- data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -79
- data/lib/active_record/connection_adapters/abstract_adapter.rb +373 -202
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +401 -562
- data/lib/active_record/connection_adapters/column.rb +41 -13
- data/lib/active_record/connection_adapters/connection_specification.rb +172 -139
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +11 -4
- data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +137 -49
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -23
- data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +58 -56
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +12 -13
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +48 -30
- data/lib/active_record/connection_adapters/postgresql/column.rb +19 -31
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -54
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -11
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +12 -2
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -18
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
- data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +30 -9
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -30
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +8 -4
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +24 -21
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +95 -35
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +20 -26
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +34 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +378 -308
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +26 -25
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -6
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +383 -275
- data/lib/active_record/connection_adapters/schema_cache.rb +46 -12
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +13 -8
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +72 -18
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +3 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +261 -267
- data/lib/active_record/connection_adapters/statement_pool.rb +9 -8
- data/lib/active_record/connection_handling.rb +143 -40
- data/lib/active_record/core.rb +207 -160
- data/lib/active_record/counter_cache.rb +60 -28
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +78 -0
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -87
- data/lib/active_record/enum.rb +67 -23
- data/lib/active_record/errors.rb +114 -18
- data/lib/active_record/explain.rb +4 -4
- data/lib/active_record/explain_registry.rb +3 -1
- data/lib/active_record/explain_subscriber.rb +9 -4
- data/lib/active_record/fixture_set/file.rb +13 -8
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +194 -504
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +150 -99
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +116 -25
- data/lib/active_record/internal_metadata.rb +16 -19
- data/lib/active_record/legacy_yaml_adapter.rb +4 -2
- data/lib/active_record/locking/optimistic.rb +85 -86
- data/lib/active_record/locking/pessimistic.rb +18 -6
- data/lib/active_record/log_subscriber.rb +48 -29
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
- data/lib/active_record/middleware/database_selector.rb +74 -0
- data/lib/active_record/migration/command_recorder.rb +134 -100
- data/lib/active_record/migration/compatibility.rb +174 -56
- data/lib/active_record/migration/join_table.rb +8 -7
- data/lib/active_record/migration.rb +369 -302
- data/lib/active_record/model_schema.rb +160 -127
- data/lib/active_record/nested_attributes.rb +213 -202
- data/lib/active_record/no_touching.rb +12 -3
- data/lib/active_record/null_relation.rb +12 -34
- data/lib/active_record/persistence.rb +446 -77
- data/lib/active_record/query_cache.rb +13 -12
- data/lib/active_record/querying.rb +37 -24
- data/lib/active_record/railtie.rb +128 -36
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +34 -33
- data/lib/active_record/railties/databases.rake +312 -177
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +214 -254
- data/lib/active_record/relation/batches/batch_enumerator.rb +3 -1
- data/lib/active_record/relation/batches.rb +98 -52
- data/lib/active_record/relation/calculations.rb +212 -173
- data/lib/active_record/relation/delegation.rb +73 -69
- data/lib/active_record/relation/finder_methods.rb +207 -247
- data/lib/active_record/relation/from_clause.rb +6 -8
- data/lib/active_record/relation/merger.rb +82 -61
- data/lib/active_record/relation/predicate_builder/array_handler.rb +20 -14
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/predicate_builder.rb +83 -105
- data/lib/active_record/relation/query_attribute.rb +33 -2
- data/lib/active_record/relation/query_methods.rb +488 -332
- data/lib/active_record/relation/record_fetch_warning.rb +5 -3
- data/lib/active_record/relation/spawn_methods.rb +8 -8
- data/lib/active_record/relation/where_clause.rb +111 -96
- data/lib/active_record/relation/where_clause_factory.rb +6 -11
- data/lib/active_record/relation.rb +443 -318
- data/lib/active_record/result.rb +69 -40
- data/lib/active_record/runtime_registry.rb +5 -3
- data/lib/active_record/sanitization.rb +83 -99
- data/lib/active_record/schema.rb +7 -14
- data/lib/active_record/schema_dumper.rb +71 -69
- data/lib/active_record/schema_migration.rb +16 -6
- data/lib/active_record/scoping/default.rb +92 -95
- data/lib/active_record/scoping/named.rb +51 -26
- data/lib/active_record/scoping.rb +20 -20
- data/lib/active_record/secure_token.rb +4 -2
- data/lib/active_record/serialization.rb +2 -0
- data/lib/active_record/statement_cache.rb +63 -28
- data/lib/active_record/store.rb +121 -41
- data/lib/active_record/suppressor.rb +6 -3
- data/lib/active_record/table_metadata.rb +39 -18
- data/lib/active_record/tasks/database_tasks.rb +271 -81
- data/lib/active_record/tasks/mysql_database_tasks.rb +54 -91
- data/lib/active_record/tasks/postgresql_database_tasks.rb +77 -47
- data/lib/active_record/tasks/sqlite_database_tasks.rb +33 -16
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +243 -0
- data/lib/active_record/timestamp.rb +70 -36
- data/lib/active_record/touch_later.rb +8 -6
- data/lib/active_record/transactions.rb +141 -157
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type/adapter_specific_registry.rb +44 -48
- data/lib/active_record/type/date.rb +2 -0
- data/lib/active_record/type/date_time.rb +2 -0
- data/lib/active_record/type/decimal_without_scale.rb +15 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
- data/lib/active_record/type/internal/timezone.rb +2 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +16 -9
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +12 -1
- data/lib/active_record/type/type_map.rb +14 -17
- data/lib/active_record/type/unsigned_integer.rb +16 -0
- data/lib/active_record/type.rb +23 -18
- data/lib/active_record/type_caster/connection.rb +17 -12
- data/lib/active_record/type_caster/map.rb +5 -4
- data/lib/active_record/type_caster.rb +4 -2
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +3 -2
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/presence.rb +4 -2
- data/lib/active_record/validations/uniqueness.rb +29 -42
- data/lib/active_record/validations.rb +7 -5
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +37 -22
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +45 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +68 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +256 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/depth_first.rb +203 -0
- data/lib/arel/visitors/dot.rb +296 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +156 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +158 -0
- data/lib/arel/visitors/oracle12.rb +65 -0
- data/lib/arel/visitors/postgresql.rb +109 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +888 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors/where_sql.rb +22 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +62 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -35
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +1 -1
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +4 -2
- data/lib/rails/generators/active_record/migration.rb +17 -3
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -30
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +138 -52
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -17
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -15
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -20
- data/lib/active_record/attribute/user_provided_default.rb +0 -28
- data/lib/active_record/attribute.rb +0 -213
- data/lib/active_record/attribute_mutation_tracker.rb +0 -70
- data/lib/active_record/attribute_set/builder.rb +0 -132
- data/lib/active_record/attribute_set.rb +0 -110
- data/lib/active_record/collection_cache_key.rb +0 -50
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
- data/lib/active_record/type/internal/abstract_json.rb +0 -33
- /data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,20 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Make sure we're using pg high enough for type casts and Ruby 2.2+ compatibility
|
2
4
|
gem "pg", ">= 0.18", "< 2.0"
|
3
|
-
require
|
5
|
+
require "pg"
|
6
|
+
|
7
|
+
# Use async_exec instead of exec_params on pg versions before 1.1
|
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
|
4
14
|
|
5
15
|
require "active_record/connection_adapters/abstract_adapter"
|
16
|
+
require "active_record/connection_adapters/statement_pool"
|
6
17
|
require "active_record/connection_adapters/postgresql/column"
|
7
18
|
require "active_record/connection_adapters/postgresql/database_statements"
|
8
19
|
require "active_record/connection_adapters/postgresql/explain_pretty_printer"
|
9
20
|
require "active_record/connection_adapters/postgresql/oid"
|
10
21
|
require "active_record/connection_adapters/postgresql/quoting"
|
11
22
|
require "active_record/connection_adapters/postgresql/referential_integrity"
|
23
|
+
require "active_record/connection_adapters/postgresql/schema_creation"
|
12
24
|
require "active_record/connection_adapters/postgresql/schema_definitions"
|
13
25
|
require "active_record/connection_adapters/postgresql/schema_dumper"
|
14
26
|
require "active_record/connection_adapters/postgresql/schema_statements"
|
15
27
|
require "active_record/connection_adapters/postgresql/type_metadata"
|
16
28
|
require "active_record/connection_adapters/postgresql/utils"
|
17
|
-
require "active_record/connection_adapters/statement_pool"
|
18
29
|
|
19
30
|
module ActiveRecord
|
20
31
|
module ConnectionHandling # :nodoc:
|
@@ -32,9 +43,14 @@ module ActiveRecord
|
|
32
43
|
valid_conn_param_keys = PG::Connection.conndefaults_hash.keys + [:requiressl]
|
33
44
|
conn_params.slice!(*valid_conn_param_keys)
|
34
45
|
|
35
|
-
|
36
|
-
|
37
|
-
|
46
|
+
conn = PG.connect(conn_params)
|
47
|
+
ConnectionAdapters::PostgreSQLAdapter.new(conn, logger, conn_params, config)
|
48
|
+
rescue ::PG::Error => error
|
49
|
+
if error.message.include?(conn_params[:dbname])
|
50
|
+
raise ActiveRecord::NoDatabaseError
|
51
|
+
else
|
52
|
+
raise
|
53
|
+
end
|
38
54
|
end
|
39
55
|
end
|
40
56
|
|
@@ -61,19 +77,32 @@ module ActiveRecord
|
|
61
77
|
# defaults to true.
|
62
78
|
#
|
63
79
|
# Any further options are used as connection parameters to libpq. See
|
64
|
-
#
|
80
|
+
# https://www.postgresql.org/docs/current/static/libpq-connect.html for the
|
65
81
|
# list of parameters.
|
66
82
|
#
|
67
83
|
# In addition, default connection parameters of libpq can be set per environment variables.
|
68
|
-
# See
|
84
|
+
# See https://www.postgresql.org/docs/current/static/libpq-envars.html .
|
69
85
|
class PostgreSQLAdapter < AbstractAdapter
|
70
|
-
ADAPTER_NAME =
|
86
|
+
ADAPTER_NAME = "PostgreSQL"
|
87
|
+
|
88
|
+
##
|
89
|
+
# :singleton-method:
|
90
|
+
# PostgreSQL allows the creation of "unlogged" tables, which do not record
|
91
|
+
# data in the PostgreSQL Write-Ahead Log. This can make the tables faster,
|
92
|
+
# but significantly increases the risk of data loss if the database
|
93
|
+
# crashes. As a result, this should not be used in production
|
94
|
+
# environments. If you would like all created tables to be unlogged in
|
95
|
+
# the test environment you can add the following line to your test.rb
|
96
|
+
# file:
|
97
|
+
#
|
98
|
+
# ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.create_unlogged_tables = true
|
99
|
+
class_attribute :create_unlogged_tables, default: false
|
71
100
|
|
72
101
|
NATIVE_DATABASE_TYPES = {
|
73
|
-
primary_key: "
|
102
|
+
primary_key: "bigserial primary key",
|
74
103
|
string: { name: "character varying" },
|
75
104
|
text: { name: "text" },
|
76
|
-
integer: { name: "integer" },
|
105
|
+
integer: { name: "integer", limit: 4 },
|
77
106
|
float: { name: "float" },
|
78
107
|
decimal: { name: "decimal" },
|
79
108
|
datetime: { name: "timestamp" },
|
@@ -108,6 +137,8 @@ module ActiveRecord
|
|
108
137
|
bit: { name: "bit" },
|
109
138
|
bit_varying: { name: "bit varying" },
|
110
139
|
money: { name: "money" },
|
140
|
+
interval: { name: "interval" },
|
141
|
+
oid: { name: "oid" },
|
111
142
|
}
|
112
143
|
|
113
144
|
OID = PostgreSQL::OID #:nodoc:
|
@@ -116,19 +147,8 @@ module ActiveRecord
|
|
116
147
|
include PostgreSQL::ReferentialIntegrity
|
117
148
|
include PostgreSQL::SchemaStatements
|
118
149
|
include PostgreSQL::DatabaseStatements
|
119
|
-
include PostgreSQL::ColumnDumper
|
120
|
-
|
121
|
-
def schema_creation # :nodoc:
|
122
|
-
PostgreSQL::SchemaCreation.new self
|
123
|
-
end
|
124
150
|
|
125
|
-
def
|
126
|
-
Arel::Visitors::PostgreSQL.new(self)
|
127
|
-
end
|
128
|
-
|
129
|
-
# Returns true, since this connection adapter supports prepared statement
|
130
|
-
# caching.
|
131
|
-
def supports_statement_cache?
|
151
|
+
def supports_bulk_alter?
|
132
152
|
true
|
133
153
|
end
|
134
154
|
|
@@ -136,6 +156,10 @@ module ActiveRecord
|
|
136
156
|
true
|
137
157
|
end
|
138
158
|
|
159
|
+
def supports_partitioned_indexes?
|
160
|
+
database_version >= 110_000
|
161
|
+
end
|
162
|
+
|
139
163
|
def supports_partial_index?
|
140
164
|
true
|
141
165
|
end
|
@@ -152,6 +176,10 @@ module ActiveRecord
|
|
152
176
|
true
|
153
177
|
end
|
154
178
|
|
179
|
+
def supports_validate_constraints?
|
180
|
+
true
|
181
|
+
end
|
182
|
+
|
155
183
|
def supports_views?
|
156
184
|
true
|
157
185
|
end
|
@@ -161,7 +189,7 @@ module ActiveRecord
|
|
161
189
|
end
|
162
190
|
|
163
191
|
def supports_json?
|
164
|
-
|
192
|
+
true
|
165
193
|
end
|
166
194
|
|
167
195
|
def supports_comments?
|
@@ -172,11 +200,22 @@ module ActiveRecord
|
|
172
200
|
true
|
173
201
|
end
|
174
202
|
|
203
|
+
def supports_insert_returning?
|
204
|
+
true
|
205
|
+
end
|
206
|
+
|
207
|
+
def supports_insert_on_conflict?
|
208
|
+
database_version >= 90500
|
209
|
+
end
|
210
|
+
alias supports_insert_on_duplicate_skip? supports_insert_on_conflict?
|
211
|
+
alias supports_insert_on_duplicate_update? supports_insert_on_conflict?
|
212
|
+
alias supports_insert_conflict_target? supports_insert_on_conflict?
|
213
|
+
|
175
214
|
def index_algorithms
|
176
|
-
{ concurrently:
|
215
|
+
{ concurrently: "CONCURRENTLY" }
|
177
216
|
end
|
178
217
|
|
179
|
-
class StatementPool < ConnectionAdapters::StatementPool
|
218
|
+
class StatementPool < ConnectionAdapters::StatementPool # :nodoc:
|
180
219
|
def initialize(connection, max)
|
181
220
|
super(max)
|
182
221
|
@connection = connection
|
@@ -192,9 +231,9 @@ module ActiveRecord
|
|
192
231
|
end
|
193
232
|
|
194
233
|
private
|
195
|
-
|
196
234
|
def dealloc(key)
|
197
235
|
@connection.query "DEALLOCATE #{key}" if connection_active?
|
236
|
+
rescue PG::Error
|
198
237
|
end
|
199
238
|
|
200
239
|
def connection_active?
|
@@ -214,35 +253,27 @@ module ActiveRecord
|
|
214
253
|
@local_tz = nil
|
215
254
|
@max_identifier_length = nil
|
216
255
|
|
217
|
-
|
256
|
+
configure_connection
|
218
257
|
add_pg_encoders
|
219
|
-
@statements = StatementPool.new @connection,
|
220
|
-
self.class.type_cast_config_to_integer(config[:statement_limit])
|
221
|
-
|
222
|
-
if postgresql_version < 90100
|
223
|
-
raise "Your version of PostgreSQL (#{postgresql_version}) is too old. Active Record supports PostgreSQL >= 9.1."
|
224
|
-
end
|
225
|
-
|
226
258
|
add_pg_decoders
|
227
259
|
|
228
260
|
@type_map = Type::HashLookupTypeMap.new
|
229
|
-
initialize_type_map
|
230
|
-
@local_tz = execute(
|
261
|
+
initialize_type_map
|
262
|
+
@local_tz = execute("SHOW TIME ZONE", "SCHEMA").first["TimeZone"]
|
231
263
|
@use_insert_returning = @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
|
232
264
|
end
|
233
265
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
def truncate(table_name, name = nil)
|
240
|
-
exec_query "TRUNCATE TABLE #{quote_table_name(table_name)}", name, []
|
266
|
+
def self.database_exists?(config)
|
267
|
+
!!ActiveRecord::Base.postgresql_connection(config)
|
268
|
+
rescue ActiveRecord::NoDatabaseError
|
269
|
+
false
|
241
270
|
end
|
242
271
|
|
243
272
|
# Is this connection alive and ready for queries?
|
244
273
|
def active?
|
245
|
-
@
|
274
|
+
@lock.synchronize do
|
275
|
+
@connection.query "SELECT 1"
|
276
|
+
end
|
246
277
|
true
|
247
278
|
rescue PG::Error
|
248
279
|
false
|
@@ -250,44 +281,48 @@ module ActiveRecord
|
|
250
281
|
|
251
282
|
# Close then reopen the connection.
|
252
283
|
def reconnect!
|
253
|
-
|
254
|
-
|
255
|
-
|
284
|
+
@lock.synchronize do
|
285
|
+
super
|
286
|
+
@connection.reset
|
287
|
+
configure_connection
|
288
|
+
rescue PG::ConnectionBad
|
289
|
+
connect
|
290
|
+
end
|
256
291
|
end
|
257
292
|
|
258
293
|
def reset!
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
@connection.
|
294
|
+
@lock.synchronize do
|
295
|
+
clear_cache!
|
296
|
+
reset_transaction
|
297
|
+
unless @connection.transaction_status == ::PG::PQTRANS_IDLE
|
298
|
+
@connection.query "ROLLBACK"
|
299
|
+
end
|
300
|
+
@connection.query "DISCARD ALL"
|
301
|
+
configure_connection
|
263
302
|
end
|
264
|
-
@connection.query 'DISCARD ALL'
|
265
|
-
configure_connection
|
266
303
|
end
|
267
304
|
|
268
305
|
# Disconnects from the database if already connected. Otherwise, this
|
269
306
|
# method does nothing.
|
270
307
|
def disconnect!
|
308
|
+
@lock.synchronize do
|
309
|
+
super
|
310
|
+
@connection.close rescue nil
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
def discard! # :nodoc:
|
271
315
|
super
|
272
|
-
@connection.
|
316
|
+
@connection.socket_io.reopen(IO::NULL) rescue nil
|
317
|
+
@connection = nil
|
273
318
|
end
|
274
319
|
|
275
320
|
def native_database_types #:nodoc:
|
276
321
|
NATIVE_DATABASE_TYPES
|
277
322
|
end
|
278
323
|
|
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
324
|
def set_standard_conforming_strings
|
290
|
-
execute(
|
325
|
+
execute("SET standard_conforming_strings = on", "SCHEMA")
|
291
326
|
end
|
292
327
|
|
293
328
|
def supports_ddl_transactions?
|
@@ -306,27 +341,50 @@ module ActiveRecord
|
|
306
341
|
true
|
307
342
|
end
|
308
343
|
|
309
|
-
# Range datatypes weren't introduced until PostgreSQL 9.2
|
310
344
|
def supports_ranges?
|
311
|
-
|
345
|
+
true
|
312
346
|
end
|
347
|
+
deprecate :supports_ranges?
|
313
348
|
|
314
349
|
def supports_materialized_views?
|
315
|
-
|
350
|
+
true
|
351
|
+
end
|
352
|
+
|
353
|
+
def supports_foreign_tables?
|
354
|
+
true
|
355
|
+
end
|
356
|
+
|
357
|
+
def supports_pgcrypto_uuid?
|
358
|
+
database_version >= 90400
|
359
|
+
end
|
360
|
+
|
361
|
+
def supports_optimizer_hints?
|
362
|
+
unless defined?(@has_pg_hint_plan)
|
363
|
+
@has_pg_hint_plan = extension_available?("pg_hint_plan")
|
364
|
+
end
|
365
|
+
@has_pg_hint_plan
|
366
|
+
end
|
367
|
+
|
368
|
+
def supports_common_table_expressions?
|
369
|
+
true
|
370
|
+
end
|
371
|
+
|
372
|
+
def supports_lazy_transactions?
|
373
|
+
true
|
316
374
|
end
|
317
375
|
|
318
376
|
def get_advisory_lock(lock_id) # :nodoc:
|
319
377
|
unless lock_id.is_a?(Integer) && lock_id.bit_length <= 63
|
320
|
-
raise(ArgumentError, "
|
378
|
+
raise(ArgumentError, "PostgreSQL requires advisory lock ids to be a signed 64 bit integer")
|
321
379
|
end
|
322
|
-
|
380
|
+
query_value("SELECT pg_try_advisory_lock(#{lock_id})")
|
323
381
|
end
|
324
382
|
|
325
383
|
def release_advisory_lock(lock_id) # :nodoc:
|
326
384
|
unless lock_id.is_a?(Integer) && lock_id.bit_length <= 63
|
327
|
-
raise(ArgumentError, "
|
385
|
+
raise(ArgumentError, "PostgreSQL requires advisory lock ids to be a signed 64 bit integer")
|
328
386
|
end
|
329
|
-
|
387
|
+
query_value("SELECT pg_advisory_unlock(#{lock_id})")
|
330
388
|
end
|
331
389
|
|
332
390
|
def enable_extension(name)
|
@@ -341,52 +399,33 @@ module ActiveRecord
|
|
341
399
|
}
|
342
400
|
end
|
343
401
|
|
402
|
+
def extension_available?(name)
|
403
|
+
query_value("SELECT true FROM pg_available_extensions WHERE name = #{quote(name)}", "SCHEMA")
|
404
|
+
end
|
405
|
+
|
344
406
|
def extension_enabled?(name)
|
345
|
-
|
346
|
-
res = exec_query "SELECT EXISTS(SELECT * FROM pg_available_extensions WHERE name = '#{name}' AND installed_version IS NOT NULL) as enabled",
|
347
|
-
'SCHEMA'
|
348
|
-
res.cast_values.first
|
349
|
-
end
|
407
|
+
query_value("SELECT installed_version IS NOT NULL FROM pg_available_extensions WHERE name = #{quote(name)}", "SCHEMA")
|
350
408
|
end
|
351
409
|
|
352
410
|
def extensions
|
353
|
-
|
354
|
-
exec_query("SELECT extname from pg_extension", "SCHEMA").cast_values
|
355
|
-
else
|
356
|
-
super
|
357
|
-
end
|
411
|
+
exec_query("SELECT extname FROM pg_extension", "SCHEMA").cast_values
|
358
412
|
end
|
359
413
|
|
360
414
|
# Returns the configured supported identifier length supported by PostgreSQL
|
361
415
|
def max_identifier_length
|
362
|
-
@max_identifier_length ||=
|
416
|
+
@max_identifier_length ||= query_value("SHOW max_identifier_length", "SCHEMA").to_i
|
363
417
|
end
|
364
|
-
alias table_alias_length max_identifier_length
|
365
|
-
alias index_name_length max_identifier_length
|
366
418
|
|
367
419
|
# Set the authorized user for this session
|
368
420
|
def session_auth=(user)
|
369
421
|
clear_cache!
|
370
|
-
|
422
|
+
execute("SET SESSION AUTHORIZATION #{user}")
|
371
423
|
end
|
372
424
|
|
373
425
|
def use_insert_returning?
|
374
426
|
@use_insert_returning
|
375
427
|
end
|
376
428
|
|
377
|
-
def valid_type?(type)
|
378
|
-
!native_database_types[type].nil?
|
379
|
-
end
|
380
|
-
|
381
|
-
def update_table_definition(table_name, base) #:nodoc:
|
382
|
-
PostgreSQL::Table.new(table_name, base)
|
383
|
-
end
|
384
|
-
|
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
429
|
def column_name_for_operation(operation, node) # :nodoc:
|
391
430
|
OPERATION_ALIASES.fetch(operation) { operation.downcase }
|
392
431
|
end
|
@@ -398,93 +437,135 @@ module ActiveRecord
|
|
398
437
|
}
|
399
438
|
|
400
439
|
# Returns the version of the connected PostgreSQL server.
|
401
|
-
def
|
440
|
+
def get_database_version # :nodoc:
|
402
441
|
@connection.server_version
|
403
442
|
end
|
443
|
+
alias :postgresql_version :database_version
|
444
|
+
|
445
|
+
def default_index_type?(index) # :nodoc:
|
446
|
+
index.using == :btree || super
|
447
|
+
end
|
404
448
|
|
405
|
-
|
449
|
+
def build_insert_sql(insert) # :nodoc:
|
450
|
+
sql = +"INSERT #{insert.into} #{insert.values_list}"
|
406
451
|
|
407
|
-
|
452
|
+
if insert.skip_duplicates?
|
453
|
+
sql << " ON CONFLICT #{insert.conflict_target} DO NOTHING"
|
454
|
+
elsif insert.update_duplicates?
|
455
|
+
sql << " ON CONFLICT #{insert.conflict_target} DO UPDATE SET "
|
456
|
+
sql << insert.updatable_columns.map { |column| "#{column}=excluded.#{column}" }.join(",")
|
457
|
+
end
|
458
|
+
|
459
|
+
sql << " RETURNING #{insert.returning}" if insert.returning
|
460
|
+
sql
|
461
|
+
end
|
462
|
+
|
463
|
+
def check_version # :nodoc:
|
464
|
+
if database_version < 90300
|
465
|
+
raise "Your version of PostgreSQL (#{database_version}) is too old. Active Record supports PostgreSQL >= 9.3."
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
469
|
+
private
|
470
|
+
# See https://www.postgresql.org/docs/current/static/errcodes-appendix.html
|
408
471
|
VALUE_LIMIT_VIOLATION = "22001"
|
472
|
+
NUMERIC_VALUE_OUT_OF_RANGE = "22003"
|
473
|
+
NOT_NULL_VIOLATION = "23502"
|
409
474
|
FOREIGN_KEY_VIOLATION = "23503"
|
410
475
|
UNIQUE_VIOLATION = "23505"
|
476
|
+
SERIALIZATION_FAILURE = "40001"
|
477
|
+
DEADLOCK_DETECTED = "40P01"
|
478
|
+
LOCK_NOT_AVAILABLE = "55P03"
|
479
|
+
QUERY_CANCELED = "57014"
|
411
480
|
|
412
|
-
def translate_exception(exception, message)
|
481
|
+
def translate_exception(exception, message:, sql:, binds:)
|
413
482
|
return exception unless exception.respond_to?(:result)
|
414
483
|
|
415
484
|
case exception.result.try(:error_field, PG::PG_DIAG_SQLSTATE)
|
416
485
|
when UNIQUE_VIOLATION
|
417
|
-
RecordNotUnique.new(message)
|
486
|
+
RecordNotUnique.new(message, sql: sql, binds: binds)
|
418
487
|
when FOREIGN_KEY_VIOLATION
|
419
|
-
InvalidForeignKey.new(message)
|
488
|
+
InvalidForeignKey.new(message, sql: sql, binds: binds)
|
420
489
|
when VALUE_LIMIT_VIOLATION
|
421
|
-
ValueTooLong.new(message)
|
490
|
+
ValueTooLong.new(message, sql: sql, binds: binds)
|
491
|
+
when NUMERIC_VALUE_OUT_OF_RANGE
|
492
|
+
RangeError.new(message, sql: sql, binds: binds)
|
493
|
+
when NOT_NULL_VIOLATION
|
494
|
+
NotNullViolation.new(message, sql: sql, binds: binds)
|
495
|
+
when SERIALIZATION_FAILURE
|
496
|
+
SerializationFailure.new(message, sql: sql, binds: binds)
|
497
|
+
when DEADLOCK_DETECTED
|
498
|
+
Deadlocked.new(message, sql: sql, binds: binds)
|
499
|
+
when LOCK_NOT_AVAILABLE
|
500
|
+
LockWaitTimeout.new(message, sql: sql, binds: binds)
|
501
|
+
when QUERY_CANCELED
|
502
|
+
QueryCanceled.new(message, sql: sql, binds: binds)
|
422
503
|
else
|
423
504
|
super
|
424
505
|
end
|
425
506
|
end
|
426
507
|
|
427
|
-
|
428
|
-
|
429
|
-
def get_oid_type(oid, fmod, column_name, sql_type = '') # :nodoc:
|
508
|
+
def get_oid_type(oid, fmod, column_name, sql_type = "")
|
430
509
|
if !type_map.key?(oid)
|
431
|
-
load_additional_types(
|
510
|
+
load_additional_types([oid])
|
432
511
|
end
|
433
512
|
|
434
513
|
type_map.fetch(oid, fmod, sql_type) {
|
435
514
|
warn "unknown OID #{oid}: failed to recognize type of '#{column_name}'. It will be treated as String."
|
436
|
-
Type
|
515
|
+
Type.default_value.tap do |cast_type|
|
437
516
|
type_map.register_type(oid, cast_type)
|
438
517
|
end
|
439
518
|
}
|
440
519
|
end
|
441
520
|
|
442
|
-
def initialize_type_map(m
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
m.
|
447
|
-
m.register_type
|
448
|
-
m.alias_type
|
449
|
-
m.register_type
|
450
|
-
register_class_with_limit m,
|
451
|
-
m.alias_type
|
452
|
-
m.alias_type
|
453
|
-
m.alias_type
|
454
|
-
m.register_type
|
455
|
-
register_class_with_limit m,
|
456
|
-
register_class_with_limit m,
|
457
|
-
m.alias_type
|
458
|
-
m.register_type
|
459
|
-
|
460
|
-
m.register_type
|
461
|
-
m.register_type
|
462
|
-
m.register_type
|
463
|
-
m.register_type
|
464
|
-
m.register_type
|
465
|
-
m.register_type
|
466
|
-
m.register_type
|
467
|
-
m.register_type
|
468
|
-
m.register_type
|
469
|
-
m.register_type
|
470
|
-
m.register_type
|
471
|
-
m.register_type
|
472
|
-
m.register_type
|
473
|
-
m.register_type
|
474
|
-
m.register_type
|
475
|
-
m.register_type
|
476
|
-
m.register_type
|
477
|
-
m.register_type
|
478
|
-
m.register_type
|
479
|
-
m.register_type
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
m
|
521
|
+
def initialize_type_map(m = type_map)
|
522
|
+
m.register_type "int2", Type::Integer.new(limit: 2)
|
523
|
+
m.register_type "int4", Type::Integer.new(limit: 4)
|
524
|
+
m.register_type "int8", Type::Integer.new(limit: 8)
|
525
|
+
m.register_type "oid", OID::Oid.new
|
526
|
+
m.register_type "float4", Type::Float.new
|
527
|
+
m.alias_type "float8", "float4"
|
528
|
+
m.register_type "text", Type::Text.new
|
529
|
+
register_class_with_limit m, "varchar", Type::String
|
530
|
+
m.alias_type "char", "varchar"
|
531
|
+
m.alias_type "name", "varchar"
|
532
|
+
m.alias_type "bpchar", "varchar"
|
533
|
+
m.register_type "bool", Type::Boolean.new
|
534
|
+
register_class_with_limit m, "bit", OID::Bit
|
535
|
+
register_class_with_limit m, "varbit", OID::BitVarying
|
536
|
+
m.alias_type "timestamptz", "timestamp"
|
537
|
+
m.register_type "date", OID::Date.new
|
538
|
+
|
539
|
+
m.register_type "money", OID::Money.new
|
540
|
+
m.register_type "bytea", OID::Bytea.new
|
541
|
+
m.register_type "point", OID::Point.new
|
542
|
+
m.register_type "hstore", OID::Hstore.new
|
543
|
+
m.register_type "json", Type::Json.new
|
544
|
+
m.register_type "jsonb", OID::Jsonb.new
|
545
|
+
m.register_type "cidr", OID::Cidr.new
|
546
|
+
m.register_type "inet", OID::Inet.new
|
547
|
+
m.register_type "uuid", OID::Uuid.new
|
548
|
+
m.register_type "xml", OID::Xml.new
|
549
|
+
m.register_type "tsvector", OID::SpecializedString.new(:tsvector)
|
550
|
+
m.register_type "macaddr", OID::SpecializedString.new(:macaddr)
|
551
|
+
m.register_type "citext", OID::SpecializedString.new(:citext)
|
552
|
+
m.register_type "ltree", OID::SpecializedString.new(:ltree)
|
553
|
+
m.register_type "line", OID::SpecializedString.new(:line)
|
554
|
+
m.register_type "lseg", OID::SpecializedString.new(:lseg)
|
555
|
+
m.register_type "box", OID::SpecializedString.new(:box)
|
556
|
+
m.register_type "path", OID::SpecializedString.new(:path)
|
557
|
+
m.register_type "polygon", OID::SpecializedString.new(:polygon)
|
558
|
+
m.register_type "circle", OID::SpecializedString.new(:circle)
|
559
|
+
|
560
|
+
m.register_type "interval" do |_, _, sql_type|
|
561
|
+
precision = extract_precision(sql_type)
|
562
|
+
OID::SpecializedString.new(:interval, precision: precision)
|
563
|
+
end
|
564
|
+
|
565
|
+
register_class_with_precision m, "time", Type::Time
|
566
|
+
register_class_with_precision m, "timestamp", OID::DateTime
|
567
|
+
|
568
|
+
m.register_type "numeric" do |_, fmod, sql_type|
|
488
569
|
precision = extract_precision(sql_type)
|
489
570
|
scale = extract_scale(sql_type)
|
490
571
|
|
@@ -504,78 +585,60 @@ module ActiveRecord
|
|
504
585
|
end
|
505
586
|
end
|
506
587
|
|
507
|
-
load_additional_types
|
508
|
-
end
|
509
|
-
|
510
|
-
def extract_limit(sql_type) # :nodoc:
|
511
|
-
case sql_type
|
512
|
-
when /^bigint/i, /^int8/i
|
513
|
-
8
|
514
|
-
when /^smallint/i
|
515
|
-
2
|
516
|
-
else
|
517
|
-
super
|
518
|
-
end
|
588
|
+
load_additional_types
|
519
589
|
end
|
520
590
|
|
521
591
|
# Extracts the value from a PostgreSQL column default definition.
|
522
|
-
def extract_value_from_default(default)
|
592
|
+
def extract_value_from_default(default)
|
523
593
|
case default
|
524
594
|
# Quoted types
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
595
|
+
when /\A[\(B]?'(.*)'.*::"?([\w. ]+)"?(?:\[\])?\z/m
|
596
|
+
# The default 'now'::date is CURRENT_DATE
|
597
|
+
if $1 == "now" && $2 == "date"
|
598
|
+
nil
|
599
|
+
else
|
600
|
+
$1.gsub("''", "'")
|
601
|
+
end
|
532
602
|
# Boolean types
|
533
|
-
|
534
|
-
|
603
|
+
when "true", "false"
|
604
|
+
default
|
535
605
|
# Numeric types
|
536
|
-
|
537
|
-
|
606
|
+
when /\A\(?(-?\d+(\.\d*)?)\)?(::bigint)?\z/
|
607
|
+
$1
|
538
608
|
# Object identifier types
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
609
|
+
when /\A-?\d+\z/
|
610
|
+
$1
|
611
|
+
else
|
612
|
+
# Anything else is blank, some user type, or some function
|
613
|
+
# and we can't know the value of that, so return nil.
|
614
|
+
nil
|
545
615
|
end
|
546
616
|
end
|
547
617
|
|
548
|
-
def extract_default_function(default_value, default)
|
618
|
+
def extract_default_function(default_value, default)
|
549
619
|
default if has_default_function?(default_value, default)
|
550
620
|
end
|
551
621
|
|
552
|
-
def has_default_function?(default_value, default)
|
553
|
-
!default_value &&
|
622
|
+
def has_default_function?(default_value, default)
|
623
|
+
!default_value && %r{\w+\(.*\)|\(.*\)::\w+|CURRENT_DATE|CURRENT_TIMESTAMP}.match?(default)
|
554
624
|
end
|
555
625
|
|
556
|
-
def load_additional_types(
|
626
|
+
def load_additional_types(oids = nil)
|
557
627
|
initializer = OID::TypeMapInitializer.new(type_map)
|
558
628
|
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
SQL
|
565
|
-
else
|
566
|
-
query = <<-SQL
|
567
|
-
SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, t.typtype, t.typbasetype
|
568
|
-
FROM pg_type as t
|
569
|
-
SQL
|
570
|
-
end
|
629
|
+
query = <<~SQL
|
630
|
+
SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
|
631
|
+
FROM pg_type as t
|
632
|
+
LEFT JOIN pg_range as r ON oid = rngtypid
|
633
|
+
SQL
|
571
634
|
|
572
635
|
if oids
|
573
|
-
query += "WHERE t.oid
|
636
|
+
query += "WHERE t.oid IN (%s)" % oids.join(", ")
|
574
637
|
else
|
575
|
-
query += initializer.query_conditions_for_initial_load
|
638
|
+
query += initializer.query_conditions_for_initial_load
|
576
639
|
end
|
577
640
|
|
578
|
-
execute_and_clear(query,
|
641
|
+
execute_and_clear(query, "SCHEMA", []) do |records|
|
579
642
|
initializer.run(records)
|
580
643
|
end
|
581
644
|
end
|
@@ -583,6 +646,10 @@ module ActiveRecord
|
|
583
646
|
FEATURE_NOT_SUPPORTED = "0A000" #:nodoc:
|
584
647
|
|
585
648
|
def execute_and_clear(sql, name, binds, prepare: false)
|
649
|
+
if preventing_writes? && write_query?(sql)
|
650
|
+
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
651
|
+
end
|
652
|
+
|
586
653
|
if without_prepared_statement?(binds)
|
587
654
|
result = exec_no_cache(sql, name, [])
|
588
655
|
elsif !prepare
|
@@ -596,16 +663,31 @@ module ActiveRecord
|
|
596
663
|
end
|
597
664
|
|
598
665
|
def exec_no_cache(sql, name, binds)
|
666
|
+
materialize_transactions
|
667
|
+
|
668
|
+
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
|
669
|
+
# made since we established the connection
|
670
|
+
update_typemap_for_default_timezone
|
671
|
+
|
599
672
|
type_casted_binds = type_casted_binds(binds)
|
600
|
-
log(sql, name, binds, type_casted_binds)
|
673
|
+
log(sql, name, binds, type_casted_binds) do
|
674
|
+
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
675
|
+
@connection.exec_params(sql, type_casted_binds)
|
676
|
+
end
|
677
|
+
end
|
601
678
|
end
|
602
679
|
|
603
680
|
def exec_cache(sql, name, binds)
|
604
|
-
|
681
|
+
materialize_transactions
|
682
|
+
update_typemap_for_default_timezone
|
683
|
+
|
684
|
+
stmt_key = prepare_statement(sql, binds)
|
605
685
|
type_casted_binds = type_casted_binds(binds)
|
606
686
|
|
607
687
|
log(sql, name, binds, type_casted_binds, stmt_key) do
|
608
|
-
|
688
|
+
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
689
|
+
@connection.exec_prepared(stmt_key, type_casted_binds)
|
690
|
+
end
|
609
691
|
end
|
610
692
|
rescue ActiveRecord::StatementInvalid => e
|
611
693
|
raise unless is_cached_plan_failure?(e)
|
@@ -615,8 +697,10 @@ module ActiveRecord
|
|
615
697
|
if in_transaction?
|
616
698
|
raise ActiveRecord::PreparedStatementCacheExpired.new(e.cause.message)
|
617
699
|
else
|
618
|
-
|
619
|
-
|
700
|
+
@lock.synchronize do
|
701
|
+
# outside of transactions we can simply flush this query and retry
|
702
|
+
@statements.delete sql_key(sql)
|
703
|
+
end
|
620
704
|
retry
|
621
705
|
end
|
622
706
|
end
|
@@ -629,8 +713,8 @@ module ActiveRecord
|
|
629
713
|
# ActiveRecord::PreparedStatementCacheExpired
|
630
714
|
#
|
631
715
|
# Check here for more details:
|
632
|
-
#
|
633
|
-
CACHED_PLAN_HEURISTIC =
|
716
|
+
# https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/cache/plancache.c#l573
|
717
|
+
CACHED_PLAN_HEURISTIC = "cached plan must not change result type"
|
634
718
|
def is_cached_plan_failure?(e)
|
635
719
|
pgerror = e.cause
|
636
720
|
code = pgerror.result.result_error_field(PG::PG_DIAG_SQLSTATE)
|
@@ -651,20 +735,22 @@ module ActiveRecord
|
|
651
735
|
|
652
736
|
# Prepare the statement if it hasn't been prepared, return
|
653
737
|
# the statement key.
|
654
|
-
def prepare_statement(sql)
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
738
|
+
def prepare_statement(sql, binds)
|
739
|
+
@lock.synchronize do
|
740
|
+
sql_key = sql_key(sql)
|
741
|
+
unless @statements.key? sql_key
|
742
|
+
nextkey = @statements.next_key
|
743
|
+
begin
|
744
|
+
@connection.prepare nextkey, sql
|
745
|
+
rescue => e
|
746
|
+
raise translate_exception_class(e, sql, binds)
|
747
|
+
end
|
748
|
+
# Clear the queue
|
749
|
+
@connection.get_last_result
|
750
|
+
@statements[sql_key] = nextkey
|
662
751
|
end
|
663
|
-
|
664
|
-
@connection.get_last_result
|
665
|
-
@statements[sql_key] = nextkey
|
752
|
+
@statements[sql_key]
|
666
753
|
end
|
667
|
-
@statements[sql_key]
|
668
754
|
end
|
669
755
|
|
670
756
|
# Connects to a PostgreSQL server and sets up the adapter depending on the
|
@@ -672,12 +758,8 @@ module ActiveRecord
|
|
672
758
|
def connect
|
673
759
|
@connection = PG.connect(@connection_parameters)
|
674
760
|
configure_connection
|
675
|
-
|
676
|
-
|
677
|
-
raise ActiveRecord::NoDatabaseError
|
678
|
-
else
|
679
|
-
raise
|
680
|
-
end
|
761
|
+
add_pg_encoders
|
762
|
+
add_pg_decoders
|
681
763
|
end
|
682
764
|
|
683
765
|
# Configures the encoding, verbosity, schema search path, and time zone of the connection.
|
@@ -686,39 +768,36 @@ module ActiveRecord
|
|
686
768
|
if @config[:encoding]
|
687
769
|
@connection.set_client_encoding(@config[:encoding])
|
688
770
|
end
|
689
|
-
self.client_min_messages = @config[:min_messages] ||
|
771
|
+
self.client_min_messages = @config[:min_messages] || "warning"
|
690
772
|
self.schema_search_path = @config[:schema_search_path] || @config[:schema_order]
|
691
773
|
|
692
774
|
# Use standard-conforming strings so we don't have to do the E'...' dance.
|
693
775
|
set_standard_conforming_strings
|
694
776
|
|
777
|
+
variables = @config.fetch(:variables, {}).stringify_keys
|
778
|
+
|
695
779
|
# If using Active Record's time zone support configure the connection to return
|
696
780
|
# TIMESTAMP WITH ZONE types in UTC.
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
781
|
+
unless variables["timezone"]
|
782
|
+
if ActiveRecord::Base.default_timezone == :utc
|
783
|
+
variables["timezone"] = "UTC"
|
784
|
+
elsif @local_tz
|
785
|
+
variables["timezone"] = @local_tz
|
786
|
+
end
|
702
787
|
end
|
703
788
|
|
704
789
|
# SET statements from :variables config hash
|
705
|
-
#
|
706
|
-
variables = @config[:variables] || {}
|
790
|
+
# https://www.postgresql.org/docs/current/static/sql-set.html
|
707
791
|
variables.map do |k, v|
|
708
|
-
if v ==
|
792
|
+
if v == ":default" || v == :default
|
709
793
|
# Sets the value to the global or compile default
|
710
|
-
execute("SET SESSION #{k} TO DEFAULT",
|
794
|
+
execute("SET SESSION #{k} TO DEFAULT", "SCHEMA")
|
711
795
|
elsif !v.nil?
|
712
|
-
execute("SET SESSION #{k} TO #{quote(v)}",
|
796
|
+
execute("SET SESSION #{k} TO #{quote(v)}", "SCHEMA")
|
713
797
|
end
|
714
798
|
end
|
715
799
|
end
|
716
800
|
|
717
|
-
# 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')
|
720
|
-
end
|
721
|
-
|
722
801
|
# Returns the list of a table's column names, data types, and default values.
|
723
802
|
#
|
724
803
|
# The underlying query is roughly:
|
@@ -737,34 +816,38 @@ module ActiveRecord
|
|
737
816
|
# Query implementation notes:
|
738
817
|
# - format_type includes the column size constraint, e.g. varchar(50)
|
739
818
|
# - ::regclass is a function that gives the id for a table name
|
740
|
-
def column_definitions(table_name)
|
741
|
-
query(
|
819
|
+
def column_definitions(table_name)
|
820
|
+
query(<<~SQL, "SCHEMA")
|
742
821
|
SELECT a.attname, format_type(a.atttypid, a.atttypmod),
|
743
822
|
pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
WHERE a.attrelid =
|
823
|
+
c.collname, col_description(a.attrelid, a.attnum) AS comment
|
824
|
+
FROM pg_attribute a
|
825
|
+
LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
|
826
|
+
LEFT JOIN pg_type t ON a.atttypid = t.oid
|
827
|
+
LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation
|
828
|
+
WHERE a.attrelid = #{quote(quote_table_name(table_name))}::regclass
|
750
829
|
AND a.attnum > 0 AND NOT a.attisdropped
|
751
830
|
ORDER BY a.attnum
|
752
|
-
|
831
|
+
SQL
|
753
832
|
end
|
754
833
|
|
755
|
-
def extract_table_ref_from_insert_sql(sql)
|
834
|
+
def extract_table_ref_from_insert_sql(sql)
|
756
835
|
sql[/into\s("[A-Za-z0-9_."\[\]\s]+"|[A-Za-z0-9_."\[\]]+)\s*/im]
|
757
836
|
$1.strip if $1
|
758
837
|
end
|
759
838
|
|
760
|
-
def
|
761
|
-
PostgreSQL
|
839
|
+
def arel_visitor
|
840
|
+
Arel::Visitors::PostgreSQL.new(self)
|
841
|
+
end
|
842
|
+
|
843
|
+
def build_statement_pool
|
844
|
+
StatementPool.new(@connection, self.class.type_cast_config_to_integer(@config[:statement_limit]))
|
762
845
|
end
|
763
846
|
|
764
847
|
def can_perform_case_insensitive_comparison_for?(column)
|
765
848
|
@case_insensitive_cache ||= {}
|
766
849
|
@case_insensitive_cache[column.sql_type] ||= begin
|
767
|
-
sql =
|
850
|
+
sql = <<~SQL
|
768
851
|
SELECT exists(
|
769
852
|
SELECT * FROM pg_proc
|
770
853
|
WHERE proname = 'lower'
|
@@ -776,7 +859,7 @@ module ActiveRecord
|
|
776
859
|
WHERE proname = 'lower'
|
777
860
|
AND castsource = #{quote column.sql_type}::regtype
|
778
861
|
)
|
779
|
-
|
862
|
+
SQL
|
780
863
|
execute_and_clear(sql, "SCHEMA", []) do |result|
|
781
864
|
result.getvalue(0, 0)
|
782
865
|
end
|
@@ -788,40 +871,65 @@ module ActiveRecord
|
|
788
871
|
map[Integer] = PG::TextEncoder::Integer.new
|
789
872
|
map[TrueClass] = PG::TextEncoder::Boolean.new
|
790
873
|
map[FalseClass] = PG::TextEncoder::Boolean.new
|
791
|
-
map[Float] = PG::TextEncoder::Float.new
|
792
874
|
@connection.type_map_for_queries = map
|
793
875
|
end
|
794
876
|
|
877
|
+
def update_typemap_for_default_timezone
|
878
|
+
if @default_timezone != ActiveRecord::Base.default_timezone && @timestamp_decoder
|
879
|
+
decoder_class = ActiveRecord::Base.default_timezone == :utc ?
|
880
|
+
PG::TextDecoder::TimestampUtc :
|
881
|
+
PG::TextDecoder::TimestampWithoutTimeZone
|
882
|
+
|
883
|
+
@timestamp_decoder = decoder_class.new(@timestamp_decoder.to_h)
|
884
|
+
@connection.type_map_for_results.add_coder(@timestamp_decoder)
|
885
|
+
@default_timezone = ActiveRecord::Base.default_timezone
|
886
|
+
end
|
887
|
+
end
|
888
|
+
|
795
889
|
def add_pg_decoders
|
890
|
+
@default_timezone = nil
|
891
|
+
@timestamp_decoder = nil
|
892
|
+
|
796
893
|
coders_by_name = {
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
894
|
+
"int2" => PG::TextDecoder::Integer,
|
895
|
+
"int4" => PG::TextDecoder::Integer,
|
896
|
+
"int8" => PG::TextDecoder::Integer,
|
897
|
+
"oid" => PG::TextDecoder::Integer,
|
898
|
+
"float4" => PG::TextDecoder::Float,
|
899
|
+
"float8" => PG::TextDecoder::Float,
|
900
|
+
"bool" => PG::TextDecoder::Boolean,
|
804
901
|
}
|
902
|
+
|
903
|
+
if defined?(PG::TextDecoder::TimestampUtc)
|
904
|
+
# Use native PG encoders available since pg-1.1
|
905
|
+
coders_by_name["timestamp"] = PG::TextDecoder::TimestampUtc
|
906
|
+
coders_by_name["timestamptz"] = PG::TextDecoder::TimestampWithTimeZone
|
907
|
+
end
|
908
|
+
|
805
909
|
known_coder_types = coders_by_name.keys.map { |n| quote(n) }
|
806
|
-
query =
|
910
|
+
query = <<~SQL % known_coder_types.join(", ")
|
807
911
|
SELECT t.oid, t.typname
|
808
912
|
FROM pg_type as t
|
809
913
|
WHERE t.typname IN (%s)
|
810
914
|
SQL
|
811
915
|
coders = execute_and_clear(query, "SCHEMA", []) do |result|
|
812
916
|
result
|
813
|
-
.map { |row| construct_coder(row, coders_by_name[row[
|
917
|
+
.map { |row| construct_coder(row, coders_by_name[row["typname"]]) }
|
814
918
|
.compact
|
815
919
|
end
|
816
920
|
|
817
921
|
map = PG::TypeMapByOid.new
|
818
922
|
coders.each { |coder| map.add_coder(coder) }
|
819
923
|
@connection.type_map_for_results = map
|
924
|
+
|
925
|
+
# extract timestamp decoder for use in update_typemap_for_default_timezone
|
926
|
+
@timestamp_decoder = coders.find { |coder| coder.name == "timestamp" }
|
927
|
+
update_typemap_for_default_timezone
|
820
928
|
end
|
821
929
|
|
822
930
|
def construct_coder(row, coder_class)
|
823
931
|
return unless coder_class
|
824
|
-
coder_class.new(oid: row[
|
932
|
+
coder_class.new(oid: row["oid"].to_i, name: row["typname"])
|
825
933
|
end
|
826
934
|
|
827
935
|
ActiveRecord::Type.add_modifier({ array: true }, OID::Array, adapter: :postgresql)
|
@@ -830,16 +938,16 @@ module ActiveRecord
|
|
830
938
|
ActiveRecord::Type.register(:bit_varying, OID::BitVarying, adapter: :postgresql)
|
831
939
|
ActiveRecord::Type.register(:binary, OID::Bytea, adapter: :postgresql)
|
832
940
|
ActiveRecord::Type.register(:cidr, OID::Cidr, adapter: :postgresql)
|
941
|
+
ActiveRecord::Type.register(:date, OID::Date, adapter: :postgresql)
|
833
942
|
ActiveRecord::Type.register(:datetime, OID::DateTime, adapter: :postgresql)
|
834
943
|
ActiveRecord::Type.register(:decimal, OID::Decimal, adapter: :postgresql)
|
835
944
|
ActiveRecord::Type.register(:enum, OID::Enum, adapter: :postgresql)
|
836
945
|
ActiveRecord::Type.register(:hstore, OID::Hstore, adapter: :postgresql)
|
837
946
|
ActiveRecord::Type.register(:inet, OID::Inet, adapter: :postgresql)
|
838
|
-
ActiveRecord::Type.register(:json, OID::Json, adapter: :postgresql)
|
839
947
|
ActiveRecord::Type.register(:jsonb, OID::Jsonb, adapter: :postgresql)
|
840
948
|
ActiveRecord::Type.register(:money, OID::Money, adapter: :postgresql)
|
841
|
-
ActiveRecord::Type.register(:point, OID::
|
842
|
-
ActiveRecord::Type.register(:legacy_point, OID::
|
949
|
+
ActiveRecord::Type.register(:point, OID::Point, adapter: :postgresql)
|
950
|
+
ActiveRecord::Type.register(:legacy_point, OID::LegacyPoint, adapter: :postgresql)
|
843
951
|
ActiveRecord::Type.register(:uuid, OID::Uuid, adapter: :postgresql)
|
844
952
|
ActiveRecord::Type.register(:vector, OID::Vector, adapter: :postgresql)
|
845
953
|
ActiveRecord::Type.register(:xml, OID::Xml, adapter: :postgresql)
|