# class PG::TextEncoder::Record

This class encodes one record of columns for transmission as query parameter in text format. See PostgreSQL Composite Types for a description of the format and how it can be used.

PostgreSQL allows composite types to be used in many of the same ways that simple types can be used. For example, a column of a table can be declared to be of a composite type.

The encoder expects the record columns as array of values. The single values are encoded as defined in the assigned `type_map`. If no type_map was assigned, all values are converted to strings by `PG::TextEncoder::String`.

It is possible to manually assign a type encoder for each column per `PG::TypeMapByColumn`, or to make use of `PG::BasicTypeMapBasedOnResult` to assign them based on the table OIDs.

Encode a record from an `Array<String>` to a `String` in PostgreSQL Composite Type format (uses default type map `TypeMapAllStrings`):

    PG::TextEncoder::Record.new.encode([1, 2])  # => "(\"1\",\"2\")"

Encode a record from `Array<Float>` to `String` :

    # Build a type map for two Floats
    tm = PG::TypeMapByColumn.new([PG::TextEncoder::Float.new]*2)
    # Use this type map to encode the record:
    PG::TextEncoder::Record.new(type_map: tm).encode([1,2])
    # => "(\"1.0000000000000000E+00\",\"2.0000000000000000E+00\")"

Records can also be encoded and decoded directly to and from the database. This avoids intermediate string allocations and is very fast. Take the following type and table definitions:

    conn.exec("CREATE TYPE complex AS (r float, i float) ")
    conn.exec("CREATE TABLE my_table (v1 complex, v2 complex) ")

A record can be encoded by adding a type map to `Connection#exec_params` and siblings:

    # Build a type map for the two floats "r" and "i" as in our "complex" type
    tm = PG::TypeMapByColumn.new([PG::TextEncoder::Float.new]*2)
    # Build a record encoder to encode this type as a record:
    enco = PG::TextEncoder::Record.new(type_map: tm)
    # Insert table data and use the encoder to cast the complex value "v1" from ruby array:
    conn.exec_params("INSERT INTO my_table VALUES ($1) RETURNING v1", [[1,2]], 0, PG::TypeMapByColumn.new([enco])).to_a
    # => [{"v1"=>"(1,2)"}]

Alternatively the typemap can be build based on database OIDs rather than manually assigning encoders.

    # Fetch a NULL record of our type to retrieve the OIDs of the two fields "r" and "i"
    oids = conn.exec( "SELECT (NULL::complex).*" )
    # Build a type map (PG::TypeMapByColumn) for encoding the "complex" type
    etm = PG::BasicTypeMapBasedOnResult.new(conn).build_column_map( oids )

It's also possible to use the `BasicTypeMapForQueries` to send records to the database server. In contrast to ORM libraries, `PG` doesn't have information regarding the type of data the server is expecting. So `BasicTypeMapForQueries` works based on the class of the values to be sent and it has to be instructed that a ruby array shall be casted to a record.

    # Retrieve OIDs of all basic types from the database
    etm = PG::BasicTypeMapForQueries.new(conn)
    etm.encode_array_as = :record
    # Apply the basic type registry to all values sent to the server
    conn.type_map_for_queries = etm
    # Send a complex number as an array of two integers
    conn.exec_params("INSERT INTO my_table VALUES ($1) RETURNING v1", [[1,2]]).to_a
    # => [{"v1"=>"(1,2)"}]

Records can also be nested or further wrapped into other encoders like `PG::TextEncoder::CopyRow`.

See also `PG::TextDecoder::Record` for the decoding direction.