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

### Methods

bound_variable_arg extended register_row_type reset_conversion_procs row_type schema_column_type

### Constants

ESCAPE_RE | = | /("|\\)/.freeze
ESCAPE_REPLACEMENT | = | '\\\\\1'.freeze
COMMA | = | ','.freeze

### 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.

[Source]

         # File lib/sequel/extensions/pg_row.rb, line 364
    364:         def self.extended(db)
    365:           # Return right away if row_types has already been set. This
    366:           # makes things not break if a user extends the database with
    367:           # this module more than once (since extended is called every
    368:           # time).
    369:           return if db.row_types
    370:
    371:           db.instance_eval do
    372:             @row_types = {}
    373:             @row_schema_types = {}
    374:             extend(@row_type_method_module = Module.new)
    375:           end
    376:         end

### Public Instance methods

bound_variable_arg(arg, conn)

Handle ArrayRow and HashRow values in bound variables.

[Source]

         # File lib/sequel/extensions/pg_row.rb, line 379
    379:         def bound_variable_arg(arg, conn)
    380:           case arg
    381:           when ArrayRow
    382:             "(#{arg.map{|v| bound_variable_array(v)}.join(COMMA)})"
    383:           when HashRow
    384:             arg.check_columns!
    385:             "(#{arg.values_at(*arg.columns).map{|v| bound_variable_array(v)}.join(COMMA)})"
    386:           else
    387:             super
    388:           end
    389:         end

register_row_type(db_type, 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.

[Source]

         # File lib/sequel/extensions/pg_row.rb, line 400
    400:         def register_row_type(db_type, opts={})
    401:           procs = @conversion_procs
    402:           rel_oid = nil
    403:           array_oid = nil
    404:           parser_opts = {}
    405:
    406:           # Try to handle schema-qualified types.
    407:           type_schema, type_name = schema_and_table(db_type)
    408:           schema_type_string = type_name.to_s
    409:
    410:           # Get basic oid information for the composite type.
    411:           ds = from(:pg_type).
    412:             select(:pg_type__oid, :typrelid, :typarray).
    413:             where([[:typtype, 'c'], [:typname, type_name.to_s]])
    414:           if type_schema
    415:             ds = ds.join(:pg_namespace, [[:oid, :typnamespace], [:nspname, type_schema.to_s]])
    416:             schema_type_symbol = "pg_row_#{type_schema}__#{type_name}""pg_row_#{type_schema}__#{type_name}"
    417:           else
    418:             schema_type_symbol = "pg_row_#{type_name}""pg_row_#{type_name}"
    419:           end
    420:           unless row = ds.first
    421:             raise Error, "row type #{db_type.inspect} not found in database"
    422:           end
    423:           # Manually cast to integer using to_i, because adapter may not cast oid type
    424:           # correctly (e.g. swift)
    425:           parser_opts[:oid], rel_oid, array_oid = row.values_at(:oid, :typrelid, :typarray).map{|i| i.to_i}
    426:
    427:           # Get column names and oids for each of the members of the composite type.
    428:           res = from(:pg_attribute).
    429:             where(:attrelid=>rel_oid).
    430:             where{attnum > 0}.
    431:             exclude(:attisdropped).
    432:             order(:attnum).
    433:             select_map([:attname, :atttypid])
    434:           if res.empty?
    435:             raise Error, "no columns for row type #{db_type.inspect} in database"
    436:           end
    437:           parser_opts[:columns] = res.map{|r| r[0].to_sym}
    438:           parser_opts[:column_oids] = res.map{|r| r[1].to_i}
    439:
    440:           # Using the conversion_procs, lookup converters for each member of the composite type
    441:           parser_opts[:column_converters] = parser_opts[:column_oids].map do |oid|
    442:             if pr = procs[oid]
    443:               pr
    444:             elsif !Sequel::Postgres::STRING_TYPES.include?(oid)
    445:               # It's not a string type, and it's possible a conversion proc for this
    446:               # oid will be added later, so do a runtime check for it.
    447:               lambda{|s| (pr = procs[oid]) ? pr.call(s) : s}
    448:             end
    449:           end
    450:
    451:           # Setup the converter and typecaster
    452:           parser_opts[:converter] = opts.fetch(:converter){HashRow.subclass(db_type, parser_opts[:columns])}
    453:           parser_opts[:typecaster] = opts.fetch(:typecaster, parser_opts[:converter])
    454:
    455:           parser = Parser.new(parser_opts)
    456:           @conversion_procs[parser.oid] = parser
    457:
    458:           if defined?(PGArray) && PGArray.respond_to?(:register) && array_oid && array_oid > 0
    459:             PGArray.register(db_type, :oid=>array_oid, :converter=>parser, :type_procs=>@conversion_procs, :scalar_typecast=>schema_type_symbol)
    460:           end
    461:
    462:           @row_types[db_type] = opts.merge(:parser=>parser)
    463:           @row_schema_types[schema_type_string] = schema_type_symbol
    464:           @row_type_method_module.class_eval do
    465:             meth = "typecast_value_#{schema_type_symbol}""typecast_value_#{schema_type_symbol}"
    466:             define_method(meth) do |v|
    467:               row_type(db_type, v)
    468:             end
    469:             private meth
    470:           end
    471:
    472:           nil
    473:         end

reset_conversion_procs()

When reseting conversion procs, reregister all the row types so that the system tables are introspected again, picking up database changes.

[Source]

         # File lib/sequel/extensions/pg_row.rb, line 477
    477:         def reset_conversion_procs
    478:           procs = super
    479:
    480:           row_types.each do |db_type, opts|
    481:             register_row_type(db_type, opts)
    482:           end
    483:
    484:           procs
    485:         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.

[Source]

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

schema_column_type(db_type)

Make the column type detection handle registered row types.

[Source]

         # File lib/sequel/extensions/pg_row.rb, line 517
    517:         def schema_column_type(db_type)
    518:           if type = @row_schema_types[db_type]
    519:             type
    520:           else
    521:             super
    522:           end
    523:         end

[Validate]