#### 7.4.3 Working with composite types

This is a more complicated example with nested composite types.

    # connect
    conn = pq_connect (setdbopts ("dbname", "test"));

    # create a first composite type, consisting of a boolean and an array of
    # booleans
    pq_exec_params (conn,
    "create type complex_bool_array_type as (b bool, ba bool[]);")

    # create a second composite type, consisting of a boolean and the first
    # composite type
    pq_exec_params (conn,
    "create type complex_complex_bool_array_type as (b bool, c complex_bool_array_type);")

    # create a table with one column, holding the second defined composite
    # type
    pq_exec_params (conn,
    "create table complex_complex_bool_array (a complex_complex_bool_array_type);")

    # to enable data exchange using the new types, update type infomation
    pq_update_types (conn);

    # construct a data element for an SQL array of booleans in Octave
    d_arr = cell2struct ({2; {true, false; true, true}}, {"ndims", "data"})

    # construct a data element for the first defined composite type in
    # Octave
    d_c1 = {true; d_arr};

    # construct a data element for the second defined composite type in
    # Octave
    d_c2 = {false; d_c1};

    # insert the data element of the second composite type into the table;
    # note that in this case specification of the parameter type in
    # `param_types' is necessary
    pq_exec_params (conn,
                    "insert into complex_complex_bool_array values ($1);",
                    {d_c2},
                    setdbopts ("param_types", {"complex_complex_bool_array_type"}))

    # read contents of the table
    result = pq_exec_params (conn, "select * from complex_complex_bool_array");

    # only for demonstration purpouses, verify that the read data matches
    # the element constructed in Octave;
    # for this, the field `lbounds' is deleted from the returned data
    #
    # note that the verification would not work if we had constructed the
    # data element with rows of cell-arrays instead of columns, which would
    # also have been possible
    rdata = result.data{1};
    rdata{2}{2} = rmfield (rdata{2}{2}, "lbounds");
    isequal (d_c2, rdata)

    # view returned column names
    result.columns

    # view returned type information
    result.types

    # cleanup

    pq_exec_params (conn, "drop table complex_complex_bool_array;")

    pq_exec_params (conn, "drop type complex_complex_bool_array_type;")

    pq_exec_params (conn, "drop type complex_bool_array_type;")

    pq_close (conn);