activerecord 4.2.0 → 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 +4 -4
- data/CHANGELOG.md +1537 -789
- 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/aggregations.rb +37 -23
- data/lib/active_record/association_relation.rb +16 -3
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +23 -9
- data/lib/active_record/associations/association_scope.rb +74 -102
- data/lib/active_record/associations/belongs_to_association.rb +26 -29
- 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 +12 -20
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +22 -15
- 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 +61 -33
- data/lib/active_record/associations/collection_proxy.rb +81 -35
- data/lib/active_record/associations/foreign_association.rb +11 -0
- data/lib/active_record/associations/has_many_association.rb +21 -57
- data/lib/active_record/associations/has_many_through_association.rb +15 -45
- data/lib/active_record/associations/has_one_association.rb +13 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +20 -8
- data/lib/active_record/associations/join_dependency.rb +37 -21
- data/lib/active_record/associations/preloader/association.rb +51 -53
- 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/preloader.rb +18 -8
- data/lib/active_record/associations/singular_association.rb +8 -8
- data/lib/active_record/associations/through_association.rb +22 -9
- data/lib/active_record/associations.rb +321 -212
- data/lib/active_record/attribute/user_provided_default.rb +28 -0
- data/lib/active_record/attribute.rb +79 -15
- data/lib/active_record/attribute_assignment.rb +20 -141
- data/lib/active_record/attribute_decorators.rb +6 -5
- data/lib/active_record/attribute_methods/before_type_cast.rb +6 -1
- data/lib/active_record/attribute_methods/dirty.rb +51 -81
- 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 +65 -14
- data/lib/active_record/attribute_methods/write.rb +14 -38
- data/lib/active_record/attribute_methods.rb +70 -45
- data/lib/active_record/attribute_mutation_tracker.rb +70 -0
- data/lib/active_record/attribute_set/builder.rb +37 -15
- data/lib/active_record/attribute_set.rb +34 -3
- data/lib/active_record/attributes.rb +199 -73
- data/lib/active_record/autosave_association.rb +73 -25
- data/lib/active_record/base.rb +35 -27
- 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 +457 -181
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +83 -59
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -9
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -4
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +246 -185
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +438 -136
- data/lib/active_record/connection_adapters/abstract/transaction.rb +53 -40
- data/lib/active_record/connection_adapters/abstract_adapter.rb +166 -66
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +429 -335
- 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 +26 -177
- data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +11 -73
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +27 -56
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -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 -13
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -1
- 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/type_map_initializer.rb +17 -5
- 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/oid.rb +1 -6
- 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 +248 -154
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +258 -170
- 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 +150 -209
- data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
- data/lib/active_record/connection_handling.rb +38 -15
- data/lib/active_record/core.rb +109 -114
- data/lib/active_record/counter_cache.rb +14 -25
- data/lib/active_record/dynamic_matchers.rb +1 -20
- data/lib/active_record/enum.rb +115 -79
- data/lib/active_record/errors.rb +88 -48
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +2 -2
- data/lib/active_record/fixture_set/file.rb +26 -5
- data/lib/active_record/fixtures.rb +84 -46
- data/lib/active_record/gem_version.rb +2 -2
- 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 +46 -0
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +27 -25
- data/lib/active_record/locking/pessimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +43 -21
- data/lib/active_record/migration/command_recorder.rb +59 -18
- data/lib/active_record/migration/compatibility.rb +126 -0
- data/lib/active_record/migration.rb +372 -114
- data/lib/active_record/model_schema.rb +128 -38
- data/lib/active_record/nested_attributes.rb +71 -32
- data/lib/active_record/no_touching.rb +1 -1
- data/lib/active_record/null_relation.rb +16 -8
- data/lib/active_record/persistence.rb +124 -80
- data/lib/active_record/query_cache.rb +15 -18
- data/lib/active_record/querying.rb +10 -9
- data/lib/active_record/railtie.rb +28 -19
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +67 -51
- data/lib/active_record/readonly_attributes.rb +1 -1
- data/lib/active_record/reflection.rb +318 -139
- data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
- data/lib/active_record/relation/batches.rb +139 -34
- data/lib/active_record/relation/calculations.rb +80 -102
- data/lib/active_record/relation/delegation.rb +7 -20
- data/lib/active_record/relation/finder_methods.rb +167 -97
- data/lib/active_record/relation/from_clause.rb +32 -0
- data/lib/active_record/relation/merger.rb +38 -41
- data/lib/active_record/relation/predicate_builder/array_handler.rb +12 -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/predicate_builder.rb +124 -82
- data/lib/active_record/relation/query_attribute.rb +19 -0
- data/lib/active_record/relation/query_methods.rb +323 -257
- data/lib/active_record/relation/record_fetch_warning.rb +49 -0
- data/lib/active_record/relation/spawn_methods.rb +11 -10
- 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/relation.rb +176 -115
- 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 -17
- data/lib/active_record/scoping/default.rb +24 -9
- data/lib/active_record/scoping/named.rb +49 -28
- data/lib/active_record/scoping.rb +32 -15
- 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 +59 -42
- data/lib/active_record/tasks/mysql_database_tasks.rb +32 -26
- data/lib/active_record/tasks/postgresql_database_tasks.rb +29 -9
- 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 +159 -67
- data/lib/active_record/type/adapter_specific_registry.rb +130 -0
- data/lib/active_record/type/date.rb +2 -41
- data/lib/active_record/type/date_time.rb +2 -38
- data/lib/active_record/type/hash_lookup_type_map.rb +8 -2
- 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 +21 -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.rb +66 -17
- data/lib/active_record/type_caster/connection.rb +29 -0
- data/lib/active_record/type_caster/map.rb +19 -0
- data/lib/active_record/type_caster.rb +7 -0
- 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 +29 -18
- data/lib/active_record/validations.rb +33 -32
- data/lib/active_record.rb +9 -2
- 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 -6
- data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -7
- data/lib/rails/generators/active_record/migration.rb +7 -0
- 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 +60 -34
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
- 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 -30
- data/lib/active_record/type/decimal.rb +0 -40
- 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 -55
- 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 -36
- 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 -101
@@ -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.
|
@@ -64,21 +57,20 @@ module ActiveRecord
|
|
64
57
|
# <tt>SET client_min_messages TO <min_messages></tt> call on the connection.
|
65
58
|
# * <tt>:variables</tt> - An optional hash of additional parameters that
|
66
59
|
# will be used in <tt>SET SESSION key = val</tt> calls on the connection.
|
67
|
-
# * <tt>:insert_returning</tt> - An optional boolean to control the use
|
60
|
+
# * <tt>:insert_returning</tt> - An optional boolean to control the use of <tt>RETURNING</tt> for <tt>INSERT</tt> statements
|
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)
|
228
|
-
|
229
|
-
@visitor = Arel::Visitors::PostgreSQL.new self
|
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
|
209
|
+
super(connection, logger, config)
|
235
210
|
|
236
|
-
@connection_parameters
|
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"]
|
@@ -308,25 +286,24 @@ module ActiveRecord
|
|
308
286
|
true
|
309
287
|
end
|
310
288
|
|
311
|
-
# Enable standard-conforming strings if available.
|
312
289
|
def set_standard_conforming_strings
|
313
|
-
|
314
|
-
execute('SET standard_conforming_strings = on', 'SCHEMA') rescue nil
|
315
|
-
ensure
|
316
|
-
self.client_min_messages = old
|
290
|
+
execute('SET standard_conforming_strings = on', 'SCHEMA')
|
317
291
|
end
|
318
292
|
|
319
293
|
def supports_ddl_transactions?
|
320
294
|
true
|
321
295
|
end
|
322
296
|
|
297
|
+
def supports_advisory_locks?
|
298
|
+
true
|
299
|
+
end
|
300
|
+
|
323
301
|
def supports_explain?
|
324
302
|
true
|
325
303
|
end
|
326
304
|
|
327
|
-
# Returns true if pg > 9.1
|
328
305
|
def supports_extensions?
|
329
|
-
|
306
|
+
true
|
330
307
|
end
|
331
308
|
|
332
309
|
# Range datatypes weren't introduced until PostgreSQL 9.2
|
@@ -338,6 +315,20 @@ module ActiveRecord
|
|
338
315
|
postgresql_version >= 90300
|
339
316
|
end
|
340
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
|
+
|
341
332
|
def enable_extension(name)
|
342
333
|
exec_query("CREATE EXTENSION IF NOT EXISTS \"#{name}\"").tap {
|
343
334
|
reload_type_map
|
@@ -404,14 +395,15 @@ module ActiveRecord
|
|
404
395
|
"average" => "avg",
|
405
396
|
}
|
406
397
|
|
407
|
-
|
398
|
+
# Returns the version of the connected PostgreSQL server.
|
399
|
+
def postgresql_version
|
400
|
+
@connection.server_version
|
401
|
+
end
|
408
402
|
|
409
|
-
|
410
|
-
def postgresql_version
|
411
|
-
@connection.server_version
|
412
|
-
end
|
403
|
+
protected
|
413
404
|
|
414
|
-
# See http://www.postgresql.org/docs/
|
405
|
+
# See http://www.postgresql.org/docs/current/static/errcodes-appendix.html
|
406
|
+
VALUE_LIMIT_VIOLATION = "22001"
|
415
407
|
FOREIGN_KEY_VIOLATION = "23503"
|
416
408
|
UNIQUE_VIOLATION = "23505"
|
417
409
|
|
@@ -420,9 +412,11 @@ module ActiveRecord
|
|
420
412
|
|
421
413
|
case exception.result.try(:error_field, PGresult::PG_DIAG_SQLSTATE)
|
422
414
|
when UNIQUE_VIOLATION
|
423
|
-
RecordNotUnique.new(message
|
415
|
+
RecordNotUnique.new(message)
|
424
416
|
when FOREIGN_KEY_VIOLATION
|
425
|
-
InvalidForeignKey.new(message
|
417
|
+
InvalidForeignKey.new(message)
|
418
|
+
when VALUE_LIMIT_VIOLATION
|
419
|
+
ValueTooLong.new(message)
|
426
420
|
else
|
427
421
|
super
|
428
422
|
end
|
@@ -444,11 +438,11 @@ module ActiveRecord
|
|
444
438
|
end
|
445
439
|
|
446
440
|
def initialize_type_map(m) # :nodoc:
|
447
|
-
register_class_with_limit m, 'int2',
|
448
|
-
m
|
449
|
-
m
|
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
|
450
444
|
m.alias_type 'oid', 'int2'
|
451
|
-
m.register_type 'float4',
|
445
|
+
m.register_type 'float4', Type::Float.new
|
452
446
|
m.alias_type 'float8', 'float4'
|
453
447
|
m.register_type 'text', Type::Text.new
|
454
448
|
register_class_with_limit m, 'varchar', Type::String
|
@@ -459,8 +453,7 @@ module ActiveRecord
|
|
459
453
|
register_class_with_limit m, 'bit', OID::Bit
|
460
454
|
register_class_with_limit m, 'varbit', OID::BitVarying
|
461
455
|
m.alias_type 'timestamptz', 'timestamp'
|
462
|
-
m.register_type 'date',
|
463
|
-
m.register_type 'time', OID::Time.new
|
456
|
+
m.register_type 'date', Type::Date.new
|
464
457
|
|
465
458
|
m.register_type 'money', OID::Money.new
|
466
459
|
m.register_type 'bytea', OID::Bytea.new
|
@@ -476,20 +469,18 @@ module ActiveRecord
|
|
476
469
|
m.register_type 'macaddr', OID::SpecializedString.new(:macaddr)
|
477
470
|
m.register_type 'citext', OID::SpecializedString.new(:citext)
|
478
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)
|
479
478
|
|
480
479
|
# FIXME: why are we keeping these types as strings?
|
481
480
|
m.alias_type 'interval', 'varchar'
|
482
|
-
|
483
|
-
m
|
484
|
-
m
|
485
|
-
m.alias_type 'circle', 'varchar'
|
486
|
-
m.alias_type 'lseg', 'varchar'
|
487
|
-
m.alias_type 'box', 'varchar'
|
488
|
-
|
489
|
-
m.register_type 'timestamp' do |_, _, sql_type|
|
490
|
-
precision = extract_precision(sql_type)
|
491
|
-
OID::DateTime.new(precision: precision)
|
492
|
-
end
|
481
|
+
|
482
|
+
register_class_with_precision m, 'time', Type::Time
|
483
|
+
register_class_with_precision m, 'timestamp', OID::DateTime
|
493
484
|
|
494
485
|
m.register_type 'numeric' do |_, fmod, sql_type|
|
495
486
|
precision = extract_precision(sql_type)
|
@@ -526,13 +517,18 @@ module ActiveRecord
|
|
526
517
|
end
|
527
518
|
|
528
519
|
# Extracts the value from a PostgreSQL column default definition.
|
529
|
-
def extract_value_from_default(
|
520
|
+
def extract_value_from_default(default) # :nodoc:
|
530
521
|
case default
|
531
522
|
# Quoted types
|
532
|
-
when /\A[\(B]?'(.*)'
|
533
|
-
|
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
|
534
530
|
# Boolean types
|
535
|
-
when 'true', 'false'
|
531
|
+
when 'true'.freeze, 'false'.freeze
|
536
532
|
default
|
537
533
|
# Numeric types
|
538
534
|
when /\A\(?(-?\d+(\.\d*)?)\)?(::bigint)?\z/
|
@@ -552,10 +548,12 @@ module ActiveRecord
|
|
552
548
|
end
|
553
549
|
|
554
550
|
def has_default_function?(default_value, default) # :nodoc:
|
555
|
-
!default_value && (%r{\w+\(.*\)} === default)
|
551
|
+
!default_value && (%r{\w+\(.*\)|\(.*\)::\w+} === default)
|
556
552
|
end
|
557
553
|
|
558
554
|
def load_additional_types(type_map, oids = nil) # :nodoc:
|
555
|
+
initializer = OID::TypeMapInitializer.new(type_map)
|
556
|
+
|
559
557
|
if supports_ranges?
|
560
558
|
query = <<-SQL
|
561
559
|
SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
|
@@ -571,56 +569,78 @@ module ActiveRecord
|
|
571
569
|
|
572
570
|
if oids
|
573
571
|
query += "WHERE t.oid::integer IN (%s)" % oids.join(", ")
|
572
|
+
else
|
573
|
+
query += initializer.query_conditions_for_initial_load(type_map)
|
574
574
|
end
|
575
575
|
|
576
|
-
|
577
|
-
|
578
|
-
|
576
|
+
execute_and_clear(query, 'SCHEMA', []) do |records|
|
577
|
+
initializer.run(records)
|
578
|
+
end
|
579
579
|
end
|
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
|
@@ -673,7 +687,7 @@ module ActiveRecord
|
|
673
687
|
self.client_min_messages = @config[:min_messages] || 'warning'
|
674
688
|
self.schema_search_path = @config[:schema_search_path] || @config[:schema_order]
|
675
689
|
|
676
|
-
# Use standard-conforming strings
|
690
|
+
# Use standard-conforming strings so we don't have to do the E'...' dance.
|
677
691
|
set_standard_conforming_strings
|
678
692
|
|
679
693
|
# If using Active Record's time zone support configure the connection to return
|
@@ -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
|