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