Class: Sequel::Postgres::Database

Inherits:
Database show all
Includes:
DatabaseMethods
Defined in:
lib/sequel/adapters/postgres.rb

Overview

Database class for PostgreSQL databases used with Sequel and the pg, postgres, or postgres-pr driver.

Constant Summary

INFINITE_TIMESTAMP_STRINGS =
['infinity'.freeze, '-infinity'.freeze].freeze
INFINITE_DATETIME_VALUES =
([PLUS_INFINITY, MINUS_INFINITY] + INFINITE_TIMESTAMP_STRINGS).freeze

Constants included from DatabaseMethods

Sequel::Postgres::DatabaseMethods::FOREIGN_KEY_LIST_ON_DELETE_MAP, Sequel::Postgres::DatabaseMethods::ON_COMMIT, Sequel::Postgres::DatabaseMethods::POSTGRES_DEFAULT_RE, Sequel::Postgres::DatabaseMethods::PREPARED_ARG_PLACEHOLDER, Sequel::Postgres::DatabaseMethods::RE_CURRVAL_ERROR, Sequel::Postgres::DatabaseMethods::SELECT_CUSTOM_SEQUENCE_SQL, Sequel::Postgres::DatabaseMethods::SELECT_PK_SQL, Sequel::Postgres::DatabaseMethods::SELECT_SERIAL_SEQUENCE_SQL, Sequel::Postgres::DatabaseMethods::UNLOGGED

Constants inherited from Database

Database::ADAPTERS, Database::AUTOINCREMENT, Database::COLUMN_DEFINITION_ORDER, Database::COLUMN_SCHEMA_DATETIME_TYPES, Database::COLUMN_SCHEMA_STRING_TYPES, Database::COMBINABLE_ALTER_TABLE_OPS, Database::COMMA_SEPARATOR, Database::CURRENT_TIMESTAMP_RE, Database::DEFAULT_DATABASE_ERROR_REGEXPS, Database::DEFAULT_JOIN_TABLE_COLUMN_OPTIONS, Database::DEFAULT_STRING_COLUMN_SIZE, Database::DatasetClass, Database::EXTENSIONS, Database::NOT_NULL, Database::NULL, Database::OPTS, Database::PRIMARY_KEY, Database::SCHEMA_TYPE_CLASSES, Database::SQL_BEGIN, Database::SQL_COMMIT, Database::SQL_RELEASE_SAVEPOINT, Database::SQL_ROLLBACK, Database::SQL_ROLLBACK_TO_SAVEPOINT, Database::SQL_SAVEPOINT, Database::STRING_DEFAULT_RE, Database::TEMPORARY, Database::TRANSACTION_BEGIN, Database::TRANSACTION_COMMIT, Database::TRANSACTION_ISOLATION_LEVELS, Database::TRANSACTION_ROLLBACK, Database::UNDERSCORE, Database::UNIQUE, Database::UNSIGNED

Instance Attribute Summary collapse

Attributes included from DatabaseMethods

#conversion_procs

Attributes inherited from Database

#cache_schema, #dataset_class, #default_string_column_size, #identifier_input_method, #identifier_output_method, #log_warn_duration, #loggers, #opts, #pool, #prepared_statements, #sql_log_level, #timezone, #transaction_isolation_level

Instance Method Summary collapse

Methods included from DatabaseMethods

#commit_prepared_transaction, #create_function, #create_language, #create_schema, #create_trigger, #database_type, #do, #drop_function, #drop_language, #drop_schema, #drop_trigger, #foreign_key_list, #indexes, #locks, #notify, #primary_key, #primary_key_sequence, #refresh_view, #reset_conversion_procs, #reset_primary_key_sequence, #rollback_prepared_transaction, #serial_primary_key_options, #server_version, #supports_create_table_if_not_exists?, #supports_deferrable_constraints?, #supports_deferrable_foreign_key_constraints?, #supports_drop_table_if_exists?, #supports_partial_indexes?, #supports_prepared_transactions?, #supports_savepoints?, #supports_transaction_isolation_levels?, #supports_transactional_ddl?, #supports_trigger_conditions?, #tables, #type_supported?, #values, #views

Methods included from Database::ResetIdentifierMangling

#extended

Methods inherited from Database

