class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
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 aSET client_encoding TO <encoding>
call on the connection. -
:min_messages
- An optional client min messages that is used in aSET client_min_messages TO <min_messages>
call on the connection. -
:variables
- An optional hash of additional parameters that will be used inSET SESSION key = val
calls on the connection. -
:insert_returning
- An optional boolean to control the use ofRETURNING
forINSERT
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 .
Constants
- ADAPTER_NAME
- FOREIGN_KEY_VIOLATION
See www.postgresql.org/docs/9.1/static/errcodes-appendix.html
- NATIVE_DATABASE_TYPES
- UNIQUE_VIOLATION
Public Class Methods
Initializes and connects a PostgreSQL adapter.
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 226 def initialize(connection, logger, connection_parameters, config) super(connection, logger) @visitor = Arel::Visitors::PostgreSQL.new self if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true }) @prepared_statements = true else @prepared_statements = false 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 @type_map = Type::HashLookupTypeMap.new initialize_type_map(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
Public Instance Methods
Is this connection alive and ready for queries?
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 266 def active? @connection.query 'SELECT 1' true rescue PGError false end
Clears the prepared statements cache.
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 257 def clear_cache! @statements.clear end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 343 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 292 def disconnect! super @connection.close rescue nil end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 337 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 349 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.cast_values.first end end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 357 def extensions if supports_extensions? exec_query("SELECT extname from pg_extension", "SCHEMA").cast_values else super end end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 168 def index_algorithms { concurrently: 'CONCURRENTLY' } end
Adds :array
as a valid migration key
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 138 def migration_keys super + [:array] end
Close then reopen the connection.
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 274 def reconnect! super @connection.reset configure_connection end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 280 def reset! clear_cache! reset_transaction unless @connection.transaction_status == ::PG::PQTRANS_IDLE @connection.query 'ROLLBACK' end @connection.query 'DISCARD ALL' configure_connection end
Set the authorized user for this session
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 371 def session_auth=(user) clear_cache! exec_query "SET SESSION AUTHORIZATION #{user}" end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 311 def set_standard_conforming_strings execute('SET standard_conforming_strings = on', 'SCHEMA') end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 315 def supports_ddl_transactions? true end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 319 def supports_explain? true end
Returns true if pg > 9.1
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 324 def supports_extensions? postgresql_version >= 90100 end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 160 def supports_foreign_keys? true end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 148 def supports_index_sort_order? true end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 333 def supports_materialized_views? postgresql_version >= 90300 end
Returns true, since this connection adapter supports migrations.
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 302 def supports_migrations? true end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 152 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 329 def supports_ranges? postgresql_version >= 90200 end
Returns true
, since this connection adapter supports prepared
statement caching.
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 144 def supports_statement_cache? true end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 156 def supports_transaction_isolation? true end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 164 def supports_views? true end
Returns the configured supported identifier length supported by PostgreSQL
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 366 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 261 def truncate(table_name, name = nil) exec_query "TRUNCATE TABLE #{quote_table_name(table_name)}", name, [] end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 376 def use_insert_returning? @use_insert_returning end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 380 def valid_type?(type) !native_database_types[type].nil? end
Protected Instance Methods
Returns the version of the connected PostgreSQL server.
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 406 def postgresql_version @connection.server_version end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 414 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
Private Instance Methods
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 669 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 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 DEFAULT", 'SCHEMA') elsif !v.nil? execute("SET SESSION #{k} 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 650 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. OID::Money.precision = (postgresql_version >= 80300) ? 19 : 10 configure_connection rescue ::PG::Error => error if error.message.include?("does not exist") raise ActiveRecord::NoDatabaseError.new(error.message, error) else raise end end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 595 def exec_cache(sql, name, binds) stmt_key = prepare_statement(sql) type_casted_binds = binds.map { |col, val| [col, type_cast(val, col)] } log(sql, name, type_casted_binds, stmt_key) do @connection.exec_prepared(stmt_key, type_casted_binds.map { |_, val| val }) end rescue ActiveRecord::StatementInvalid => e pgerror = e.original_exception # 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 = pgerror.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 591 def exec_no_cache(sql, name, binds) log(sql, name, binds) { @connection.async_exec(sql, []) } end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 583 def execute_and_clear(sql, name, binds) result = without_prepared_statement?(binds) ? exec_no_cache(sql, name, binds) : exec_cache(sql, name, binds) ret = yield result result.clear ret end
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 706 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 632 def prepare_statement(sql) sql_key = sql_key(sql) unless @statements.key? sql_key nextkey = @statements.next_key begin @connection.prepare nextkey, sql rescue => e raise translate_exception_class(e, sql) end # Clear the queue @connection.get_last_result @statements[sql_key] = nextkey end @statements[sql_key] end
Returns the statement identifier for the client side cache of statements
# File lib/active_record/connection_adapters/postgresql_adapter.rb, line 626 def sql_key(sql) "#{schema_search_path}-#{sql}" end