Class: Ensql::PostgresAdapter

Inherits:
Object
  • Object
show all
Includes:
Adapter
Defined in:
lib/ensql/postgres_adapter.rb

Overview

Wraps a pool of PG connections to implement the Adapter interface. The adapter can use a 3rd-party pool (e.g. from ActiveRecord of Sequel) or manage its own using the simple connection_pool gem.

This adapter is much faster and offers much better PostgreSQL specific parameter interpolation than the framework adapters. See #query_type_map for options.

Examples:

# Use with ActiveRecord's connection pool
Ensql.adapter = Ensql::PostgresAdapter.new(Ensql::ActiveRecordAdapter.pool)

# Use with Sequel's connection pool
DB = Sequel.connect(ENV['DATABASE_URL'])
Ensql.adapter = Ensql::PostgresAdapter.new(Ensql::SequelAdapter.pool(DB))

# Use with our own thread-safe connection pool
Ensql.adapter = Ensql::PostgresAdapter.pool { PG.connect ENV['DATABASE_URL'] }
Ensql.adapter = Ensql::PostgresAdapter.pool(size: 5) { PG.connect ENV['DATABASE_URL'] }

See Also:

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(pool) ⇒ PostgresAdapter

Returns a new instance of PostgresAdapter.

Parameters:

  • pool (PoolWrapper, ConnectionPool, #with)

    a object that yields a PG::Connection using #with



50
51
52
53
# File 'lib/ensql/postgres_adapter.rb', line 50

def initialize(pool)
  @pool = pool
  @quoter = PG::TextEncoder::QuotedLiteral.new
end

Class Method Details

.pool(**pool_opts, &connection_block) ⇒ Object

Set up a connection pool using the supplied block to initialise connections.

PostgresAdapter.pool(size: 20) { PG.connect ENV['DATABASE_URL'] }

Parameters:

  • pool_opts

    are sent straight to the ConnectionPool initializer.

Options Hash (**pool_opts):

  • timeout (Integer) — default: 5

    number of seconds to wait for a connection if none currently available.

  • size (Integer) — default: 5

    number of connections to pool.

Yield Returns:

  • (PG::Connection)

    a new connection.



45
46
47
# File 'lib/ensql/postgres_adapter.rb', line 45

def self.pool(**pool_opts, &connection_block)
  new ConnectionPool.new(**pool_opts, &connection_block)
end

Instance Method Details

#query_type_mapPG::TypeMapByClass

A map for encoding Ruby objects into PostgreSQL literals based on their class. You can add additional class mappings to suit your needs. See https://rubydoc.info/gems/pg/PG/BasicTypeRegistry for details of adding your own encoders and decoders.

# Encode any `IPAddr` objects for interpolation using the `InetEncoder`.
Ensql.adapter.query_type_map[IPAddr] = InetEncoder.new

# Deserialize `inet` columns as IPAddr objects.
PG::BasicTypeRegistry.register_type(0, 'inet', InetEncoder, InetDecoder)

Returns:

  • (PG::TypeMapByClass)


67
68
69
70
71
72
73
74
75
76
77
# File 'lib/ensql/postgres_adapter.rb', line 67

def query_type_map
  @query_type_map ||= @pool.with do |connection|
    map = PG::BasicTypeMapForQueries.new(connection)
    # Ensure encoders are set up for old versions of the pg gem
    map[Date] ||= PG::TextEncoder::Date.new
    map[Time] ||= PG::TextEncoder::TimestampWithoutTimeZone.new
    map[Hash] ||= PG::TextEncoder::JSON.new
    map[BigDecimal] ||= NumericEncoder.new
    map
  end
end