#<<, #[], adapter_class, adapter_scheme, #adapter_scheme, #add_column, #add_index, #add_servers, #after_commit, after_initialize, #after_rollback, #alter_table, #alter_table_generator, #call, #cast_type_literal, connect, #create_join_table, #create_join_table!, #create_join_table?, #create_or_replace_view, #create_table, #create_table!, #create_table?, #create_table_generator, #create_view, #database_type, #dataset, #disconnect, #drop_column, #drop_index, #drop_join_table, #drop_table, #drop_table?, #drop_view, #each_server, #execute_ddl, #execute_dui, #execute_insert, #extend_datasets, extension, #extension, #fetch, #from, #from_application_timestamp, #get, #global_index_namespace?, #in_transaction?, #initialize, #inspect, #literal, #literal_symbol, #literal_symbol_set, load_adapter, #log_exception, #log_info, #log_yield, #logger=, #prepared_statement, #quote_identifier, #quote_identifiers=, #quote_identifiers?, register_extension, #remove_servers, #rename_column, #rename_table, #run, run_after_initialize, #schema, #schema_type_class, #select, #serial_primary_key_options, #servers, #set_column_default, #set_column_type, #set_prepared_statement, #sharded?, #single_threaded?, #supports_create_table_if_not_exists?, #supports_deferrable_constraints?, #supports_deferrable_foreign_key_constraints?, #supports_drop_table_if_exists?, #supports_foreign_key_parsing?, #supports_index_parsing?, #supports_partial_indexes?, #supports_prepared_transactions?, #supports_savepoints?, #supports_savepoints_in_prepared_transactions?, #supports_schema_parsing?, #supports_table_listing?, #supports_transaction_isolation_levels?, #supports_transactional_ddl?, #supports_view_listing?, #supports_views_with_check_option?, #supports_views_with_local_check_option?, #synchronize, #table_exists?, #test_connection, #transaction, #typecast_value, #uri, #url, #valid_connection?

Constructor Details

This class inherits a constructor from Sequel::Database

Instance Attribute Details

#convert_infinite_timestampsObject

Whether infinite timestamps/dates should be converted on retrieval. By default, no conversion is done, so an error is raised if you attempt to retrieve an infinite timestamp/date. You can set this to :nil to convert to nil, :string to leave as a string, or :float to convert to an infinite float.



198
199
200
# File 'lib/sequel/adapters/postgres.rb', line 198

def convert_infinite_timestamps
  @convert_infinite_timestamps
end

Instance Method Details

#bound_variable_arg(arg, conn) ⇒ Object

Convert given argument so that it can be used directly by pg. Currently, pg doesn't handle fractional seconds in Time/DateTime or blobs with “0”, and it won't ever handle Sequel::SQLTime values correctly. Only public for use by the adapter, shouldn't be used by external code.



204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/sequel/adapters/postgres.rb', line 204

def bound_variable_arg(arg, conn)
  case arg
  when Sequel::SQL::Blob
    {:value=>arg, :type=>17, :format=>1}
  when Sequel::SQLTime
    literal(arg)
  when DateTime, Time
    literal(arg)
  else
    arg
  end
end

#connect(server) ⇒ Object

Connects to the database. In addition to the standard database options, using the :encoding or :charset option changes the client encoding for the connection, :connect_timeout is a connection timeout in seconds, :sslmode sets whether postgres's sslmode, and :notice_receiver handles server notices in a proc. :connect_timeout, :ssl_mode, and :notice_receiver are only supported if the pg driver is used.



224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# File 'lib/sequel/adapters/postgres.rb', line 224

def connect(server)
  opts = server_opts(server)
  if SEQUEL_POSTGRES_USES_PG
    connection_params = {
      :host => opts[:host],
      :port => opts[:port] || 5432,
      :dbname => opts[:database],
      :user => opts[:user],
      :password => opts[:password],
      :connect_timeout => opts[:connect_timeout] || 20,
      :sslmode => opts[:sslmode]
    }.delete_if { |key, value| blank_object?(value) }
    conn = Adapter.connect(connection_params)

    conn.instance_variable_set(:@prepared_statements, {})

    if receiver = opts[:notice_receiver]
      conn.set_notice_receiver(&receiver)
    end
  else
    conn = Adapter.connect(
      (opts[:host] unless blank_object?(opts[:host])),
      opts[:port] || 5432,
      nil, '',
      opts[:database],
      opts[:user],
      opts[:password]
    )
  end

  conn.instance_variable_set(:@db, self)

  if encoding = opts[:encoding] || opts[:charset]
    if conn.respond_to?(:set_client_encoding)
      conn.set_client_encoding(encoding)
    else
      conn.async_exec("set client_encoding to '#{encoding}'")
    end
  end

  connection_configuration_sqls.each{|sql| conn.execute(sql)}
  conn
