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
372 def self.extended(db)
373   db.instance_exec do
374     @row_types = {}
375     @row_schema_types = {}
376     extend(@row_type_method_module = Module.new)
377     add_conversion_proc(2249, PGRow::Parser.new(:converter=>PGRow::ArrayRow))
378     if respond_to?(:register_array_type)
379       register_array_type('record', :oid=>2287, :scalar_oid=>2249)
380     end
381   end
382 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
385 def bound_variable_arg(arg, conn)
386   case arg
387   when ArrayRow
388     "(#{arg.map{|v| bound_variable_array(v) if v}.join(',')})"
389   when HashRow
390     arg.check_columns!
391     "(#{arg.values_at(*arg.columns).map{|v| bound_variable_array(v) if v}.join(',')})"
392   else
393     super
394   end
395 end
freeze()

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

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