activerecord 4.2.11.1 → 5.0.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 +5 -5
- data/CHANGELOG.md +1282 -1195
- data/MIT-LICENSE +2 -2
- data/README.rdoc +7 -8
- data/examples/performance.rb +2 -3
- data/examples/simple.rb +0 -1
- data/lib/active_record.rb +8 -4
- data/lib/active_record/aggregations.rb +35 -24
- data/lib/active_record/association_relation.rb +3 -3
- data/lib/active_record/associations.rb +317 -209
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +11 -9
- data/lib/active_record/associations/association_scope.rb +73 -102
- data/lib/active_record/associations/belongs_to_association.rb +21 -32
- data/lib/active_record/associations/builder/association.rb +28 -34
- data/lib/active_record/associations/builder/belongs_to.rb +43 -18
- data/lib/active_record/associations/builder/collection_association.rb +7 -19
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +14 -11
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +11 -6
- data/lib/active_record/associations/builder/singular_association.rb +3 -10
- data/lib/active_record/associations/collection_association.rb +49 -41
- data/lib/active_record/associations/collection_proxy.rb +67 -27
- data/lib/active_record/associations/foreign_association.rb +1 -1
- data/lib/active_record/associations/has_many_association.rb +20 -71
- data/lib/active_record/associations/has_many_through_association.rb +8 -47
- data/lib/active_record/associations/has_one_association.rb +12 -5
- data/lib/active_record/associations/join_dependency.rb +29 -19
- data/lib/active_record/associations/join_dependency/join_association.rb +16 -10
- data/lib/active_record/associations/preloader.rb +14 -4
- data/lib/active_record/associations/preloader/association.rb +46 -52
- data/lib/active_record/associations/preloader/collection_association.rb +0 -6
- data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
- data/lib/active_record/associations/preloader/has_one.rb +0 -8
- data/lib/active_record/associations/preloader/through_association.rb +27 -14
- data/lib/active_record/associations/singular_association.rb +7 -1
- data/lib/active_record/associations/through_association.rb +11 -3
- data/lib/active_record/attribute.rb +68 -18
- data/lib/active_record/attribute/user_provided_default.rb +28 -0
- data/lib/active_record/attribute_assignment.rb +19 -140
- data/lib/active_record/attribute_decorators.rb +6 -5
- data/lib/active_record/attribute_methods.rb +76 -47
- data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
- data/lib/active_record/attribute_methods/dirty.rb +46 -86
- data/lib/active_record/attribute_methods/primary_key.rb +2 -2
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +31 -59
- data/lib/active_record/attribute_methods/serialization.rb +13 -16
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -14
- data/lib/active_record/attribute_methods/write.rb +13 -37
- data/lib/active_record/attribute_mutation_tracker.rb +70 -0
- data/lib/active_record/attribute_set.rb +30 -3
- data/lib/active_record/attribute_set/builder.rb +6 -4
- data/lib/active_record/attributes.rb +199 -81
- data/lib/active_record/autosave_association.rb +49 -16
- data/lib/active_record/base.rb +32 -23
- data/lib/active_record/callbacks.rb +39 -43
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +20 -8
- data/lib/active_record/collection_cache_key.rb +40 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +452 -182
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -61
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -10
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -185
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +380 -141
- data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
- data/lib/active_record/connection_adapters/abstract_adapter.rb +141 -59
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +401 -370
- data/lib/active_record/connection_adapters/column.rb +28 -43
- data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +29 -166
- data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +10 -72
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +27 -57
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -18
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +234 -148
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +248 -160
- data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +149 -192
- data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
- data/lib/active_record/connection_handling.rb +37 -14
- data/lib/active_record/core.rb +89 -107
- data/lib/active_record/counter_cache.rb +13 -24
- data/lib/active_record/dynamic_matchers.rb +1 -20
- data/lib/active_record/enum.rb +113 -76
- data/lib/active_record/errors.rb +87 -48
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +26 -5
- data/lib/active_record/fixtures.rb +76 -40
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +32 -40
- data/lib/active_record/integration.rb +4 -4
- data/lib/active_record/internal_metadata.rb +56 -0
- data/lib/active_record/legacy_yaml_adapter.rb +18 -2
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +15 -15
- data/lib/active_record/locking/pessimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +43 -21
- data/lib/active_record/migration.rb +363 -133
- data/lib/active_record/migration/command_recorder.rb +59 -18
- data/lib/active_record/migration/compatibility.rb +126 -0
- data/lib/active_record/model_schema.rb +129 -41
- data/lib/active_record/nested_attributes.rb +58 -29
- data/lib/active_record/null_relation.rb +16 -8
- data/lib/active_record/persistence.rb +121 -80
- data/lib/active_record/query_cache.rb +15 -18
- data/lib/active_record/querying.rb +10 -9
- data/lib/active_record/railtie.rb +23 -16
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +69 -46
- data/lib/active_record/readonly_attributes.rb +1 -1
- data/lib/active_record/reflection.rb +282 -115
- data/lib/active_record/relation.rb +176 -116
- data/lib/active_record/relation/batches.rb +139 -34
- data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
- data/lib/active_record/relation/calculations.rb +79 -108
- data/lib/active_record/relation/delegation.rb +7 -20
- data/lib/active_record/relation/finder_methods.rb +163 -81
- data/lib/active_record/relation/from_clause.rb +32 -0
- data/lib/active_record/relation/merger.rb +16 -42
- data/lib/active_record/relation/predicate_builder.rb +120 -107
- data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/query_attribute.rb +19 -0
- data/lib/active_record/relation/query_methods.rb +308 -244
- data/lib/active_record/relation/record_fetch_warning.rb +49 -0
- data/lib/active_record/relation/spawn_methods.rb +4 -7
- data/lib/active_record/relation/where_clause.rb +174 -0
- data/lib/active_record/relation/where_clause_factory.rb +38 -0
- data/lib/active_record/result.rb +4 -3
- data/lib/active_record/runtime_registry.rb +1 -1
- data/lib/active_record/sanitization.rb +95 -66
- data/lib/active_record/schema.rb +26 -22
- data/lib/active_record/schema_dumper.rb +62 -38
- data/lib/active_record/schema_migration.rb +11 -14
- data/lib/active_record/scoping.rb +32 -15
- data/lib/active_record/scoping/default.rb +23 -9
- data/lib/active_record/scoping/named.rb +49 -28
- data/lib/active_record/secure_token.rb +38 -0
- data/lib/active_record/serialization.rb +2 -4
- data/lib/active_record/statement_cache.rb +16 -14
- data/lib/active_record/store.rb +8 -3
- data/lib/active_record/suppressor.rb +58 -0
- data/lib/active_record/table_metadata.rb +68 -0
- data/lib/active_record/tasks/database_tasks.rb +57 -43
- data/lib/active_record/tasks/mysql_database_tasks.rb +6 -14
- data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
- data/lib/active_record/timestamp.rb +20 -9
- data/lib/active_record/touch_later.rb +58 -0
- data/lib/active_record/transactions.rb +138 -56
- data/lib/active_record/type.rb +66 -17
- data/lib/active_record/type/adapter_specific_registry.rb +130 -0
- data/lib/active_record/type/date.rb +2 -45
- data/lib/active_record/type/date_time.rb +2 -49
- data/lib/active_record/type/internal/abstract_json.rb +29 -0
- data/lib/active_record/type/internal/timezone.rb +15 -0
- data/lib/active_record/type/serialized.rb +15 -14
- data/lib/active_record/type/time.rb +10 -16
- data/lib/active_record/type/type_map.rb +4 -4
- data/lib/active_record/type_caster.rb +7 -0
- data/lib/active_record/type_caster/connection.rb +29 -0
- data/lib/active_record/type_caster/map.rb +19 -0
- data/lib/active_record/validations.rb +33 -32
- data/lib/active_record/validations/absence.rb +23 -0
- data/lib/active_record/validations/associated.rb +10 -3
- data/lib/active_record/validations/length.rb +24 -0
- data/lib/active_record/validations/presence.rb +11 -12
- data/lib/active_record/validations/uniqueness.rb +30 -29
- data/lib/rails/generators/active_record/migration.rb +7 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
- data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +32 -15
- data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
- data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
- metadata +59 -34
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -31
- data/lib/active_record/type/decimal.rb +0 -64
- data/lib/active_record/type/decimal_without_scale.rb +0 -11
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -59
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -40
- data/lib/active_record/type/text.rb +0 -11
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/unsigned_integer.rb +0 -15
- data/lib/active_record/type/value.rb +0 -110
@@ -0,0 +1,35 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
class PostgreSQLTypeMetadata < DelegateClass(SqlTypeMetadata)
|
4
|
+
attr_reader :oid, :fmod, :array
|
5
|
+
|
6
|
+
def initialize(type_metadata, oid: nil, fmod: nil)
|
7
|
+
super(type_metadata)
|
8
|
+
@type_metadata = type_metadata
|
9
|
+
@oid = oid
|
10
|
+
@fmod = fmod
|
11
|
+
@array = /\[\]$/ === type_metadata.sql_type
|
12
|
+
end
|
13
|
+
|
14
|
+
def sql_type
|
15
|
+
super.gsub(/\[\]$/, "".freeze)
|
16
|
+
end
|
17
|
+
|
18
|
+
def ==(other)
|
19
|
+
other.is_a?(PostgreSQLTypeMetadata) &&
|
20
|
+
attributes_for_hash == other.attributes_for_hash
|
21
|
+
end
|
22
|
+
alias eql? ==
|
23
|
+
|
24
|
+
def hash
|
25
|
+
attributes_for_hash.hash
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def attributes_for_hash
|
31
|
+
[self.class, @type_metadata, oid, fmod]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -1,31 +1,23 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
require 'active_record/connection_adapters/postgresql/utils'
|
5
|
-
require 'active_record/connection_adapters/postgresql/column'
|
6
|
-
require 'active_record/connection_adapters/postgresql/oid'
|
7
|
-
require 'active_record/connection_adapters/postgresql/quoting'
|
8
|
-
require 'active_record/connection_adapters/postgresql/referential_integrity'
|
9
|
-
require 'active_record/connection_adapters/postgresql/schema_definitions'
|
10
|
-
require 'active_record/connection_adapters/postgresql/schema_statements'
|
11
|
-
require 'active_record/connection_adapters/postgresql/database_statements'
|
12
|
-
|
13
|
-
require 'arel/visitors/bind_visitor'
|
14
|
-
|
15
|
-
# Make sure we're using pg high enough for PGResult#values
|
16
|
-
gem 'pg', '~> 0.15'
|
1
|
+
# Make sure we're using pg high enough for type casts and Ruby 2.2+ compatibility
|
2
|
+
gem 'pg', '~> 0.18'
|
17
3
|
require 'pg'
|
18
4
|
|
19
|
-
require
|
5
|
+
require "active_record/connection_adapters/abstract_adapter"
|
6
|
+
require "active_record/connection_adapters/postgresql/column"
|
7
|
+
require "active_record/connection_adapters/postgresql/database_statements"
|
8
|
+
require "active_record/connection_adapters/postgresql/explain_pretty_printer"
|
9
|
+
require "active_record/connection_adapters/postgresql/oid"
|
10
|
+
require "active_record/connection_adapters/postgresql/quoting"
|
11
|
+
require "active_record/connection_adapters/postgresql/referential_integrity"
|
12
|
+
require "active_record/connection_adapters/postgresql/schema_definitions"
|
13
|
+
require "active_record/connection_adapters/postgresql/schema_dumper"
|
14
|
+
require "active_record/connection_adapters/postgresql/schema_statements"
|
15
|
+
require "active_record/connection_adapters/postgresql/type_metadata"
|
16
|
+
require "active_record/connection_adapters/postgresql/utils"
|
17
|
+
require "active_record/connection_adapters/statement_pool"
|
20
18
|
|
21
19
|
module ActiveRecord
|
22
20
|
module ConnectionHandling # :nodoc:
|
23
|
-
VALID_CONN_PARAMS = [:host, :hostaddr, :port, :dbname, :user, :password, :connect_timeout,
|
24
|
-
:client_encoding, :options, :application_name, :fallback_application_name,
|
25
|
-
:keepalives, :keepalives_idle, :keepalives_interval, :keepalives_count,
|
26
|
-
:tty, :sslmode, :requiressl, :sslcompression, :sslcert, :sslkey,
|
27
|
-
:sslrootcert, :sslcrl, :requirepeer, :krbsrvname, :gsslib, :service]
|
28
|
-
|
29
21
|
# Establishes a connection to the database that's used by all Active Record objects
|
30
22
|
def postgresql_connection(config)
|
31
23
|
conn_params = config.symbolize_keys
|
@@ -37,7 +29,8 @@ module ActiveRecord
|
|
37
29
|
conn_params[:dbname] = conn_params.delete(:database) if conn_params[:database]
|
38
30
|
|
39
31
|
# Forward only valid config params to PGconn.connect.
|
40
|
-
|
32
|
+
valid_conn_param_keys = PGconn.conndefaults_hash.keys + [:requiressl]
|
33
|
+
conn_params.slice!(*valid_conn_param_keys)
|
41
34
|
|
42
35
|
# The postgres drivers don't allow the creation of an unconnected PGconn object,
|
43
36
|
# so just pass a nil connection object for the time being.
|
@@ -68,17 +61,16 @@ module ActiveRecord
|
|
68
61
|
# defaults to true.
|
69
62
|
#
|
70
63
|
# Any further options are used as connection parameters to libpq. See
|
71
|
-
# http://www.postgresql.org/docs/
|
64
|
+
# http://www.postgresql.org/docs/current/static/libpq-connect.html for the
|
72
65
|
# list of parameters.
|
73
66
|
#
|
74
67
|
# In addition, default connection parameters of libpq can be set per environment variables.
|
75
|
-
# See http://www.postgresql.org/docs/
|
68
|
+
# See http://www.postgresql.org/docs/current/static/libpq-envars.html .
|
76
69
|
class PostgreSQLAdapter < AbstractAdapter
|
77
70
|
ADAPTER_NAME = 'PostgreSQL'.freeze
|
78
71
|
|
79
72
|
NATIVE_DATABASE_TYPES = {
|
80
73
|
primary_key: "serial primary key",
|
81
|
-
bigserial: "bigserial",
|
82
74
|
string: { name: "character varying" },
|
83
75
|
text: { name: "text" },
|
84
76
|
integer: { name: "integer" },
|
@@ -95,7 +87,6 @@ module ActiveRecord
|
|
95
87
|
int8range: { name: "int8range" },
|
96
88
|
binary: { name: "bytea" },
|
97
89
|
boolean: { name: "boolean" },
|
98
|
-
bigint: { name: "bigint" },
|
99
90
|
xml: { name: "xml" },
|
100
91
|
tsvector: { name: "tsvector" },
|
101
92
|
hstore: { name: "hstore" },
|
@@ -108,6 +99,12 @@ module ActiveRecord
|
|
108
99
|
ltree: { name: "ltree" },
|
109
100
|
citext: { name: "citext" },
|
110
101
|
point: { name: "point" },
|
102
|
+
line: { name: "line" },
|
103
|
+
lseg: { name: "lseg" },
|
104
|
+
box: { name: "box" },
|
105
|
+
path: { name: "path" },
|
106
|
+
polygon: { name: "polygon" },
|
107
|
+
circle: { name: "circle" },
|
111
108
|
bit: { name: "bit" },
|
112
109
|
bit_varying: { name: "bit varying" },
|
113
110
|
money: { name: "money" },
|
@@ -119,27 +116,17 @@ module ActiveRecord
|
|
119
116
|
include PostgreSQL::ReferentialIntegrity
|
120
117
|
include PostgreSQL::SchemaStatements
|
121
118
|
include PostgreSQL::DatabaseStatements
|
122
|
-
include
|
119
|
+
include PostgreSQL::ColumnDumper
|
123
120
|
|
124
121
|
def schema_creation # :nodoc:
|
125
122
|
PostgreSQL::SchemaCreation.new self
|
126
123
|
end
|
127
124
|
|
128
|
-
|
129
|
-
|
130
|
-
def prepare_column_options(column, types) # :nodoc:
|
131
|
-
spec = super
|
132
|
-
spec[:array] = 'true' if column.respond_to?(:array) && column.array
|
133
|
-
spec[:default] = "\"#{column.default_function}\"" if column.default_function
|
134
|
-
spec
|
135
|
-
end
|
136
|
-
|
137
|
-
# Adds +:array+ as a valid migration key
|
138
|
-
def migration_keys
|
139
|
-
super + [:array]
|
125
|
+
def arel_visitor # :nodoc:
|
126
|
+
Arel::Visitors::PostgreSQL.new(self)
|
140
127
|
end
|
141
128
|
|
142
|
-
# Returns
|
129
|
+
# Returns true, since this connection adapter supports prepared statement
|
143
130
|
# caching.
|
144
131
|
def supports_statement_cache?
|
145
132
|
true
|
@@ -153,6 +140,10 @@ module ActiveRecord
|
|
153
140
|
true
|
154
141
|
end
|
155
142
|
|
143
|
+
def supports_expression_index?
|
144
|
+
true
|
145
|
+
end
|
146
|
+
|
156
147
|
def supports_transaction_isolation?
|
157
148
|
true
|
158
149
|
end
|
@@ -165,52 +156,43 @@ module ActiveRecord
|
|
165
156
|
true
|
166
157
|
end
|
167
158
|
|
159
|
+
def supports_datetime_with_precision?
|
160
|
+
true
|
161
|
+
end
|
162
|
+
|
163
|
+
def supports_json?
|
164
|
+
postgresql_version >= 90200
|
165
|
+
end
|
166
|
+
|
167
|
+
def supports_comments?
|
168
|
+
true
|
169
|
+
end
|
170
|
+
|
171
|
+
def supports_savepoints?
|
172
|
+
true
|
173
|
+
end
|
174
|
+
|
168
175
|
def index_algorithms
|
169
176
|
{ concurrently: 'CONCURRENTLY' }
|
170
177
|
end
|
171
178
|
|
172
179
|
class StatementPool < ConnectionAdapters::StatementPool
|
173
180
|
def initialize(connection, max)
|
174
|
-
super
|
181
|
+
super(max)
|
182
|
+
@connection = connection
|
175
183
|
@counter = 0
|
176
|
-
@cache = Hash.new { |h,pid| h[pid] = {} }
|
177
184
|
end
|
178
185
|
|
179
|
-
def each(&block); cache.each(&block); end
|
180
|
-
def key?(key); cache.key?(key); end
|
181
|
-
def [](key); cache[key]; end
|
182
|
-
def length; cache.length; end
|
183
|
-
|
184
186
|
def next_key
|
185
187
|
"a#{@counter + 1}"
|
186
188
|
end
|
187
189
|
|
188
190
|
def []=(sql, key)
|
189
|
-
|
190
|
-
dealloc(cache.shift.last)
|
191
|
-
end
|
192
|
-
@counter += 1
|
193
|
-
cache[sql] = key
|
194
|
-
end
|
195
|
-
|
196
|
-
def clear
|
197
|
-
cache.each_value do |stmt_key|
|
198
|
-
dealloc stmt_key
|
199
|
-
end
|
200
|
-
cache.clear
|
201
|
-
end
|
202
|
-
|
203
|
-
def delete(sql_key)
|
204
|
-
dealloc cache[sql_key]
|
205
|
-
cache.delete sql_key
|
191
|
+
super.tap { @counter += 1 }
|
206
192
|
end
|
207
193
|
|
208
194
|
private
|
209
195
|
|
210
|
-
def cache
|
211
|
-
@cache[Process.pid]
|
212
|
-
end
|
213
|
-
|
214
196
|
def dealloc(key)
|
215
197
|
@connection.query "DEALLOCATE #{key}" if connection_active?
|
216
198
|
end
|
@@ -224,29 +206,25 @@ module ActiveRecord
|
|
224
206
|
|
225
207
|
# Initializes and connects a PostgreSQL adapter.
|
226
208
|
def initialize(connection, logger, connection_parameters, config)
|
227
|
-
super(connection, logger)
|
209
|
+
super(connection, logger, config)
|
228
210
|
|
229
|
-
@
|
230
|
-
if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
|
231
|
-
@prepared_statements = true
|
232
|
-
else
|
233
|
-
@prepared_statements = false
|
234
|
-
end
|
235
|
-
|
236
|
-
@connection_parameters, @config = connection_parameters, config
|
211
|
+
@connection_parameters = connection_parameters
|
237
212
|
|
238
213
|
# @local_tz is initialized as nil to avoid warnings when connect tries to use it
|
239
214
|
@local_tz = nil
|
240
215
|
@table_alias_length = nil
|
241
216
|
|
242
217
|
connect
|
218
|
+
add_pg_encoders
|
243
219
|
@statements = StatementPool.new @connection,
|
244
|
-
self.class.type_cast_config_to_integer(config
|
220
|
+
self.class.type_cast_config_to_integer(config[:statement_limit])
|
245
221
|
|
246
|
-
if postgresql_version <
|
247
|
-
raise "Your version of PostgreSQL (#{postgresql_version}) is too old
|
222
|
+
if postgresql_version < 90100
|
223
|
+
raise "Your version of PostgreSQL (#{postgresql_version}) is too old. Active Record supports PostgreSQL >= 9.1."
|
248
224
|
end
|
249
225
|
|
226
|
+
add_pg_decoders
|
227
|
+
|
250
228
|
@type_map = Type::HashLookupTypeMap.new
|
251
229
|
initialize_type_map(type_map)
|
252
230
|
@local_tz = execute('SHOW TIME ZONE', 'SCHEMA').first["TimeZone"]
|
@@ -316,13 +294,16 @@ module ActiveRecord
|
|
316
294
|
true
|
317
295
|
end
|
318
296
|
|
297
|
+
def supports_advisory_locks?
|
298
|
+
true
|
299
|
+
end
|
300
|
+
|
319
301
|
def supports_explain?
|
320
302
|
true
|
321
303
|
end
|
322
304
|
|
323
|
-
# Returns true if pg > 9.1
|
324
305
|
def supports_extensions?
|
325
|
-
|
306
|
+
true
|
326
307
|
end
|
327
308
|
|
328
309
|
# Range datatypes weren't introduced until PostgreSQL 9.2
|
@@ -334,6 +315,20 @@ module ActiveRecord
|
|
334
315
|
postgresql_version >= 90300
|
335
316
|
end
|
336
317
|
|
318
|
+
def get_advisory_lock(lock_id) # :nodoc:
|
319
|
+
unless lock_id.is_a?(Integer) && lock_id.bit_length <= 63
|
320
|
+
raise(ArgumentError, "Postgres requires advisory lock ids to be a signed 64 bit integer")
|
321
|
+
end
|
322
|
+
select_value("SELECT pg_try_advisory_lock(#{lock_id});")
|
323
|
+
end
|
324
|
+
|
325
|
+
def release_advisory_lock(lock_id) # :nodoc:
|
326
|
+
unless lock_id.is_a?(Integer) && lock_id.bit_length <= 63
|
327
|
+
raise(ArgumentError, "Postgres requires advisory lock ids to be a signed 64 bit integer")
|
328
|
+
end
|
329
|
+
select_value("SELECT pg_advisory_unlock(#{lock_id})")
|
330
|
+
end
|
331
|
+
|
337
332
|
def enable_extension(name)
|
338
333
|
exec_query("CREATE EXTENSION IF NOT EXISTS \"#{name}\"").tap {
|
339
334
|
reload_type_map
|
@@ -400,14 +395,15 @@ module ActiveRecord
|
|
400
395
|
"average" => "avg",
|
401
396
|
}
|
402
397
|
|
403
|
-
|
398
|
+
# Returns the version of the connected PostgreSQL server.
|
399
|
+
def postgresql_version
|
400
|
+
@connection.server_version
|
401
|
+
end
|
404
402
|
|
405
|
-
|
406
|
-
def postgresql_version
|
407
|
-
@connection.server_version
|
408
|
-
end
|
403
|
+
protected
|
409
404
|
|
410
|
-
# See http://www.postgresql.org/docs/
|
405
|
+
# See http://www.postgresql.org/docs/current/static/errcodes-appendix.html
|
406
|
+
VALUE_LIMIT_VIOLATION = "22001"
|
411
407
|
FOREIGN_KEY_VIOLATION = "23503"
|
412
408
|
UNIQUE_VIOLATION = "23505"
|
413
409
|
|
@@ -416,9 +412,11 @@ module ActiveRecord
|
|
416
412
|
|
417
413
|
case exception.result.try(:error_field, PGresult::PG_DIAG_SQLSTATE)
|
418
414
|
when UNIQUE_VIOLATION
|
419
|
-
RecordNotUnique.new(message
|
415
|
+
RecordNotUnique.new(message)
|
420
416
|
when FOREIGN_KEY_VIOLATION
|
421
|
-
InvalidForeignKey.new(message
|
417
|
+
InvalidForeignKey.new(message)
|
418
|
+
when VALUE_LIMIT_VIOLATION
|
419
|
+
ValueTooLong.new(message)
|
422
420
|
else
|
423
421
|
super
|
424
422
|
end
|
@@ -440,11 +438,11 @@ module ActiveRecord
|
|
440
438
|
end
|
441
439
|
|
442
440
|
def initialize_type_map(m) # :nodoc:
|
443
|
-
register_class_with_limit m, 'int2',
|
444
|
-
register_class_with_limit m, 'int4',
|
445
|
-
register_class_with_limit m, 'int8',
|
441
|
+
register_class_with_limit m, 'int2', Type::Integer
|
442
|
+
register_class_with_limit m, 'int4', Type::Integer
|
443
|
+
register_class_with_limit m, 'int8', Type::Integer
|
446
444
|
m.alias_type 'oid', 'int2'
|
447
|
-
m.register_type 'float4',
|
445
|
+
m.register_type 'float4', Type::Float.new
|
448
446
|
m.alias_type 'float8', 'float4'
|
449
447
|
m.register_type 'text', Type::Text.new
|
450
448
|
register_class_with_limit m, 'varchar', Type::String
|
@@ -455,8 +453,7 @@ module ActiveRecord
|
|
455
453
|
register_class_with_limit m, 'bit', OID::Bit
|
456
454
|
register_class_with_limit m, 'varbit', OID::BitVarying
|
457
455
|
m.alias_type 'timestamptz', 'timestamp'
|
458
|
-
m.register_type 'date',
|
459
|
-
m.register_type 'time', OID::Time.new
|
456
|
+
m.register_type 'date', Type::Date.new
|
460
457
|
|
461
458
|
m.register_type 'money', OID::Money.new
|
462
459
|
m.register_type 'bytea', OID::Bytea.new
|
@@ -472,20 +469,18 @@ module ActiveRecord
|
|
472
469
|
m.register_type 'macaddr', OID::SpecializedString.new(:macaddr)
|
473
470
|
m.register_type 'citext', OID::SpecializedString.new(:citext)
|
474
471
|
m.register_type 'ltree', OID::SpecializedString.new(:ltree)
|
472
|
+
m.register_type 'line', OID::SpecializedString.new(:line)
|
473
|
+
m.register_type 'lseg', OID::SpecializedString.new(:lseg)
|
474
|
+
m.register_type 'box', OID::SpecializedString.new(:box)
|
475
|
+
m.register_type 'path', OID::SpecializedString.new(:path)
|
476
|
+
m.register_type 'polygon', OID::SpecializedString.new(:polygon)
|
477
|
+
m.register_type 'circle', OID::SpecializedString.new(:circle)
|
475
478
|
|
476
479
|
# FIXME: why are we keeping these types as strings?
|
477
480
|
m.alias_type 'interval', 'varchar'
|
478
|
-
|
479
|
-
m
|
480
|
-
m
|
481
|
-
m.alias_type 'circle', 'varchar'
|
482
|
-
m.alias_type 'lseg', 'varchar'
|
483
|
-
m.alias_type 'box', 'varchar'
|
484
|
-
|
485
|
-
m.register_type 'timestamp' do |_, _, sql_type|
|
486
|
-
precision = extract_precision(sql_type)
|
487
|
-
OID::DateTime.new(precision: precision)
|
488
|
-
end
|
481
|
+
|
482
|
+
register_class_with_precision m, 'time', Type::Time
|
483
|
+
register_class_with_precision m, 'timestamp', OID::DateTime
|
489
484
|
|
490
485
|
m.register_type 'numeric' do |_, fmod, sql_type|
|
491
486
|
precision = extract_precision(sql_type)
|
@@ -522,13 +517,18 @@ module ActiveRecord
|
|
522
517
|
end
|
523
518
|
|
524
519
|
# Extracts the value from a PostgreSQL column default definition.
|
525
|
-
def extract_value_from_default(
|
520
|
+
def extract_value_from_default(default) # :nodoc:
|
526
521
|
case default
|
527
522
|
# Quoted types
|
528
|
-
when /\A[\(B]?'(.*)'
|
529
|
-
|
523
|
+
when /\A[\(B]?'(.*)'.*::"?([\w. ]+)"?(?:\[\])?\z/m
|
524
|
+
# The default 'now'::date is CURRENT_DATE
|
525
|
+
if $1 == "now".freeze && $2 == "date".freeze
|
526
|
+
nil
|
527
|
+
else
|
528
|
+
$1.gsub("''".freeze, "'".freeze)
|
529
|
+
end
|
530
530
|
# Boolean types
|
531
|
-
when 'true', 'false'
|
531
|
+
when 'true'.freeze, 'false'.freeze
|
532
532
|
default
|
533
533
|
# Numeric types
|
534
534
|
when /\A\(?(-?\d+(\.\d*)?)\)?(::bigint)?\z/
|
@@ -548,7 +548,7 @@ module ActiveRecord
|
|
548
548
|
end
|
549
549
|
|
550
550
|
def has_default_function?(default_value, default) # :nodoc:
|
551
|
-
!default_value && (%r{\w+\(.*\)} === default)
|
551
|
+
!default_value && (%r{\w+\(.*\)|\(.*\)::\w+} === default)
|
552
552
|
end
|
553
553
|
|
554
554
|
def load_additional_types(type_map, oids = nil) # :nodoc:
|
@@ -580,47 +580,67 @@ module ActiveRecord
|
|
580
580
|
|
581
581
|
FEATURE_NOT_SUPPORTED = "0A000" #:nodoc:
|
582
582
|
|
583
|
-
def execute_and_clear(sql, name, binds)
|
584
|
-
|
585
|
-
|
583
|
+
def execute_and_clear(sql, name, binds, prepare: false)
|
584
|
+
if without_prepared_statement?(binds)
|
585
|
+
result = exec_no_cache(sql, name, [])
|
586
|
+
elsif !prepare
|
587
|
+
result = exec_no_cache(sql, name, binds)
|
588
|
+
else
|
589
|
+
result = exec_cache(sql, name, binds)
|
590
|
+
end
|
586
591
|
ret = yield result
|
587
592
|
result.clear
|
588
593
|
ret
|
589
594
|
end
|
590
595
|
|
591
596
|
def exec_no_cache(sql, name, binds)
|
592
|
-
|
597
|
+
type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) }
|
598
|
+
log(sql, name, binds) { @connection.async_exec(sql, type_casted_binds) }
|
593
599
|
end
|
594
600
|
|
595
601
|
def exec_cache(sql, name, binds)
|
596
602
|
stmt_key = prepare_statement(sql)
|
597
|
-
type_casted_binds = binds.map { |
|
598
|
-
[col, type_cast(val, col)]
|
599
|
-
}
|
603
|
+
type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) }
|
600
604
|
|
601
|
-
log(sql, name,
|
602
|
-
@connection.exec_prepared(stmt_key, type_casted_binds
|
605
|
+
log(sql, name, binds, stmt_key) do
|
606
|
+
@connection.exec_prepared(stmt_key, type_casted_binds)
|
603
607
|
end
|
604
608
|
rescue ActiveRecord::StatementInvalid => e
|
605
|
-
|
606
|
-
|
607
|
-
#
|
608
|
-
#
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
rescue
|
614
|
-
raise e
|
615
|
-
end
|
616
|
-
if FEATURE_NOT_SUPPORTED == code
|
609
|
+
raise unless is_cached_plan_failure?(e)
|
610
|
+
|
611
|
+
# Nothing we can do if we are in a transaction because all commands
|
612
|
+
# will raise InFailedSQLTransaction
|
613
|
+
if in_transaction?
|
614
|
+
raise ActiveRecord::PreparedStatementCacheExpired.new(e.cause.message)
|
615
|
+
else
|
616
|
+
# outside of transactions we can simply flush this query and retry
|
617
617
|
@statements.delete sql_key(sql)
|
618
618
|
retry
|
619
|
-
else
|
620
|
-
raise e
|
621
619
|
end
|
622
620
|
end
|
623
621
|
|
622
|
+
# Annoyingly, the code for prepared statements whose return value may
|
623
|
+
# have changed is FEATURE_NOT_SUPPORTED.
|
624
|
+
#
|
625
|
+
# This covers various different error types so we need to do additional
|
626
|
+
# work to classify the exception definitively as a
|
627
|
+
# ActiveRecord::PreparedStatementCacheExpired
|
628
|
+
#
|
629
|
+
# Check here for more details:
|
630
|
+
# http://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/cache/plancache.c#l573
|
631
|
+
CACHED_PLAN_HEURISTIC = 'cached plan must not change result type'.freeze
|
632
|
+
def is_cached_plan_failure?(e)
|
633
|
+
pgerror = e.cause
|
634
|
+
code = pgerror.result.result_error_field(PGresult::PG_DIAG_SQLSTATE)
|
635
|
+
code == FEATURE_NOT_SUPPORTED && pgerror.message.include?(CACHED_PLAN_HEURISTIC)
|
636
|
+
rescue
|
637
|
+
false
|
638
|
+
end
|
639
|
+
|
640
|
+
def in_transaction?
|
641
|
+
open_transactions > 0
|
642
|
+
end
|
643
|
+
|
624
644
|
# Returns the statement identifier for the client side cache
|
625
645
|
# of statements
|
626
646
|
def sql_key(sql)
|
@@ -649,16 +669,10 @@ module ActiveRecord
|
|
649
669
|
# connected server's characteristics.
|
650
670
|
def connect
|
651
671
|
@connection = PGconn.connect(@connection_parameters)
|
652
|
-
|
653
|
-
# Money type has a fixed precision of 10 in PostgreSQL 8.2 and below, and as of
|
654
|
-
# PostgreSQL 8.3 it has a fixed precision of 19. PostgreSQLColumn.extract_precision
|
655
|
-
# should know about this but can't detect it there, so deal with it here.
|
656
|
-
OID::Money.precision = (postgresql_version >= 80300) ? 19 : 10
|
657
|
-
|
658
672
|
configure_connection
|
659
673
|
rescue ::PG::Error => error
|
660
674
|
if error.message.include?("does not exist")
|
661
|
-
raise ActiveRecord::NoDatabaseError
|
675
|
+
raise ActiveRecord::NoDatabaseError
|
662
676
|
else
|
663
677
|
raise
|
664
678
|
end
|
@@ -686,7 +700,7 @@ module ActiveRecord
|
|
686
700
|
end
|
687
701
|
|
688
702
|
# SET statements from :variables config hash
|
689
|
-
# http://www.postgresql.org/docs/
|
703
|
+
# http://www.postgresql.org/docs/current/static/sql-set.html
|
690
704
|
variables = @config[:variables] || {}
|
691
705
|
variables.map do |k, v|
|
692
706
|
if v == ':default' || v == :default
|
@@ -699,22 +713,14 @@ module ActiveRecord
|
|
699
713
|
end
|
700
714
|
|
701
715
|
# Returns the current ID of a table's sequence.
|
702
|
-
def
|
703
|
-
Integer(last_insert_id_value(sequence_name))
|
704
|
-
end
|
705
|
-
|
706
|
-
def last_insert_id_value(sequence_name)
|
707
|
-
last_insert_id_result(sequence_name).rows.first.first
|
708
|
-
end
|
709
|
-
|
710
|
-
def last_insert_id_result(sequence_name) #:nodoc:
|
716
|
+
def last_insert_id_result(sequence_name) # :nodoc:
|
711
717
|
exec_query("SELECT currval('#{sequence_name}')", 'SQL')
|
712
718
|
end
|
713
719
|
|
714
720
|
# Returns the list of a table's column names, data types, and default values.
|
715
721
|
#
|
716
722
|
# The underlying query is roughly:
|
717
|
-
# SELECT column.name, column.type, default.value
|
723
|
+
# SELECT column.name, column.type, default.value, column.comment
|
718
724
|
# FROM column LEFT JOIN default
|
719
725
|
# ON column.table_id = default.table_id
|
720
726
|
# AND column.num = default.column_num
|
@@ -730,9 +736,12 @@ module ActiveRecord
|
|
730
736
|
# - format_type includes the column size constraint, e.g. varchar(50)
|
731
737
|
# - ::regclass is a function that gives the id for a table name
|
732
738
|
def column_definitions(table_name) # :nodoc:
|
733
|
-
|
739
|
+
query(<<-end_sql, 'SCHEMA')
|
734
740
|
SELECT a.attname, format_type(a.atttypid, a.atttypmod),
|
735
|
-
pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
|
741
|
+
pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
|
742
|
+
(SELECT c.collname FROM pg_collation c, pg_type t
|
743
|
+
WHERE c.oid = a.attcollation AND t.oid = a.atttypid AND a.attcollation <> t.typcollation),
|
744
|
+
col_description(a.attrelid, a.attnum) AS comment
|
736
745
|
FROM pg_attribute a LEFT JOIN pg_attrdef d
|
737
746
|
ON a.attrelid = d.adrelid AND a.attnum = d.adnum
|
738
747
|
WHERE a.attrelid = '#{quote_table_name(table_name)}'::regclass
|
@@ -742,13 +751,92 @@ module ActiveRecord
|
|
742
751
|
end
|
743
752
|
|
744
753
|
def extract_table_ref_from_insert_sql(sql) # :nodoc:
|
745
|
-
sql[/into\s
|
754
|
+
sql[/into\s("[A-Za-z0-9_."\[\]\s]+"|[A-Za-z0-9_."\[\]]+)\s*/im]
|
746
755
|
$1.strip if $1
|
747
756
|
end
|
748
757
|
|
749
|
-
def create_table_definition(
|
750
|
-
PostgreSQL::TableDefinition.new
|
758
|
+
def create_table_definition(*args) # :nodoc:
|
759
|
+
PostgreSQL::TableDefinition.new(*args)
|
760
|
+
end
|
761
|
+
|
762
|
+
def can_perform_case_insensitive_comparison_for?(column)
|
763
|
+
@case_insensitive_cache ||= {}
|
764
|
+
@case_insensitive_cache[column.sql_type] ||= begin
|
765
|
+
sql = <<-end_sql
|
766
|
+
SELECT exists(
|
767
|
+
SELECT * FROM pg_proc
|
768
|
+
INNER JOIN pg_cast
|
769
|
+
ON casttarget::text::oidvector = proargtypes
|
770
|
+
WHERE proname = 'lower'
|
771
|
+
AND castsource = '#{column.sql_type}'::regtype::oid
|
772
|
+
)
|
773
|
+
end_sql
|
774
|
+
execute_and_clear(sql, "SCHEMA", []) do |result|
|
775
|
+
result.getvalue(0, 0)
|
776
|
+
end
|
777
|
+
end
|
751
778
|
end
|
779
|
+
|
780
|
+
def add_pg_encoders
|
781
|
+
map = PG::TypeMapByClass.new
|
782
|
+
map[Integer] = PG::TextEncoder::Integer.new
|
783
|
+
map[TrueClass] = PG::TextEncoder::Boolean.new
|
784
|
+
map[FalseClass] = PG::TextEncoder::Boolean.new
|
785
|
+
map[Float] = PG::TextEncoder::Float.new
|
786
|
+
@connection.type_map_for_queries = map
|
787
|
+
end
|
788
|
+
|
789
|
+
def add_pg_decoders
|
790
|
+
coders_by_name = {
|
791
|
+
'int2' => PG::TextDecoder::Integer,
|
792
|
+
'int4' => PG::TextDecoder::Integer,
|
793
|
+
'int8' => PG::TextDecoder::Integer,
|
794
|
+
'oid' => PG::TextDecoder::Integer,
|
795
|
+
'float4' => PG::TextDecoder::Float,
|
796
|
+
'float8' => PG::TextDecoder::Float,
|
797
|
+
'bool' => PG::TextDecoder::Boolean,
|
798
|
+
}
|
799
|
+
known_coder_types = coders_by_name.keys.map { |n| quote(n) }
|
800
|
+
query = <<-SQL % known_coder_types.join(", ")
|
801
|
+
SELECT t.oid, t.typname
|
802
|
+
FROM pg_type as t
|
803
|
+
WHERE t.typname IN (%s)
|
804
|
+
SQL
|
805
|
+
coders = execute_and_clear(query, "SCHEMA", []) do |result|
|
806
|
+
result
|
807
|
+
.map { |row| construct_coder(row, coders_by_name[row['typname']]) }
|
808
|
+
.compact
|
809
|
+
end
|
810
|
+
|
811
|
+
map = PG::TypeMapByOid.new
|
812
|
+
coders.each { |coder| map.add_coder(coder) }
|
813
|
+
@connection.type_map_for_results = map
|
814
|
+
end
|
815
|
+
|
816
|
+
def construct_coder(row, coder_class)
|
817
|
+
return unless coder_class
|
818
|
+
coder_class.new(oid: row['oid'].to_i, name: row['typname'])
|
819
|
+
end
|
820
|
+
|
821
|
+
ActiveRecord::Type.add_modifier({ array: true }, OID::Array, adapter: :postgresql)
|
822
|
+
ActiveRecord::Type.add_modifier({ range: true }, OID::Range, adapter: :postgresql)
|
823
|
+
ActiveRecord::Type.register(:bit, OID::Bit, adapter: :postgresql)
|
824
|
+
ActiveRecord::Type.register(:bit_varying, OID::BitVarying, adapter: :postgresql)
|
825
|
+
ActiveRecord::Type.register(:binary, OID::Bytea, adapter: :postgresql)
|
826
|
+
ActiveRecord::Type.register(:cidr, OID::Cidr, adapter: :postgresql)
|
827
|
+
ActiveRecord::Type.register(:datetime, OID::DateTime, adapter: :postgresql)
|
828
|
+
ActiveRecord::Type.register(:decimal, OID::Decimal, adapter: :postgresql)
|
829
|
+
ActiveRecord::Type.register(:enum, OID::Enum, adapter: :postgresql)
|
830
|
+
ActiveRecord::Type.register(:hstore, OID::Hstore, adapter: :postgresql)
|
831
|
+
ActiveRecord::Type.register(:inet, OID::Inet, adapter: :postgresql)
|
832
|
+
ActiveRecord::Type.register(:json, OID::Json, adapter: :postgresql)
|
833
|
+
ActiveRecord::Type.register(:jsonb, OID::Jsonb, adapter: :postgresql)
|
834
|
+
ActiveRecord::Type.register(:money, OID::Money, adapter: :postgresql)
|
835
|
+
ActiveRecord::Type.register(:point, OID::Rails51Point, adapter: :postgresql)
|
836
|
+
ActiveRecord::Type.register(:legacy_point, OID::Point, adapter: :postgresql)
|
837
|
+
ActiveRecord::Type.register(:uuid, OID::Uuid, adapter: :postgresql)
|
838
|
+
ActiveRecord::Type.register(:vector, OID::Vector, adapter: :postgresql)
|
839
|
+
ActiveRecord::Type.register(:xml, OID::Xml, adapter: :postgresql)
|
752
840
|
end
|
753
841
|
end
|
754
842
|
end
|