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
390 def self.extended(db)
391   db.instance_exec do
392     @row_types = {}
393     @row_schema_types = {}
394     extend(@row_type_method_module = Module.new)
395     add_conversion_proc(2249, PGRow::Parser.new(:converter=>PGRow::ArrayRow))
396     if respond_to?(:register_array_type)
397       register_array_type('record', :oid=>2287, :scalar_oid=>2249)
398     end
399   end
400 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
403 def bound_variable_arg(arg, conn)
404   case arg
405   when ArrayRow
406     "(#{arg.map{|v| bound_variable_array(v) if v}.join(',')})"
407   when HashRow
408     arg.check_columns!
409     "(#{arg.values_at(*arg.columns).map{|v| bound_variable_array(v) if v}.join(',')})"
410   else
411     super
412   end
413 end
freeze()

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

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