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 | 90 |
1 files changed, 80 insertions, 10 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index ab970e183a..6d25b53b21 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -180,6 +180,10 @@ module ActiveRecord true end + def supports_datetime_with_precision? + true + end + def index_algorithms { concurrently: 'CONCURRENTLY' } end @@ -255,6 +259,8 @@ module ActiveRecord @table_alias_length = nil connect + add_pg_decoders + @statements = StatementPool.new @connection, self.class.type_cast_config_to_integer(config.fetch(:statement_limit) { 1000 }) @@ -459,11 +465,11 @@ module ActiveRecord end def initialize_type_map(m) # :nodoc: - register_class_with_limit m, 'int2', OID::Integer - register_class_with_limit m, 'int4', OID::Integer - register_class_with_limit m, 'int8', OID::Integer + register_class_with_limit m, 'int2', Type::Integer + register_class_with_limit m, 'int4', Type::Integer + register_class_with_limit m, 'int8', Type::Integer m.alias_type 'oid', 'int2' - m.register_type 'float4', OID::Float.new + m.register_type 'float4', Type::Float.new m.alias_type 'float8', 'float4' m.register_type 'text', Type::Text.new register_class_with_limit m, 'varchar', Type::String @@ -474,8 +480,7 @@ module ActiveRecord register_class_with_limit m, 'bit', OID::Bit register_class_with_limit m, 'varbit', OID::BitVarying m.alias_type 'timestamptz', 'timestamp' - m.register_type 'date', OID::Date.new - m.register_type 'time', OID::Time.new + m.register_type 'date', Type::Date.new m.register_type 'money', OID::Money.new m.register_type 'bytea', OID::Bytea.new @@ -501,10 +506,8 @@ module ActiveRecord m.alias_type 'lseg', 'varchar' m.alias_type 'box', 'varchar' - m.register_type 'timestamp' do |_, _, sql_type| - precision = extract_precision(sql_type) - OID::DateTime.new(precision: precision) - end + register_class_with_precision m, 'time', Type::Time + register_class_with_precision m, 'timestamp', OID::DateTime m.register_type 'numeric' do |_, fmod, sql_type| precision = extract_precision(sql_type) @@ -762,6 +765,73 @@ module ActiveRecord def create_table_definition(name, temporary = false, options = nil, as = nil) # :nodoc: PostgreSQL::TableDefinition.new native_database_types, name, temporary, options, as end + + def can_perform_case_insensitive_comparison_for?(column) + @case_insensitive_cache ||= {} + @case_insensitive_cache[column.sql_type] ||= begin + sql = <<-end_sql + SELECT exists( + SELECT * FROM pg_proc + INNER JOIN pg_cast + ON casttarget::text::oidvector = proargtypes + WHERE proname = 'lower' + AND castsource = '#{column.sql_type}'::regtype::oid + ) + end_sql + execute_and_clear(sql, "SCHEMA", []) do |result| + result.getvalue(0, 0) == 't' + end + end + end + + def add_pg_decoders + coders_by_name = { + 'int2' => PG::TextDecoder::Integer, + 'int4' => PG::TextDecoder::Integer, + 'int8' => PG::TextDecoder::Integer, + 'oid' => PG::TextDecoder::Integer, + 'float4' => PG::TextDecoder::Float, + '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 + FROM pg_type as t + SQL + coders = execute_and_clear(query, "SCHEMA", []) do |result| + result + .map { |row| construct_coder(row, coders_by_name['typname']) } + .compact + end + + map = PG::TypeMapByOid.new + coders.each { |coder| map.add_coder(coder) } + @connection.type_map_for_results = map + end + + def construct_coder(row, coder_class) + return unless coder_class + coder_class.new(oid: row['oid'], name: row['typname']) + end + + ActiveRecord::Type.add_modifier({ array: true }, OID::Array, adapter: :postgresql) + ActiveRecord::Type.add_modifier({ range: true }, OID::Range, adapter: :postgresql) + ActiveRecord::Type.register(:bit, OID::Bit, adapter: :postgresql) + ActiveRecord::Type.register(:bit_varying, OID::BitVarying, adapter: :postgresql) + ActiveRecord::Type.register(:binary, OID::Bytea, adapter: :postgresql) + ActiveRecord::Type.register(:cidr, OID::Cidr, adapter: :postgresql) + ActiveRecord::Type.register(:date_time, OID::DateTime, adapter: :postgresql) + ActiveRecord::Type.register(:decimal, OID::Decimal, adapter: :postgresql) + ActiveRecord::Type.register(:enum, OID::Enum, adapter: :postgresql) + ActiveRecord::Type.register(:hstore, OID::Hstore, adapter: :postgresql) + ActiveRecord::Type.register(:inet, OID::Inet, adapter: :postgresql) + ActiveRecord::Type.register(:json, OID::Json, adapter: :postgresql) + ActiveRecord::Type.register(:jsonb, OID::Jsonb, adapter: :postgresql) + ActiveRecord::Type.register(:money, OID::Money, adapter: :postgresql) + ActiveRecord::Type.register(:point, OID::Point, adapter: :postgresql) + ActiveRecord::Type.register(:uuid, OID::Uuid, adapter: :postgresql) + ActiveRecord::Type.register(:vector, OID::Vector, adapter: :postgresql) + ActiveRecord::Type.register(:xml, OID::Xml, adapter: :postgresql) end end end |