module Sequel::Postgres::PGRow::DatabaseMethods

  1. lib/sequel/extensions/pg_row.rb

Methods

Public Class

  1. extended

Public Instance

  1. bound_variable_arg
  2. freeze
  3. register_row_type
  4. row_type
  5. row_types

Attributes

row_types [R]

A hash mapping row type keys (usually symbols), to option hashes. At the least, the values will contain the :parser option for the Parser instance that the type will use.

Public Class methods

extended(db)

Do some setup for the data structures the module uses.

[show source]
    # File lib/sequel/extensions/pg_row.rb
392 def self.extended(db)
393   db.instance_exec do
394     @row_types = {}
395     @row_schema_types = {}
396     extend(@row_type_method_module = Sequel.set_temp_name(Module.new){"Sequel::Postgres::PGRow::DatabaseMethods::_RowTypeMethodModule"})
397     add_conversion_proc(2249, PGRow::Parser.new(:converter=>PGRow::ArrayRow))
398     if respond_to?(:register_array_type)
399       register_array_type('record', :oid=>2287, :scalar_oid=>2249)
400     end
401   end
402 end

Public Instance methods

bound_variable_arg(arg, conn)

Handle ArrayRow and HashRow values in bound variables.

[show source]
    # File lib/sequel/extensions/pg_row.rb
405 def bound_variable_arg(arg, conn)
406   case arg
407   when ArrayRow
408     "(#{arg.map{|v| bound_variable_array(v) if v}.join(',')})"
409   when HashRow
410     arg.check_columns!
411     "(#{arg.values_at(*arg.columns).map{|v| bound_variable_array(v) if v}.join(',')})"
412   else
413     super
414   end
415 end
freeze()

Freeze the row types and row schema types to prevent adding new ones.

[show source]
    # File lib/sequel/extensions/pg_row.rb
418 def freeze
419   @row_types.freeze
420   @row_schema_types.freeze
421   @row_type_method_module.freeze
422   super
423 end
register_row_type(db_type, opts=OPTS)

Register a new row type for the Database instance. db_type should be the type symbol. This parses the PostgreSQL system tables to get information the composite type, and by default has the type return instances of a subclass of HashRow.

The following options are supported:

:converter

Use a custom converter for the parser.

:typecaster

Use a custom typecaster for the parser.

[show source]
    # File lib/sequel/extensions/pg_row.rb
434 def register_row_type(db_type, opts=OPTS)
435   procs = @conversion_procs
436   rel_oid = nil
437   array_oid = nil
438   parser_opts = {}
439 
440   # Try to handle schema-qualified types.
441   type_schema, type_name = schema_and_table(db_type)
442   schema_type_string = type_name.to_s
443 
444   # Get basic oid information for the composite type.
445   ds = from(:pg_type).
446     select{[pg_type[:oid], :typrelid, :typarray]}.
447     where([[:typtype, 'c'], [:typname, type_name.to_s]])
448   if type_schema
449     ds = ds.join(:pg_namespace, [[:oid, :typnamespace], [:nspname, type_schema.to_s]])
450     schema_type_symbol = :"pg_row_#{type_schema}__#{type_name}" 
451   else
452     schema_type_symbol = :"pg_row_#{type_name}"
453   end
454   unless row = ds.first
455     raise Error, "row type #{db_type.inspect} not found in database"
456   end
457   # Manually cast to integer using to_i, because adapter may not cast oid type
458   # correctly (e.g. swift)
459   parser_opts[:oid], rel_oid, array_oid = row.values_at(:oid, :typrelid, :typarray).map(&:to_i)
460 
461   # Get column names and oids for each of the members of the composite type.
462   res = from(:pg_attribute).
463     join(:pg_type, :oid=>:atttypid).
464     where(:attrelid=>rel_oid).
465     where{attnum > 0}.
466     exclude(:attisdropped).
467     order(:attnum).
468     select_map{[:attname, Sequel.case({0=>:atttypid}, pg_type[:typbasetype], pg_type[:typbasetype]).as(:atttypid)]}
469   if res.empty?
470     raise Error, "no columns for row type #{db_type.inspect} in database"
471   end
472   parser_opts[:columns] = res.map{|r| r[0].to_sym}
473   parser_opts[:column_oids] = res.map{|r| r[1].to_i}
474 
475   # Using the conversion_procs, lookup converters for each member of the composite type
476   parser_opts[:column_converters] = parser_opts[:column_oids].map do |oid|
477     procs[oid]
478   end
479 
480   # Setup the converter and typecaster
481   parser_opts[:converter] = opts.fetch(:converter){HashRow.subclass(db_type, parser_opts[:columns])}
482   parser_opts[:typecaster] = opts.fetch(:typecaster, parser_opts[:converter])
483 
484   parser = Parser.new(parser_opts)
485   add_conversion_proc(parser.oid, parser)
486 
487   if respond_to?(:register_array_type) && array_oid && array_oid > 0
488     array_type_name = if type_schema
489       "#{type_schema}.#{type_name}"
490     else
491       type_name
492     end
493     register_array_type(array_type_name, :oid=>array_oid, :converter=>parser, :scalar_typecast=>schema_type_symbol)
494   end
495 
496   @row_types[literal(db_type)] = opts.merge(:parser=>parser, :type=>db_type)
497   @row_schema_types[schema_type_string] = schema_type_symbol 
498   @schema_type_classes[schema_type_symbol] = ROW_TYPE_CLASSES
499   @row_type_method_module.class_eval do
500     meth = :"typecast_value_#{schema_type_symbol}"
501     define_method(meth) do |v|
502       row_type(db_type, v)
503     end
504     private meth
505     alias_method(meth, meth)
506   end
507 
508   nil
509 end
row_type(db_type, obj)

Handle typecasting of the given object to the given database type. In general, the given database type should already be registered, but if obj is an array, this will handled unregistered types.

[show source]
    # File lib/sequel/extensions/pg_row.rb
514 def row_type(db_type, obj)
515   (type_hash = @row_types[literal(db_type)]) &&
516     (parser = type_hash[:parser])
517 
518   case obj
519   when ArrayRow, HashRow
520     obj
521   when Array
522     if parser
523       parser.typecast(obj)
524     else
525       obj = ArrayRow.new(obj)
526       obj.db_type = db_type
527       obj
528     end
529   when Hash
530     if parser 
531       parser.typecast(obj)
532     else
533       raise InvalidValue, "Database#row_type requires the #{db_type.inspect} type have a registered parser and typecaster when called with a hash"
534     end
535   else
536     raise InvalidValue, "cannot convert #{obj.inspect} to row type #{db_type.inspect}"
537   end
538 end