aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb')
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb88
1 files changed, 52 insertions, 36 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 71b05cdbae..02cafc8079 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -13,7 +13,7 @@ require 'active_record/connection_adapters/postgresql/database_statements'
require 'arel/visitors/bind_visitor'
# Make sure we're using pg high enough for PGResult#values
-gem 'pg', '~> 0.11'
+gem 'pg', '~> 0.15'
require 'pg'
require 'ipaddr'
@@ -74,10 +74,11 @@ module ActiveRecord
# In addition, default connection parameters of libpq can be set per environment variables.
# See http://www.postgresql.org/docs/9.1/static/libpq-envars.html .
class PostgreSQLAdapter < AbstractAdapter
- ADAPTER_NAME = 'PostgreSQL'
+ ADAPTER_NAME = 'PostgreSQL'.freeze
NATIVE_DATABASE_TYPES = {
primary_key: "serial primary key",
+ bigserial: "bigserial",
string: { name: "character varying" },
text: { name: "text" },
integer: { name: "integer" },
@@ -94,6 +95,7 @@ module ActiveRecord
int8range: { name: "int8range" },
binary: { name: "bytea" },
boolean: { name: "boolean" },
+ bigint: { name: "bigint" },
xml: { name: "xml" },
tsvector: { name: "tsvector" },
hstore: { name: "hstore" },
@@ -102,6 +104,7 @@ module ActiveRecord
macaddr: { name: "macaddr" },
uuid: { name: "uuid" },
json: { name: "json" },
+ jsonb: { name: "jsonb" },
ltree: { name: "ltree" },
citext: { name: "citext" },
point: { name: "point" },
@@ -118,25 +121,20 @@ module ActiveRecord
include PostgreSQL::DatabaseStatements
include Savepoints
- # Returns 'PostgreSQL' as adapter name for identification purposes.
- def adapter_name
- ADAPTER_NAME
- end
-
def schema_creation # :nodoc:
PostgreSQL::SchemaCreation.new self
end
- # Adds `:array` option to the default set provided by the
+ # Adds +:array+ option to the default set provided by the
# AbstractAdapter
- def prepare_column_options(column, types) # :nodoc:
+ def prepare_column_options(column) # :nodoc:
spec = super
spec[:array] = 'true' if column.respond_to?(:array) && column.array
spec[:default] = "\"#{column.default_function}\"" if column.default_function
spec
end
- # Adds `:array` as a valid migration key
+ # Adds +:array+ as a valid migration key
def migration_keys
super + [:array]
end
@@ -159,6 +157,14 @@ module ActiveRecord
true
end
+ def supports_foreign_keys?
+ true
+ end
+
+ def supports_views?
+ true
+ end
+
def index_algorithms
{ concurrently: 'CONCURRENTLY' }
end
@@ -252,6 +258,10 @@ module ActiveRecord
@statements.clear
end
+ def truncate(table_name, name = nil)
+ exec_query "TRUNCATE TABLE #{quote_table_name(table_name)}", name, []
+ end
+
# Is this connection alive and ready for queries?
def active?
@connection.query 'SELECT 1'
@@ -306,10 +316,6 @@ module ActiveRecord
self.client_min_messages = old
end
- def supports_insert_with_returning?
- true
- end
-
def supports_ddl_transactions?
true
end
@@ -348,14 +354,13 @@ module ActiveRecord
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_from_database res.rows.first.first
+ res.cast_values.first
end
end
def extensions
if supports_extensions?
- res = exec_query "SELECT extname from pg_extension", "SCHEMA"
- res.rows.map { |r| res.column_types['extname'].type_cast_from_database r.first }
+ exec_query("SELECT extname from pg_extension", "SCHEMA").cast_values
else
super
end
@@ -384,6 +389,21 @@ module ActiveRecord
PostgreSQL::Table.new(table_name, base)
end
+ def lookup_cast_type(sql_type) # :nodoc:
+ oid = execute("SELECT #{quote(sql_type)}::regtype::oid", "SCHEMA").first['oid'].to_i
+ super(oid)
+ end
+
+ def column_name_for_operation(operation, node) # :nodoc:
+ OPERATION_ALIASES.fetch(operation) { operation.downcase }
+ end
+
+ OPERATION_ALIASES = { # :nodoc:
+ "maximum" => "max",
+ "minimum" => "min",
+ "average" => "avg",
+ }
+
protected
# Returns the version of the connected PostgreSQL server.
@@ -425,8 +445,8 @@ module ActiveRecord
def initialize_type_map(m) # :nodoc:
register_class_with_limit m, 'int2', OID::Integer
- m.alias_type 'int4', 'int2'
- m.alias_type 'int8', 'int2'
+ register_class_with_limit m, 'int4', OID::Integer
+ register_class_with_limit m, 'int8', OID::Integer
m.alias_type 'oid', 'int2'
m.register_type 'float4', OID::Float.new
m.alias_type 'float8', 'float4'
@@ -447,10 +467,11 @@ module ActiveRecord
m.register_type 'point', OID::Point.new
m.register_type 'hstore', OID::Hstore.new
m.register_type 'json', OID::Json.new
+ m.register_type 'jsonb', OID::Jsonb.new
m.register_type 'cidr', OID::Cidr.new
m.register_type 'inet', OID::Inet.new
m.register_type 'uuid', OID::Uuid.new
- m.register_type 'xml', OID::SpecializedString.new(:xml)
+ m.register_type 'xml', OID::Xml.new
m.register_type 'tsvector', OID::SpecializedString.new(:tsvector)
m.register_type 'macaddr', OID::SpecializedString.new(:macaddr)
m.register_type 'citext', OID::SpecializedString.new(:citext)
@@ -495,9 +516,12 @@ module ActiveRecord
def extract_limit(sql_type) # :nodoc:
case sql_type
- when /^bigint/i; 8
- when /^smallint/i; 2
- else super
+ when /^bigint/i, /^int8/i
+ 8
+ when /^smallint/i
+ 2
+ else
+ super
end
end
@@ -511,7 +535,7 @@ module ActiveRecord
when 'true', 'false'
default
# Numeric types
- when /\A\(?(-?\d+(\.\d*)?\)?(::bigint)?)\z/
+ when /\A\(?(-?\d+(\.\d*)?)\)?(::bigint)?\z/
$1
# Object identifier types
when /\A-?\d+\z/
@@ -565,7 +589,7 @@ module ActiveRecord
end
def exec_no_cache(sql, name, binds)
- log(sql, name, binds) { @connection.async_exec(sql) }
+ log(sql, name, binds) { @connection.async_exec(sql, []) }
end
def exec_cache(sql, name, binds)
@@ -575,9 +599,7 @@ module ActiveRecord
}
log(sql, name, type_casted_binds, stmt_key) do
- @connection.send_query_prepared(stmt_key, type_casted_binds.map { |_, val| val })
- @connection.block
- @connection.get_last_result
+ @connection.exec_prepared(stmt_key, type_casted_binds.map { |_, val| val })
end
rescue ActiveRecord::StatementInvalid => e
pgerror = e.original_exception
@@ -669,9 +691,9 @@ module ActiveRecord
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')
+ execute("SET SESSION #{k} TO DEFAULT", 'SCHEMA')
elsif !v.nil?
- execute("SET SESSION #{k.to_s} TO #{quote(v)}", 'SCHEMA')
+ execute("SET SESSION #{k} TO #{quote(v)}", 'SCHEMA')
end
end
end
@@ -689,12 +711,6 @@ module ActiveRecord
exec_query("SELECT currval('#{sequence_name}')", 'SQL')
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.
- def select(sql, name = nil, binds = [])
- exec_query(sql, name, binds)
- end
-
# Returns the list of a table's column names, data types, and default values.
#
# The underlying query is roughly: