The PostgreSQL adapter works with the native C (bitbucket.org/ged/ruby-pg) driver.
Options:
:host - Defaults to a Unix-domain socket in /tmp. On machines
without Unix-domain sockets, the default is to connect to localhost.
:port - Defaults to 5432.
:username - Defaults to be the same as the operating system
name of the user running the application.
:password - Password to be used if the server demands password
authentication.
:database - Defaults to be the same as the user name.
:schema_search_path - An optional schema search path for the
connection given as a string of comma-separated schema names. This is
backward-compatible with the :schema_order option.
:encoding - An optional client encoding that is used in a
SET client_encoding TO <encoding> call on the
connection.
:min_messages - An optional client min messages that is used
in a SET client_min_messages TO <min_messages> call on
the connection.
:variables - An optional hash of additional parameters that
will be used in SET SESSION key = val calls on the connection.
:insert_returning - An optional boolean to control the use or
RETURNING for INSERT statements defaults to true.
Any further options are used as connection parameters to libpq. See www.postgresql.org/docs/9.1/static/libpq-connect.html for the list of parameters.
In addition, default connection parameters of libpq can be set per environment variables. See www.postgresql.org/docs/9.1/static/libpq-envars.html .
See www.postgresql.org/docs/9.1/static/errcodes-appendix.html
Initializes and connects a PostgreSQL adapter.
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 540 def initialize(connection, logger, connection_parameters, config) super(connection, logger) if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true }) @prepared_statements = true @visitor = Arel::Visitors::PostgreSQL.new self else @visitor = unprepared_visitor end @connection_parameters, @config = connection_parameters, config # @local_tz is initialized as nil to avoid warnings when connect tries to use it @local_tz = nil @table_alias_length = nil connect @statements = StatementPool.new @connection, self.class.type_cast_config_to_integer(config.fetch(:statement_limit) { 1000 }) if postgresql_version < 80200 raise "Your version of PostgreSQL (#{postgresql_version}) is too old, please upgrade!" end initialize_type_map @local_tz = execute('SHOW TIME ZONE', 'SCHEMA').first["TimeZone"] @use_insert_returning = @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true end
Is this connection alive and ready for queries?
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 575 def active? @connection.query 'SELECT 1' true rescue PGError false end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 582 def active_threadsafe? @connection.connect_poll != PG::PGRES_POLLING_FAILED end
Returns 'PostgreSQL' as adapter name for identification purposes.
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 442 def adapter_name ADAPTER_NAME end
Clears the prepared statements cache.
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 570 def clear_cache! @statements.clear end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 661 def disable_extension(name) exec_query("DROP EXTENSION IF EXISTS \"#{name}\" CASCADE").tap { reload_type_map } end
Disconnects from the database if already connected. Otherwise, this method does nothing.
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 600 def disconnect! super @connection.close rescue nil end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 655 def enable_extension(name) exec_query("CREATE EXTENSION IF NOT EXISTS \"#{name}\"").tap { reload_type_map } end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 667 def extension_enabled?(name) if supports_extensions? res = exec_query "SELECT EXISTS(SELECT * FROM pg_available_extensions WHERE name = '#{name}' AND installed_version IS NOT NULL) as enabled", 'SCHEMA' res.column_types['enabled'].type_cast res.rows.first.first end end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 675 def extensions if supports_extensions? res = exec_query "SELECT extname from pg_extension", "SCHEMA" res.rows.map { |r| res.column_types['extname'].type_cast r.first } else super end end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 478 def index_algorithms { concurrently: 'CONCURRENTLY' } end
Adds `:array` as a valid migration key
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 456 def migration_keys super + [:array] end
Adds `:array` option to the default set provided by the AbstractAdapter
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 448 def prepare_column_options(column, types) spec = super spec[:array] = 'true' if column.respond_to?(:array) && column.array spec[:default] = "\"#{column.default_function}\"" if column.default_function spec end
Close then reopen the connection.
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 587 def reconnect! super @connection.reset configure_connection end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 593 def reset! clear_cache! super end
# File lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 36 def schema_creation SchemaCreation.new self end
Set the authorized user for this session
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 690 def session_auth=(user) clear_cache! exec_query "SET SESSION AUTHORIZATION #{user}" end
Enable standard-conforming strings if available.
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 620 def set_standard_conforming_strings old, self.client_min_messages = client_min_messages, 'panic' execute('SET standard_conforming_strings = on', 'SCHEMA') rescue nil ensure self.client_min_messages = old end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 631 def supports_ddl_transactions? true end
Returns true.
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 641 def supports_explain? true end
Returns true if pg > 9.1
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 646 def supports_extensions? postgresql_version >= 90100 end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 466 def supports_index_sort_order? true end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 627 def supports_insert_with_returning? true end
Returns true, since this connection adapter supports migrations.
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 610 def supports_migrations? true end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 470 def supports_partial_index? true end
Range datatypes weren't introduced until PostgreSQL 9.2
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 651 def supports_ranges? postgresql_version >= 90200 end
Returns true, since this connection adapter supports savepoints.
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 636 def supports_savepoints? true end
Returns true, since this connection adapter supports prepared
statement caching.
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 462 def supports_statement_cache? true end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 474 def supports_transaction_isolation? true end
Returns the configured supported identifier length supported by PostgreSQL
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 685 def table_alias_length @table_alias_length ||= query('SHOW max_identifier_length', 'SCHEMA')[0][0].to_i end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 714 def use_insert_returning? @use_insert_returning end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 718 def valid_type?(type) !native_database_types[type].nil? end
Returns the version of the connected PostgreSQL server.
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 729 def postgresql_version @connection.server_version end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 737 def translate_exception(exception, message) return exception unless exception.respond_to?(:result) case exception.result.try(:error_field, PGresult::PG_DIAG_SQLSTATE) when UNIQUE_VIOLATION RecordNotUnique.new(message, exception) when FOREIGN_KEY_VIOLATION InvalidForeignKey.new(message, exception) else super end end
Configures the encoding, verbosity, schema search path, and time zone of the connection. This is called by connect and should not be called manually.
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 867 def configure_connection if @config[:encoding] @connection.set_client_encoding(@config[:encoding]) end self.client_min_messages = @config[:min_messages] || 'warning' self.schema_search_path = @config[:schema_search_path] || @config[:schema_order] # Use standard-conforming strings if available so we don't have to do the E'...' dance. set_standard_conforming_strings # If using Active Record's time zone support configure the connection to return # TIMESTAMP WITH ZONE types in UTC. # (SET TIME ZONE does not use an equals sign like other SET variables) if ActiveRecord::Base.default_timezone == :utc execute("SET time zone 'UTC'", 'SCHEMA') elsif @local_tz execute("SET time zone '#{@local_tz}'", 'SCHEMA') end # SET statements from :variables config hash # http://www.postgresql.org/docs/8.3/static/sql-set.html variables = @config[:variables] || {} variables.map do |k, v| if v == ':default' || v == :default # Sets the value to the global or compile default execute("SET SESSION #{k.to_s} TO DEFAULT", 'SCHEMA') elsif !v.nil? execute("SET SESSION #{k.to_s} TO #{quote(v)}", 'SCHEMA') end end end
Connects to a PostgreSQL server and sets up the adapter depending on the connected server's characteristics.
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 854 def connect @connection = PGconn.connect(@connection_parameters) # Money type has a fixed precision of 10 in PostgreSQL 8.2 and below, and as of # PostgreSQL 8.3 it has a fixed precision of 19. PostgreSQLColumn.extract_precision # should know about this but can't detect it there, so deal with it here. PostgreSQLColumn.money_precision = (postgresql_version >= 80300) ? 19 : 10 configure_connection end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 963 def create_table_definition(name, temporary, options) TableDefinition.new native_database_types, name, temporary, options end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 801 def exec_cache(sql, binds) stmt_key = prepare_statement sql # Clear the queue @connection.get_last_result @connection.send_query_prepared(stmt_key, binds.map { |col, val| type_cast(val, col) }) @connection.block @connection.get_last_result rescue PGError => e # Get the PG code for the failure. Annoyingly, the code for # prepared statements whose return value may have changed is # FEATURE_NOT_SUPPORTED. Check here for more details: # http://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/cache/plancache.c#l573 begin code = e.result.result_error_field(PGresult::PG_DIAG_SQLSTATE) rescue raise e end if FEATURE_NOT_SUPPORTED == code @statements.delete sql_key(sql) retry else raise e end end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 797 def exec_no_cache(sql, binds) @connection.async_exec(sql, []) end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 948 def extract_pg_identifier_from_name(name) match_data = name.start_with?('"') ? name.match(/\"([^\"]+)\"/) : name.match(/([^\.]+)/) if match_data rest = name[match_data[0].length, name.length] rest = rest[1, rest.length] if rest.start_with? "." [match_data[1], (rest.length > 0 ? rest : nil)] end end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 958 def extract_table_ref_from_insert_sql(sql) sql[/into\s+([^\(]*).*values\s*\(/] $1.strip if $1 end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 752 def get_oid_type(oid, fmod, column_name) OID::TYPE_MAP.fetch(oid, fmod) { warn "unknown OID #{oid}: failed to recognize type of '#{column_name}'. It will be treated as String." OID::TYPE_MAP[oid] = OID::Identity.new } end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 764 def initialize_type_map result = execute('SELECT oid, typname, typelem, typdelim, typinput FROM pg_type', 'SCHEMA') leaves, nodes = result.partition { |row| row['typelem'] == '0' } # populate the leaf nodes leaves.find_all { |row| OID.registered_type? row['typname'] }.each do |row| OID::TYPE_MAP[row['oid'].to_i] = OID::NAMES[row['typname']] end arrays, nodes = nodes.partition { |row| row['typinput'] == 'array_in' } # populate composite types nodes.find_all { |row| OID::TYPE_MAP.key? row['typelem'].to_i }.each do |row| if OID.registered_type? row['typname'] # this composite type is explicitly registered vector = OID::NAMES[row['typname']] else # use the default for composite types vector = OID::Vector.new row['typdelim'], OID::TYPE_MAP[row['typelem'].to_i] end OID::TYPE_MAP[row['oid'].to_i] = vector end # populate array types arrays.find_all { |row| OID::TYPE_MAP.key? row['typelem'].to_i }.each do |row| array = OID::Array.new OID::TYPE_MAP[row['typelem'].to_i] OID::TYPE_MAP[row['oid'].to_i] = array end end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 904 def last_insert_id_value(sequence_name) last_insert_id_result(sequence_name).rows.first.first end
Prepare the statement if it hasn't been prepared, return the statement key.
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 837 def prepare_statement(sql) sql_key = sql_key(sql) unless @statements.key? sql_key nextkey = @statements.next_key @connection.prepare nextkey, sql @statements[sql_key] = nextkey end @statements[sql_key] end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 759 def reload_type_map OID::TYPE_MAP.clear initialize_type_map end
Executes a SELECT query and returns the results, performing any data type conversions that are required to be performed here instead of in PostgreSQLColumn.
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 914 def select(sql, name = nil, binds = []) exec_query(sql, name, binds) end
Returns the statement identifier for the client side cache of statements
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 831 def sql_key(sql) "#{schema_search_path}-#{sql}" end