class PgFuncall::TypeMap
See www.postgresql.org/docs/9.4/static/catalog-pg-type.html#CATALOG-TYPCATEGORY-TABLE
Constants
- FMETAQUERY
Public Class Methods
fetch(connection, options = {})
click to toggle source
# File lib/pg_funcall/type_map.rb, line 38 def self.fetch(connection, options = {}) case ActiveRecord.version.segments[0..1] when [4,0] then AR40TypeMap.new(connection, options) when [4,1] then AR41TypeMap.new(connection, options) when [4,2] then AR42TypeMap.new(connection, options) else raise ArgumentError, "Unsupported ActiveRecord version #{ActiveRecord.version}" end end
new(connection, options = {})
click to toggle source
# File lib/pg_funcall/type_map.rb, line 49 def initialize(connection, options = {}) @ftype_cache = {} @ar_connection = connection @options = options @typeinfo = [] @typeinfo_by_name = {} @typeinfo_by_oid = {} load_types end
Public Instance Methods
_canonicalize_type_name(name)
click to toggle source
# File lib/pg_funcall/type_map.rb, line 96 def _canonicalize_type_name(name) if name.end_with?('[]') name = '_' + name.gsub(/(\[\])+$/, '') end name end
ar_connection()
click to toggle source
# File lib/pg_funcall/type_map.rb, line 84 def ar_connection @ar_connection end
function_types(fn, search_path = @options[:search_path])
click to toggle source
Query PostgreSQL metadata about function to find its return type and argument types
# File lib/pg_funcall/type_map.rb, line 136 def function_types(fn, search_path = @options[:search_path]) return @ftype_cache[fn] if @ftype_cache[fn] parts = fn.split('.') info = if parts.length == 1 raise ArgumentError, "Must supply search_path for non-namespaced function" unless search_path && search_path.is_a?(Enumerable) && !search_path.empty? search_path.map do |ns| res = pg_connection.query(FMETAQUERY % [parts[0], ns]) PgFuncall._assign_pg_type_map_to_res(res, pg_connection) res.ntuples == 1 ? res : nil end.compact.first else PgFuncall._assign_pg_type_map_to_res(pg_connection.query(FMETAQUERY % [parts[1], parts[0]]), pg_connection) end return nil unless info && info.ntuples >= 1 @ftype_cache[fn] = FunctionSig.new(fn, info.getvalue(0,0).to_i, (0..info.ntuples-1).map { |row| info.getvalue(row, 1).split(/ +/).map(&:to_i) }) end
load_types()
click to toggle source
# File lib/pg_funcall/type_map.rb, line 60 def load_types res = pg_connection.query <<-SQL SELECT pgt.oid, ns.nspname, * FROM pg_type as pgt JOIN pg_namespace as ns on pgt.typnamespace = ns.oid; SQL PgFuncall._assign_pg_type_map_to_res(res, pg_connection) fields = res.fields @typeinfo = res.values.map do |values| row = Hash[fields.zip(values)] TypeInfo.new(row, lookup_ar_by_oid(row['oid'].to_i)) end @typeinfo_by_name.clear @typeinfo_by_oid.clear @typeinfo.each do |ti| @typeinfo_by_name[ti.name] = ti @typeinfo_by_oid[ti.oid] = ti end end
oid_for_type(type, array = false)
click to toggle source
Given a type name, with optional appended [] or prefixed _ for array types, return the OID for it.
If array = true, find array type for given base type.
# File lib/pg_funcall/type_map.rb, line 119 def oid_for_type(type, array = false) type = _canonicalize_type_name(type) type = '_' + type if array && !type.start_with?('_') @typeinfo_by_name[type] end
pg_connection()
click to toggle source
# File lib/pg_funcall/type_map.rb, line 88 def pg_connection @ar_connection.raw_connection end
resolve(oid_or_name)
click to toggle source
# File lib/pg_funcall/type_map.rb, line 103 def resolve(oid_or_name) if oid_or_name.is_a?(Integer) || (oid_or_name.is_a?(String) && oid_or_name.match(/^[0-9]+$/)) @typeinfo_by_oid[oid_or_name.to_i] elsif oid_or_name.is_a?(String) || oid_or_name.is_a?(Symbol) @typeinfo_by_name[_canonicalize_type_name(oid_or_name.to_s)] else raise ArgumentError, "You must supply a numeric OID or a string Type name" end end
type_cast_from_database(value, type)
click to toggle source
# File lib/pg_funcall/type_map.rb, line 92 def type_cast_from_database(value, type) type.cast_from_database(value) end