end

#copy_into(table, opts = OPTS) ⇒ Object



403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
# File 'lib/sequel/adapters/postgres.rb', line 403

def copy_into(table, opts=OPTS)
  data = opts[:data]
  data = Array(data) if data.is_a?(String)

  if block_given? && data
    raise Error, "Cannot provide both a :data option and a block to copy_into"
  elsif !block_given? && !data
    raise Error, "Must provide either a :data option or a block to copy_into"
  end

  synchronize(opts[:server]) do |conn|
    conn.execute(copy_into_sql(table, opts))
    begin
      if block_given?
        while buf = yield
          conn.put_copy_data(buf)
        end
      else
        data.each{|buff| conn.put_copy_data(buff)}
      end
    rescue Exception => e
      conn.put_copy_end("ruby exception occurred while copying data into PostgreSQL")
    ensure
      conn.put_copy_end unless e
      while res = conn.get_result
        raise e if e
        check_database_errors{res.check}
      end
    end
  end 
end

#copy_table(table, opts = OPTS) ⇒ Object



363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
# File 'lib/sequel/adapters/postgres.rb', line 363

def copy_table(table, opts=OPTS)
  synchronize(opts[:server]) do |conn|
    conn.execute(copy_table_sql(table, opts))
    begin
      if block_given?
        while buf = conn.get_copy_data
          yield buf
        end
        nil
      else
        b = ''
        b << buf while buf = conn.get_copy_data
        b
      end
    ensure
      raise DatabaseDisconnectError, "disconnecting as a partial COPY may leave the connection in an unusable state" if buf
    end
  end 
end

#disconnect_connection(conn) ⇒ Object

Disconnect given connection



301
302
303
304
305
306
# File 'lib/sequel/adapters/postgres.rb', line 301

def disconnect_connection(conn)
  begin
    conn.finish
  rescue PGError, IOError
  end
end

#error_info(e) ⇒ Object



320
321
322
323
324
325
326
327
328
329
330
# File 'lib/sequel/adapters/postgres.rb', line 320

def error_info(e)
  e = e.wrapped_exception if e.is_a?(DatabaseError)
  r = e.result
  h = {}
  h[:schema] = r.error_field(::PG::PG_DIAG_SCHEMA_NAME)
  h[:table] = r.error_field(::PG::PG_DIAG_TABLE_NAME)
  h[:column] = r.error_field(::PG::PG_DIAG_COLUMN_NAME)
  h[:constraint] = r.error_field(::PG::PG_DIAG_CONSTRAINT_NAME)
  h[:type] = r.error_field(::PG::PG_DIAG_DATATYPE_NAME)
  h
end

#execute(sql, opts = OPTS, &block) ⇒ Object

Execute the given SQL with the given args on an available connection.



334
335
336
# File 'lib/sequel/adapters/postgres.rb', line 334

def execute(sql, opts=OPTS, &block)
  synchronize(opts[:server]){|conn| check_database_errors{_execute(conn, sql, opts, &block)}}
end

#listen(channels, opts = OPTS, &block) ⇒ Object



456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
# File 'lib/sequel/adapters/postgres.rb', line 456

def listen(channels, opts=OPTS, &block)
  check_database_errors do
    synchronize(opts[:server]) do |conn|
      begin
        channels = Array(channels)
        channels.each do |channel|
          sql = "LISTEN "
          dataset.send(:identifier_append, sql, channel)
          conn.execute(sql)
        end
        opts[:after_listen].call(conn) if opts[:after_listen]
        timeout = opts[:timeout] ? [opts[:timeout]] : []
        if l = opts[:loop]
          raise Error, 'calling #listen with :loop requires a block' unless block
          loop_call = l.respond_to?(:call)
          catch(:stop) do
            loop do
              conn.wait_for_notify(*timeout, &block)
              l.call(conn) if loop_call
            end
          end
          nil
        else
          conn.wait_for_notify(*timeout, &block)
        end
      ensure
        conn.execute("UNLISTEN *")
      end
    end
  end
end

#to_application_timestamp(value) ⇒ Object

If convert_infinite_timestamps is true and the value is infinite, return an appropriate value based on the convert_infinite_timestamps setting.



491
492
493
494
495
496
497
498
499
500
501
502
# File 'lib/sequel/adapters/postgres.rb', line 491

def to_application_timestamp(value)
  if convert_infinite_timestamps
    case value
    when *INFINITE_TIMESTAMP_STRINGS
      infinite_timestamp_value(value)
    else
      super
    end
  else
    super
  end
end