diff options
Diffstat (limited to 'activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb')
-rw-r--r-- | activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb | 67 |
1 files changed, 51 insertions, 16 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 6d25b53b21..00fc69c878 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -1,3 +1,7 @@ +# Make sure we're using pg high enough for type casts and Ruby 2.2+ compatibility +gem 'pg', '~> 0.18' +require 'pg' + require "active_record/connection_adapters/abstract_adapter" require "active_record/connection_adapters/postgresql/column" require "active_record/connection_adapters/postgresql/database_statements" @@ -12,10 +16,6 @@ require "active_record/connection_adapters/statement_pool" require 'arel/visitors/bind_visitor' -# Make sure we're using pg high enough for PGResult#values -gem 'pg', '~> 0.15' -require 'pg' - require 'ipaddr' module ActiveRecord @@ -128,7 +128,7 @@ module ActiveRecord def column_spec_for_primary_key(column) spec = {} if column.serial? - return unless column.sql_type == 'bigint' + return unless column.bigint? spec[:id] = ':bigserial' elsif column.type == :uuid spec[:id] = ':uuid' @@ -145,7 +145,6 @@ module ActiveRecord def prepare_column_options(column) # :nodoc: spec = super spec[:array] = 'true' if column.array? - spec[:default] = "\"#{column.default_function}\"" if column.default_function spec end @@ -154,6 +153,26 @@ module ActiveRecord super + [:array] end + def schema_type(column) + return super unless column.serial? + + if column.bigint? + 'bigserial' + else + 'serial' + end + end + private :schema_type + + def schema_default(column) + if column.default_function + column.default_function.inspect unless column.serial? + else + super + end + end + private :schema_default + # Returns +true+, since this connection adapter supports prepared statement # caching. def supports_statement_cache? @@ -259,8 +278,7 @@ module ActiveRecord @table_alias_length = nil connect - add_pg_decoders - + add_pg_encoders @statements = StatementPool.new @connection, self.class.type_cast_config_to_integer(config.fetch(:statement_limit) { 1000 }) @@ -268,6 +286,8 @@ module ActiveRecord raise "Your version of PostgreSQL (#{postgresql_version}) is too old, please upgrade!" end + add_pg_decoders + @type_map = Type::HashLookupTypeMap.new initialize_type_map(type_map) @local_tz = execute('SHOW TIME ZONE', 'SCHEMA').first["TimeZone"] @@ -574,6 +594,8 @@ module ActiveRecord end def load_additional_types(type_map, oids = nil) # :nodoc: + initializer = OID::TypeMapInitializer.new(type_map) + if supports_ranges? query = <<-SQL SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype @@ -589,11 +611,13 @@ module ActiveRecord if oids query += "WHERE t.oid::integer IN (%s)" % oids.join(", ") + else + query += initializer.query_conditions_for_initial_load(type_map) end - initializer = OID::TypeMapInitializer.new(type_map) - records = execute(query, 'SCHEMA') - initializer.run(records) + execute_and_clear(query, 'SCHEMA', []) do |records| + initializer.run(records) + end end FEATURE_NOT_SUPPORTED = "0A000" #:nodoc: @@ -779,11 +803,20 @@ module ActiveRecord ) end_sql execute_and_clear(sql, "SCHEMA", []) do |result| - result.getvalue(0, 0) == 't' + result.getvalue(0, 0) end end end + def add_pg_encoders + map = PG::TypeMapByClass.new + map[Integer] = PG::TextEncoder::Integer.new + map[TrueClass] = PG::TextEncoder::Boolean.new + map[FalseClass] = PG::TextEncoder::Boolean.new + map[Float] = PG::TextEncoder::Float.new + @connection.type_map_for_queries = map + end + def add_pg_decoders coders_by_name = { 'int2' => PG::TextDecoder::Integer, @@ -794,13 +827,15 @@ module ActiveRecord 'float8' => PG::TextDecoder::Float, 'bool' => PG::TextDecoder::Boolean, } - query = <<-SQL - SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, t.typtype, t.typbasetype + known_coder_types = coders_by_name.keys.map { |n| quote(n) } + query = <<-SQL % known_coder_types.join(", ") + SELECT t.oid, t.typname FROM pg_type as t + WHERE t.typname IN (%s) SQL coders = execute_and_clear(query, "SCHEMA", []) do |result| result - .map { |row| construct_coder(row, coders_by_name['typname']) } + .map { |row| construct_coder(row, coders_by_name[row['typname']]) } .compact end @@ -811,7 +846,7 @@ module ActiveRecord def construct_coder(row, coder_class) return unless coder_class - coder_class.new(oid: row['oid'], name: row['typname']) + coder_class.new(oid: row['oid'].to_i, name: row['typname']) end ActiveRecord::Type.add_modifier({ array: true }, OID::Array, adapter: :postgresql) |