Module Sequel::Postgres::PGRow::DatabaseMethods
In: lib/sequel/extensions/pg_row.rb

Methods

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

Do some setup for the data structures the module uses.

[Source]

     # File lib/sequel/extensions/pg_row.rb, line 371
371:         def self.extended(db)
372:           db.instance_exec do
373:             @row_types = {}
374:             @row_schema_types = {}
375:             extend(@row_type_method_module = Module.new)
376:             add_conversion_proc(2249, PGRow::Parser.new(:converter=>PGRow::ArrayRow))
377:             if respond_to?(:register_array_type)
378:               register_array_type('record', :oid=>2287, :scalar_oid=>2249)
379:             end
380:           end
381:         end

Public Instance methods

Handle ArrayRow and HashRow values in bound variables.

[Source]

     # File lib/sequel/extensions/pg_row.rb, line 384
384:         def bound_variable_arg(arg, conn)
385:           case arg
386:           when ArrayRow
387:             "(#{arg.map{|v| bound_variable_array(v) if v}.join(',')})"
388:           when HashRow
389:             arg.check_columns!
390:             "(#{arg.values_at(*arg.columns).map{|v| bound_variable_array(v) if v}.join(',')})"
391:           else
392:             super
393:           end
394:         end

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

[Source]

     # File lib/sequel/extensions/pg_row.rb, line 397
397:         def freeze
398:           @row_types.freeze
399:           @row_schema_types.freeze
400:           @row_type_method_module.freeze
401:           super
402:         end

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.

[Source]

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

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.

[Source]

     # File lib/sequel/extensions/pg_row.rb, line 492
492:         def row_type(db_type, obj)
493:           (type_hash = @row_types[literal(db_type)]) &&
494:             (parser = type_hash[:parser])
495: 
496:           case obj
497:           when ArrayRow, HashRow
498:             obj
499:           when Array
500:             if parser
501:               parser.typecast(obj)
502:             else
503:               obj = ArrayRow.new(obj)
504:               obj.db_type = db_type
505:               obj
506:             end
507:           when Hash
508:             if parser 
509:               parser.typecast(obj)
510:             else
511:               raise InvalidValue, "Database#row_type requires the #{db_type.inspect} type have a registered parser and typecaster when called with a hash"
512:             end
513:           else
514:             raise InvalidValue, "cannot convert #{obj.inspect} to row type #{db_type.inspect}"
515:           end
516:         end

[Validate]