activerecord 5.2.3 → 6.1.0
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 +898 -532
- data/MIT-LICENSE +3 -1
- data/README.rdoc +7 -5
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +5 -4
- data/lib/active_record/association_relation.rb +22 -12
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +95 -42
- data/lib/active_record/associations/association_scope.rb +21 -21
- data/lib/active_record/associations/belongs_to_association.rb +50 -46
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -5
- data/lib/active_record/associations/builder/association.rb +23 -21
- data/lib/active_record/associations/builder/belongs_to.rb +29 -59
- data/lib/active_record/associations/builder/collection_association.rb +10 -19
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
- data/lib/active_record/associations/builder/has_many.rb +8 -2
- data/lib/active_record/associations/builder/has_one.rb +33 -2
- data/lib/active_record/associations/builder/singular_association.rb +3 -1
- data/lib/active_record/associations/collection_association.rb +31 -29
- data/lib/active_record/associations/collection_proxy.rb +25 -21
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +26 -13
- data/lib/active_record/associations/has_many_through_association.rb +27 -28
- data/lib/active_record/associations/has_one_association.rb +43 -31
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +54 -12
- data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +91 -60
- data/lib/active_record/associations/preloader/association.rb +71 -43
- data/lib/active_record/associations/preloader/through_association.rb +49 -40
- data/lib/active_record/associations/preloader.rb +48 -35
- data/lib/active_record/associations/singular_association.rb +3 -17
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +133 -25
- data/lib/active_record/attribute_assignment.rb +17 -19
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -7
- data/lib/active_record/attribute_methods/dirty.rb +101 -40
- data/lib/active_record/attribute_methods/primary_key.rb +20 -25
- data/lib/active_record/attribute_methods/query.rb +4 -8
- data/lib/active_record/attribute_methods/read.rb +14 -56
- data/lib/active_record/attribute_methods/serialization.rb +12 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
- data/lib/active_record/attribute_methods/write.rb +18 -34
- data/lib/active_record/attribute_methods.rb +81 -143
- data/lib/active_record/attributes.rb +45 -8
- data/lib/active_record/autosave_association.rb +76 -47
- data/lib/active_record/base.rb +4 -17
- data/lib/active_record/callbacks.rb +158 -43
- data/lib/active_record/coders/yaml_column.rb +1 -2
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +293 -132
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -36
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +167 -146
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +21 -17
- data/lib/active_record/connection_adapters/abstract/quoting.rb +98 -47
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -110
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +203 -90
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -4
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +381 -146
- data/lib/active_record/connection_adapters/abstract/transaction.rb +155 -68
- data/lib/active_record/connection_adapters/abstract_adapter.rb +229 -98
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +243 -275
- data/lib/active_record/connection_adapters/column.rb +30 -12
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +86 -32
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +14 -6
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +139 -19
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +53 -18
- data/lib/active_record/connection_adapters/pool_config.rb +63 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +37 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +38 -54
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- 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 +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
- 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 +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +47 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +19 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +120 -100
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +222 -112
- data/lib/active_record/connection_adapters/schema_cache.rb +127 -21
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +19 -6
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +77 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +175 -187
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_adapters.rb +50 -0
- data/lib/active_record/connection_handling.rb +285 -33
- data/lib/active_record/core.rb +308 -100
- data/lib/active_record/counter_cache.rb +8 -30
- data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
- data/lib/active_record/database_configurations/database_config.rb +80 -0
- data/lib/active_record/database_configurations/hash_config.rb +96 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/database_configurations.rb +272 -0
- 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 +3 -4
- data/lib/active_record/enum.rb +71 -17
- data/lib/active_record/errors.rb +62 -19
- data/lib/active_record/explain.rb +10 -6
- 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 +32 -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 +197 -481
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +53 -24
- data/lib/active_record/insert_all.rb +208 -0
- data/lib/active_record/integration.rb +67 -17
- data/lib/active_record/internal_metadata.rb +26 -9
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +26 -22
- data/lib/active_record/locking/pessimistic.rb +9 -5
- data/lib/active_record/log_subscriber.rb +34 -35
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +77 -0
- data/lib/active_record/migration/command_recorder.rb +96 -44
- data/lib/active_record/migration/compatibility.rb +141 -64
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/migration.rb +205 -156
- data/lib/active_record/model_schema.rb +148 -22
- data/lib/active_record/nested_attributes.rb +4 -7
- data/lib/active_record/no_touching.rb +8 -1
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +267 -59
- data/lib/active_record/query_cache.rb +21 -4
- data/lib/active_record/querying.rb +40 -23
- data/lib/active_record/railtie.rb +115 -58
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +402 -78
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +113 -101
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/batches.rb +44 -35
- data/lib/active_record/relation/calculations.rb +157 -93
- data/lib/active_record/relation/delegation.rb +35 -50
- data/lib/active_record/relation/finder_methods.rb +65 -40
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +32 -40
- data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -7
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +58 -40
- data/lib/active_record/relation/query_attribute.rb +13 -8
- data/lib/active_record/relation/query_methods.rb +487 -199
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +9 -9
- data/lib/active_record/relation/where_clause.rb +108 -58
- data/lib/active_record/relation.rb +375 -104
- data/lib/active_record/result.rb +64 -38
- data/lib/active_record/runtime_registry.rb +2 -2
- data/lib/active_record/sanitization.rb +22 -41
- data/lib/active_record/schema.rb +2 -11
- data/lib/active_record/schema_dumper.rb +54 -9
- data/lib/active_record/schema_migration.rb +7 -9
- data/lib/active_record/scoping/default.rb +6 -8
- data/lib/active_record/scoping/named.rb +17 -24
- data/lib/active_record/scoping.rb +8 -9
- 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 +51 -8
- data/lib/active_record/store.rb +88 -9
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +39 -43
- data/lib/active_record/tasks/database_tasks.rb +276 -81
- data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
- data/lib/active_record/tasks/postgresql_database_tasks.rb +27 -32
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +246 -0
- data/lib/active_record/timestamp.rb +43 -32
- data/lib/active_record/touch_later.rb +23 -22
- data/lib/active_record/transactions.rb +59 -117
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type/adapter_specific_registry.rb +3 -13
- 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 +10 -5
- data/lib/active_record/type_caster/connection.rb +15 -15
- data/lib/active_record/type_caster/map.rb +8 -8
- 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 +38 -30
- data/lib/active_record/validations.rb +4 -3
- data/lib/active_record.rb +13 -12
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +41 -0
- data/lib/arel/collectors/bind.rb +29 -0
- data/lib/arel/collectors/composite.rb +39 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -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 +126 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -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 +15 -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 +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +72 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -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 +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -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 +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -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 +70 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +250 -0
- data/lib/arel/select_manager.rb +270 -0
- data/lib/arel/table.rb +118 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/dot.rb +308 -0
- data/lib/arel/visitors/mysql.rb +93 -0
- data/lib/arel/visitors/postgresql.rb +120 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +899 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +54 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
- data/lib/rails/generators/active_record/migration.rb +19 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
- metadata +117 -32
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/collection_cache_key.rb +0 -53
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
- data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -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
|
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,14 +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
|
-
|
36
|
+
ConnectionAdapters::PostgreSQLAdapter.new(
|
37
|
+
ConnectionAdapters::PostgreSQLAdapter.new_client(conn_params),
|
38
|
+
logger,
|
39
|
+
conn_params,
|
40
|
+
config,
|
41
|
+
)
|
49
42
|
end
|
50
43
|
end
|
51
44
|
|
52
45
|
module ConnectionAdapters
|
53
|
-
# 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.
|
54
47
|
#
|
55
48
|
# Options:
|
56
49
|
#
|
@@ -78,7 +71,32 @@ module ActiveRecord
|
|
78
71
|
# In addition, default connection parameters of libpq can be set per environment variables.
|
79
72
|
# See https://www.postgresql.org/docs/current/static/libpq-envars.html .
|
80
73
|
class PostgreSQLAdapter < AbstractAdapter
|
81
|
-
ADAPTER_NAME = "PostgreSQL"
|
74
|
+
ADAPTER_NAME = "PostgreSQL"
|
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
|
+
##
|
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
|
82
100
|
|
83
101
|
NATIVE_DATABASE_TYPES = {
|
84
102
|
primary_key: "bigserial primary key",
|
@@ -138,6 +156,10 @@ module ActiveRecord
|
|
138
156
|
true
|
139
157
|
end
|
140
158
|
|
159
|
+
def supports_partitioned_indexes?
|
160
|
+
database_version >= 110_000
|
161
|
+
end
|
162
|
+
|
141
163
|
def supports_partial_index?
|
142
164
|
true
|
143
165
|
end
|
@@ -154,6 +176,10 @@ module ActiveRecord
|
|
154
176
|
true
|
155
177
|
end
|
156
178
|
|
179
|
+
def supports_check_constraints?
|
180
|
+
true
|
181
|
+
end
|
182
|
+
|
157
183
|
def supports_validate_constraints?
|
158
184
|
true
|
159
185
|
end
|
@@ -167,7 +193,7 @@ module ActiveRecord
|
|
167
193
|
end
|
168
194
|
|
169
195
|
def supports_json?
|
170
|
-
|
196
|
+
true
|
171
197
|
end
|
172
198
|
|
173
199
|
def supports_comments?
|
@@ -178,6 +204,17 @@ module ActiveRecord
|
|
178
204
|
true
|
179
205
|
end
|
180
206
|
|
207
|
+
def supports_insert_returning?
|
208
|
+
true
|
209
|
+
end
|
210
|
+
|
211
|
+
def supports_insert_on_conflict?
|
212
|
+
database_version >= 90500
|
213
|
+
end
|
214
|
+
alias supports_insert_on_duplicate_skip? supports_insert_on_conflict?
|
215
|
+
alias supports_insert_on_duplicate_update? supports_insert_on_conflict?
|
216
|
+
alias supports_insert_conflict_target? supports_insert_on_conflict?
|
217
|
+
|
181
218
|
def index_algorithms
|
182
219
|
{ concurrently: "CONCURRENTLY" }
|
183
220
|
end
|
@@ -220,15 +257,8 @@ module ActiveRecord
|
|
220
257
|
@local_tz = nil
|
221
258
|
@max_identifier_length = nil
|
222
259
|
|
223
|
-
|
260
|
+
configure_connection
|
224
261
|
add_pg_encoders
|
225
|
-
@statements = StatementPool.new @connection,
|
226
|
-
self.class.type_cast_config_to_integer(config[:statement_limit])
|
227
|
-
|
228
|
-
if postgresql_version < 90100
|
229
|
-
raise "Your version of PostgreSQL (#{postgresql_version}) is too old. Active Record supports PostgreSQL >= 9.1."
|
230
|
-
end
|
231
|
-
|
232
262
|
add_pg_decoders
|
233
263
|
|
234
264
|
@type_map = Type::HashLookupTypeMap.new
|
@@ -237,15 +267,10 @@ module ActiveRecord
|
|
237
267
|
@use_insert_returning = @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
|
238
268
|
end
|
239
269
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
def truncate(table_name, name = nil)
|
248
|
-
exec_query "TRUNCATE TABLE #{quote_table_name(table_name)}", name, []
|
270
|
+
def self.database_exists?(config)
|
271
|
+
!!ActiveRecord::Base.postgresql_connection(config)
|
272
|
+
rescue ActiveRecord::NoDatabaseError
|
273
|
+
false
|
249
274
|
end
|
250
275
|
|
251
276
|
# Is this connection alive and ready for queries?
|
@@ -264,6 +289,8 @@ module ActiveRecord
|
|
264
289
|
super
|
265
290
|
@connection.reset
|
266
291
|
configure_connection
|
292
|
+
rescue PG::ConnectionBad
|
293
|
+
connect
|
267
294
|
end
|
268
295
|
end
|
269
296
|
|
@@ -289,6 +316,7 @@ module ActiveRecord
|
|
289
316
|
end
|
290
317
|
|
291
318
|
def discard! # :nodoc:
|
319
|
+
super
|
292
320
|
@connection.socket_io.reopen(IO::NULL) rescue nil
|
293
321
|
@connection = nil
|
294
322
|
end
|
@@ -317,21 +345,31 @@ module ActiveRecord
|
|
317
345
|
true
|
318
346
|
end
|
319
347
|
|
320
|
-
def supports_ranges?
|
321
|
-
# Range datatypes weren't introduced until PostgreSQL 9.2
|
322
|
-
postgresql_version >= 90200
|
323
|
-
end
|
324
|
-
|
325
348
|
def supports_materialized_views?
|
326
|
-
|
349
|
+
true
|
327
350
|
end
|
328
351
|
|
329
352
|
def supports_foreign_tables?
|
330
|
-
|
353
|
+
true
|
331
354
|
end
|
332
355
|
|
333
356
|
def supports_pgcrypto_uuid?
|
334
|
-
|
357
|
+
database_version >= 90400
|
358
|
+
end
|
359
|
+
|
360
|
+
def supports_optimizer_hints?
|
361
|
+
unless defined?(@has_pg_hint_plan)
|
362
|
+
@has_pg_hint_plan = extension_available?("pg_hint_plan")
|
363
|
+
end
|
364
|
+
@has_pg_hint_plan
|
365
|
+
end
|
366
|
+
|
367
|
+
def supports_common_table_expressions?
|
368
|
+
true
|
369
|
+
end
|
370
|
+
|
371
|
+
def supports_lazy_transactions?
|
372
|
+
true
|
335
373
|
end
|
336
374
|
|
337
375
|
def get_advisory_lock(lock_id) # :nodoc:
|
@@ -360,9 +398,12 @@ module ActiveRecord
|
|
360
398
|
}
|
361
399
|
end
|
362
400
|
|
401
|
+
def extension_available?(name)
|
402
|
+
query_value("SELECT true FROM pg_available_extensions WHERE name = #{quote(name)}", "SCHEMA")
|
403
|
+
end
|
404
|
+
|
363
405
|
def extension_enabled?(name)
|
364
|
-
|
365
|
-
res.cast_values.first
|
406
|
+
query_value("SELECT installed_version IS NOT NULL FROM pg_available_extensions WHERE name = #{quote(name)}", "SCHEMA")
|
366
407
|
end
|
367
408
|
|
368
409
|
def extensions
|
@@ -373,8 +414,6 @@ module ActiveRecord
|
|
373
414
|
def max_identifier_length
|
374
415
|
@max_identifier_length ||= query_value("SHOW max_identifier_length", "SCHEMA").to_i
|
375
416
|
end
|
376
|
-
alias table_alias_length max_identifier_length
|
377
|
-
alias index_name_length max_identifier_length
|
378
417
|
|
379
418
|
# Set the authorized user for this session
|
380
419
|
def session_auth=(user)
|
@@ -386,25 +425,37 @@ module ActiveRecord
|
|
386
425
|
@use_insert_returning
|
387
426
|
end
|
388
427
|
|
389
|
-
def column_name_for_operation(operation, node) # :nodoc:
|
390
|
-
OPERATION_ALIASES.fetch(operation) { operation.downcase }
|
391
|
-
end
|
392
|
-
|
393
|
-
OPERATION_ALIASES = { # :nodoc:
|
394
|
-
"maximum" => "max",
|
395
|
-
"minimum" => "min",
|
396
|
-
"average" => "avg",
|
397
|
-
}
|
398
|
-
|
399
428
|
# Returns the version of the connected PostgreSQL server.
|
400
|
-
def
|
429
|
+
def get_database_version # :nodoc:
|
401
430
|
@connection.server_version
|
402
431
|
end
|
432
|
+
alias :postgresql_version :database_version
|
403
433
|
|
404
434
|
def default_index_type?(index) # :nodoc:
|
405
435
|
index.using == :btree || super
|
406
436
|
end
|
407
437
|
|
438
|
+
def build_insert_sql(insert) # :nodoc:
|
439
|
+
sql = +"INSERT #{insert.into} #{insert.values_list}"
|
440
|
+
|
441
|
+
if insert.skip_duplicates?
|
442
|
+
sql << " ON CONFLICT #{insert.conflict_target} DO NOTHING"
|
443
|
+
elsif insert.update_duplicates?
|
444
|
+
sql << " ON CONFLICT #{insert.conflict_target} DO UPDATE SET "
|
445
|
+
sql << insert.touch_model_timestamps_unless { |column| "#{insert.model.quoted_table_name}.#{column} IS NOT DISTINCT FROM excluded.#{column}" }
|
446
|
+
sql << insert.updatable_columns.map { |column| "#{column}=excluded.#{column}" }.join(",")
|
447
|
+
end
|
448
|
+
|
449
|
+
sql << " RETURNING #{insert.returning}" if insert.returning
|
450
|
+
sql
|
451
|
+
end
|
452
|
+
|
453
|
+
def check_version # :nodoc:
|
454
|
+
if database_version < 90300
|
455
|
+
raise "Your version of PostgreSQL (#{database_version}) is too old. Active Record supports PostgreSQL >= 9.3."
|
456
|
+
end
|
457
|
+
end
|
458
|
+
|
408
459
|
private
|
409
460
|
# See https://www.postgresql.org/docs/current/static/errcodes-appendix.html
|
410
461
|
VALUE_LIMIT_VIOLATION = "22001"
|
@@ -414,37 +465,46 @@ module ActiveRecord
|
|
414
465
|
UNIQUE_VIOLATION = "23505"
|
415
466
|
SERIALIZATION_FAILURE = "40001"
|
416
467
|
DEADLOCK_DETECTED = "40P01"
|
468
|
+
DUPLICATE_DATABASE = "42P04"
|
417
469
|
LOCK_NOT_AVAILABLE = "55P03"
|
418
470
|
QUERY_CANCELED = "57014"
|
419
471
|
|
420
|
-
def translate_exception(exception, message)
|
472
|
+
def translate_exception(exception, message:, sql:, binds:)
|
421
473
|
return exception unless exception.respond_to?(:result)
|
422
474
|
|
423
475
|
case exception.result.try(:error_field, PG::PG_DIAG_SQLSTATE)
|
476
|
+
when nil
|
477
|
+
if exception.message.match?(/connection is closed/i)
|
478
|
+
ConnectionNotEstablished.new(exception)
|
479
|
+
else
|
480
|
+
super
|
481
|
+
end
|
424
482
|
when UNIQUE_VIOLATION
|
425
|
-
RecordNotUnique.new(message)
|
483
|
+
RecordNotUnique.new(message, sql: sql, binds: binds)
|
426
484
|
when FOREIGN_KEY_VIOLATION
|
427
|
-
InvalidForeignKey.new(message)
|
485
|
+
InvalidForeignKey.new(message, sql: sql, binds: binds)
|
428
486
|
when VALUE_LIMIT_VIOLATION
|
429
|
-
ValueTooLong.new(message)
|
487
|
+
ValueTooLong.new(message, sql: sql, binds: binds)
|
430
488
|
when NUMERIC_VALUE_OUT_OF_RANGE
|
431
|
-
RangeError.new(message)
|
489
|
+
RangeError.new(message, sql: sql, binds: binds)
|
432
490
|
when NOT_NULL_VIOLATION
|
433
|
-
NotNullViolation.new(message)
|
491
|
+
NotNullViolation.new(message, sql: sql, binds: binds)
|
434
492
|
when SERIALIZATION_FAILURE
|
435
|
-
SerializationFailure.new(message)
|
493
|
+
SerializationFailure.new(message, sql: sql, binds: binds)
|
436
494
|
when DEADLOCK_DETECTED
|
437
|
-
Deadlocked.new(message)
|
495
|
+
Deadlocked.new(message, sql: sql, binds: binds)
|
496
|
+
when DUPLICATE_DATABASE
|
497
|
+
DatabaseAlreadyExists.new(message, sql: sql, binds: binds)
|
438
498
|
when LOCK_NOT_AVAILABLE
|
439
|
-
LockWaitTimeout.new(message)
|
499
|
+
LockWaitTimeout.new(message, sql: sql, binds: binds)
|
440
500
|
when QUERY_CANCELED
|
441
|
-
QueryCanceled.new(message)
|
501
|
+
QueryCanceled.new(message, sql: sql, binds: binds)
|
442
502
|
else
|
443
503
|
super
|
444
504
|
end
|
445
505
|
end
|
446
506
|
|
447
|
-
def get_oid_type(oid, fmod, column_name, sql_type = ""
|
507
|
+
def get_oid_type(oid, fmod, column_name, sql_type = "")
|
448
508
|
if !type_map.key?(oid)
|
449
509
|
load_additional_types([oid])
|
450
510
|
end
|
@@ -486,7 +546,7 @@ module ActiveRecord
|
|
486
546
|
m.register_type "uuid", OID::Uuid.new
|
487
547
|
m.register_type "xml", OID::Xml.new
|
488
548
|
m.register_type "tsvector", OID::SpecializedString.new(:tsvector)
|
489
|
-
m.register_type "macaddr", OID::
|
549
|
+
m.register_type "macaddr", OID::Macaddr.new
|
490
550
|
m.register_type "citext", OID::SpecializedString.new(:citext)
|
491
551
|
m.register_type "ltree", OID::SpecializedString.new(:ltree)
|
492
552
|
m.register_type "line", OID::SpecializedString.new(:line)
|
@@ -496,11 +556,6 @@ module ActiveRecord
|
|
496
556
|
m.register_type "polygon", OID::SpecializedString.new(:polygon)
|
497
557
|
m.register_type "circle", OID::SpecializedString.new(:circle)
|
498
558
|
|
499
|
-
m.register_type "interval" do |_, _, sql_type|
|
500
|
-
precision = extract_precision(sql_type)
|
501
|
-
OID::SpecializedString.new(:interval, precision: precision)
|
502
|
-
end
|
503
|
-
|
504
559
|
register_class_with_precision m, "time", Type::Time
|
505
560
|
register_class_with_precision m, "timestamp", OID::DateTime
|
506
561
|
|
@@ -524,6 +579,11 @@ module ActiveRecord
|
|
524
579
|
end
|
525
580
|
end
|
526
581
|
|
582
|
+
m.register_type "interval" do |*args, sql_type|
|
583
|
+
precision = extract_precision(sql_type)
|
584
|
+
OID::Interval.new(precision: precision)
|
585
|
+
end
|
586
|
+
|
527
587
|
load_additional_types
|
528
588
|
end
|
529
589
|
|
@@ -533,13 +593,13 @@ module ActiveRecord
|
|
533
593
|
# Quoted types
|
534
594
|
when /\A[\(B]?'(.*)'.*::"?([\w. ]+)"?(?:\[\])?\z/m
|
535
595
|
# The default 'now'::date is CURRENT_DATE
|
536
|
-
if $1 == "now"
|
596
|
+
if $1 == "now" && $2 == "date"
|
537
597
|
nil
|
538
598
|
else
|
539
|
-
$1.gsub("''"
|
599
|
+
$1.gsub("''", "'")
|
540
600
|
end
|
541
601
|
# Boolean types
|
542
|
-
when "true"
|
602
|
+
when "true", "false"
|
543
603
|
default
|
544
604
|
# Numeric types
|
545
605
|
when /\A\(?(-?\d+(\.\d*)?)\)?(::bigint)?\z/
|
@@ -565,21 +625,14 @@ module ActiveRecord
|
|
565
625
|
def load_additional_types(oids = nil)
|
566
626
|
initializer = OID::TypeMapInitializer.new(type_map)
|
567
627
|
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
SQL
|
574
|
-
else
|
575
|
-
query = <<-SQL
|
576
|
-
SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, t.typtype, t.typbasetype
|
577
|
-
FROM pg_type as t
|
578
|
-
SQL
|
579
|
-
end
|
628
|
+
query = <<~SQL
|
629
|
+
SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
|
630
|
+
FROM pg_type as t
|
631
|
+
LEFT JOIN pg_range as r ON oid = rngtypid
|
632
|
+
SQL
|
580
633
|
|
581
634
|
if oids
|
582
|
-
query += "WHERE t.oid
|
635
|
+
query += "WHERE t.oid IN (%s)" % oids.join(", ")
|
583
636
|
else
|
584
637
|
query += initializer.query_conditions_for_initial_load
|
585
638
|
end
|
@@ -592,6 +645,10 @@ module ActiveRecord
|
|
592
645
|
FEATURE_NOT_SUPPORTED = "0A000" #:nodoc:
|
593
646
|
|
594
647
|
def execute_and_clear(sql, name, binds, prepare: false)
|
648
|
+
if preventing_writes? && write_query?(sql)
|
649
|
+
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
650
|
+
end
|
651
|
+
|
595
652
|
if without_prepared_statement?(binds)
|
596
653
|
result = exec_no_cache(sql, name, [])
|
597
654
|
elsif !prepare
|
@@ -599,12 +656,22 @@ module ActiveRecord
|
|
599
656
|
else
|
600
657
|
result = exec_cache(sql, name, binds)
|
601
658
|
end
|
602
|
-
|
603
|
-
|
659
|
+
begin
|
660
|
+
ret = yield result
|
661
|
+
ensure
|
662
|
+
result.clear
|
663
|
+
end
|
604
664
|
ret
|
605
665
|
end
|
606
666
|
|
607
667
|
def exec_no_cache(sql, name, binds)
|
668
|
+
materialize_transactions
|
669
|
+
mark_transaction_written_if_write(sql)
|
670
|
+
|
671
|
+
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
|
672
|
+
# made since we established the connection
|
673
|
+
update_typemap_for_default_timezone
|
674
|
+
|
608
675
|
type_casted_binds = type_casted_binds(binds)
|
609
676
|
log(sql, name, binds, type_casted_binds) do
|
610
677
|
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
@@ -614,7 +681,11 @@ module ActiveRecord
|
|
614
681
|
end
|
615
682
|
|
616
683
|
def exec_cache(sql, name, binds)
|
617
|
-
|
684
|
+
materialize_transactions
|
685
|
+
mark_transaction_written_if_write(sql)
|
686
|
+
update_typemap_for_default_timezone
|
687
|
+
|
688
|
+
stmt_key = prepare_statement(sql, binds)
|
618
689
|
type_casted_binds = type_casted_binds(binds)
|
619
690
|
|
620
691
|
log(sql, name, binds, type_casted_binds, stmt_key) do
|
@@ -647,11 +718,10 @@ module ActiveRecord
|
|
647
718
|
#
|
648
719
|
# Check here for more details:
|
649
720
|
# https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/cache/plancache.c#l573
|
650
|
-
CACHED_PLAN_HEURISTIC = "cached plan must not change result type".freeze
|
651
721
|
def is_cached_plan_failure?(e)
|
652
722
|
pgerror = e.cause
|
653
|
-
|
654
|
-
|
723
|
+
pgerror.result.result_error_field(PG::PG_DIAG_SQLSTATE) == FEATURE_NOT_SUPPORTED &&
|
724
|
+
pgerror.result.result_error_field(PG::PG_DIAG_SOURCE_FUNCTION) == "RevalidateCachedQuery"
|
655
725
|
rescue
|
656
726
|
false
|
657
727
|
end
|
@@ -668,7 +738,7 @@ module ActiveRecord
|
|
668
738
|
|
669
739
|
# Prepare the statement if it hasn't been prepared, return
|
670
740
|
# the statement key.
|
671
|
-
def prepare_statement(sql)
|
741
|
+
def prepare_statement(sql, binds)
|
672
742
|
@lock.synchronize do
|
673
743
|
sql_key = sql_key(sql)
|
674
744
|
unless @statements.key? sql_key
|
@@ -676,7 +746,7 @@ module ActiveRecord
|
|
676
746
|
begin
|
677
747
|
@connection.prepare nextkey, sql
|
678
748
|
rescue => e
|
679
|
-
raise translate_exception_class(e, sql)
|
749
|
+
raise translate_exception_class(e, sql, binds)
|
680
750
|
end
|
681
751
|
# Clear the queue
|
682
752
|
@connection.get_last_result
|
@@ -689,14 +759,10 @@ module ActiveRecord
|
|
689
759
|
# Connects to a PostgreSQL server and sets up the adapter depending on the
|
690
760
|
# connected server's characteristics.
|
691
761
|
def connect
|
692
|
-
@connection =
|
762
|
+
@connection = self.class.new_client(@connection_parameters)
|
693
763
|
configure_connection
|
694
|
-
|
695
|
-
|
696
|
-
raise ActiveRecord::NoDatabaseError
|
697
|
-
else
|
698
|
-
raise
|
699
|
-
end
|
764
|
+
add_pg_encoders
|
765
|
+
add_pg_decoders
|
700
766
|
end
|
701
767
|
|
702
768
|
# Configures the encoding, verbosity, schema search path, and time zone of the connection.
|
@@ -723,6 +789,9 @@ module ActiveRecord
|
|
723
789
|
end
|
724
790
|
end
|
725
791
|
|
792
|
+
# Set interval output format to ISO 8601 for ease of parsing by ActiveSupport::Duration.parse
|
793
|
+
execute("SET intervalstyle = iso_8601", "SCHEMA")
|
794
|
+
|
726
795
|
# SET statements from :variables config hash
|
727
796
|
# https://www.postgresql.org/docs/current/static/sql-set.html
|
728
797
|
variables.map do |k, v|
|
@@ -754,7 +823,7 @@ module ActiveRecord
|
|
754
823
|
# - format_type includes the column size constraint, e.g. varchar(50)
|
755
824
|
# - ::regclass is a function that gives the id for a table name
|
756
825
|
def column_definitions(table_name)
|
757
|
-
query(
|
826
|
+
query(<<~SQL, "SCHEMA")
|
758
827
|
SELECT a.attname, format_type(a.atttypid, a.atttypmod),
|
759
828
|
pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
|
760
829
|
c.collname, col_description(a.attrelid, a.attnum) AS comment
|
@@ -765,7 +834,7 @@ module ActiveRecord
|
|
765
834
|
WHERE a.attrelid = #{quote(quote_table_name(table_name))}::regclass
|
766
835
|
AND a.attnum > 0 AND NOT a.attisdropped
|
767
836
|
ORDER BY a.attnum
|
768
|
-
|
837
|
+
SQL
|
769
838
|
end
|
770
839
|
|
771
840
|
def extract_table_ref_from_insert_sql(sql)
|
@@ -777,10 +846,14 @@ module ActiveRecord
|
|
777
846
|
Arel::Visitors::PostgreSQL.new(self)
|
778
847
|
end
|
779
848
|
|
849
|
+
def build_statement_pool
|
850
|
+
StatementPool.new(@connection, self.class.type_cast_config_to_integer(@config[:statement_limit]))
|
851
|
+
end
|
852
|
+
|
780
853
|
def can_perform_case_insensitive_comparison_for?(column)
|
781
854
|
@case_insensitive_cache ||= {}
|
782
855
|
@case_insensitive_cache[column.sql_type] ||= begin
|
783
|
-
sql =
|
856
|
+
sql = <<~SQL
|
784
857
|
SELECT exists(
|
785
858
|
SELECT * FROM pg_proc
|
786
859
|
WHERE proname = 'lower'
|
@@ -792,7 +865,7 @@ module ActiveRecord
|
|
792
865
|
WHERE proname = 'lower'
|
793
866
|
AND castsource = #{quote column.sql_type}::regtype
|
794
867
|
)
|
795
|
-
|
868
|
+
SQL
|
796
869
|
execute_and_clear(sql, "SCHEMA", []) do |result|
|
797
870
|
result.getvalue(0, 0)
|
798
871
|
end
|
@@ -807,7 +880,22 @@ module ActiveRecord
|
|
807
880
|
@connection.type_map_for_queries = map
|
808
881
|
end
|
809
882
|
|
883
|
+
def update_typemap_for_default_timezone
|
884
|
+
if @default_timezone != ActiveRecord::Base.default_timezone && @timestamp_decoder
|
885
|
+
decoder_class = ActiveRecord::Base.default_timezone == :utc ?
|
886
|
+
PG::TextDecoder::TimestampUtc :
|
887
|
+
PG::TextDecoder::TimestampWithoutTimeZone
|
888
|
+
|
889
|
+
@timestamp_decoder = decoder_class.new(@timestamp_decoder.to_h)
|
890
|
+
@connection.type_map_for_results.add_coder(@timestamp_decoder)
|
891
|
+
@default_timezone = ActiveRecord::Base.default_timezone
|
892
|
+
end
|
893
|
+
end
|
894
|
+
|
810
895
|
def add_pg_decoders
|
896
|
+
@default_timezone = nil
|
897
|
+
@timestamp_decoder = nil
|
898
|
+
|
811
899
|
coders_by_name = {
|
812
900
|
"int2" => PG::TextDecoder::Integer,
|
813
901
|
"int4" => PG::TextDecoder::Integer,
|
@@ -815,10 +903,14 @@ module ActiveRecord
|
|
815
903
|
"oid" => PG::TextDecoder::Integer,
|
816
904
|
"float4" => PG::TextDecoder::Float,
|
817
905
|
"float8" => PG::TextDecoder::Float,
|
906
|
+
"numeric" => PG::TextDecoder::Numeric,
|
818
907
|
"bool" => PG::TextDecoder::Boolean,
|
908
|
+
"timestamp" => PG::TextDecoder::TimestampUtc,
|
909
|
+
"timestamptz" => PG::TextDecoder::TimestampWithTimeZone,
|
819
910
|
}
|
911
|
+
|
820
912
|
known_coder_types = coders_by_name.keys.map { |n| quote(n) }
|
821
|
-
query =
|
913
|
+
query = <<~SQL % known_coder_types.join(", ")
|
822
914
|
SELECT t.oid, t.typname
|
823
915
|
FROM pg_type as t
|
824
916
|
WHERE t.typname IN (%s)
|
@@ -832,6 +924,15 @@ module ActiveRecord
|
|
832
924
|
map = PG::TypeMapByOid.new
|
833
925
|
coders.each { |coder| map.add_coder(coder) }
|
834
926
|
@connection.type_map_for_results = map
|
927
|
+
|
928
|
+
@type_map_for_results = PG::TypeMapByOid.new
|
929
|
+
@type_map_for_results.default_type_map = map
|
930
|
+
@type_map_for_results.add_coder(PG::TextDecoder::Bytea.new(oid: 17, name: "bytea"))
|
931
|
+
@type_map_for_results.add_coder(MoneyDecoder.new(oid: 790, name: "money"))
|
932
|
+
|
933
|
+
# extract timestamp decoder for use in update_typemap_for_default_timezone
|
934
|
+
@timestamp_decoder = coders.find { |coder| coder.name == "timestamp" }
|
935
|
+
update_typemap_for_default_timezone
|
835
936
|
end
|
836
937
|
|
837
938
|
def construct_coder(row, coder_class)
|
@@ -839,6 +940,14 @@ module ActiveRecord
|
|
839
940
|
coder_class.new(oid: row["oid"].to_i, name: row["typname"])
|
840
941
|
end
|
841
942
|
|
943
|
+
class MoneyDecoder < PG::SimpleDecoder # :nodoc:
|
944
|
+
TYPE = OID::Money.new
|
945
|
+
|
946
|
+
def decode(value, tuple = nil, field = nil)
|
947
|
+
TYPE.deserialize(value)
|
948
|
+
end
|
949
|
+
end
|
950
|
+
|
842
951
|
ActiveRecord::Type.add_modifier({ array: true }, OID::Array, adapter: :postgresql)
|
843
952
|
ActiveRecord::Type.add_modifier({ range: true }, OID::Range, adapter: :postgresql)
|
844
953
|
ActiveRecord::Type.register(:bit, OID::Bit, adapter: :postgresql)
|
@@ -851,6 +960,7 @@ module ActiveRecord
|
|
851
960
|
ActiveRecord::Type.register(:enum, OID::Enum, adapter: :postgresql)
|
852
961
|
ActiveRecord::Type.register(:hstore, OID::Hstore, adapter: :postgresql)
|
853
962
|
ActiveRecord::Type.register(:inet, OID::Inet, adapter: :postgresql)
|
963
|
+
ActiveRecord::Type.register(:interval, OID::Interval, adapter: :postgresql)
|
854
964
|
ActiveRecord::Type.register(:jsonb, OID::Jsonb, adapter: :postgresql)
|
855
965
|
ActiveRecord::Type.register(:money, OID::Money, adapter: :postgresql)
|
856
966
|
ActiveRecord::Type.register(:point, OID::Point, adapter: :postgresql)
|