Home Explore Blog CI



postgresql

20th chunk of `doc/src/sgml/ecpg.sgml`
cb7f2bcc2f650dee5f3cb538f809d2469a273ffb3a2b375a0000000100000fa4

</programlisting>

     Although a structure is used in the <command>FETCH</command>
     command, the attribute names in the <command>SELECT</command>
     clause are specified one by one.  This can be enhanced by using
     a <literal>*</literal> to ask for all attributes of the composite
     type value.
<programlisting>
...
EXEC SQL DECLARE cur1 CURSOR FOR SELECT (compval).* FROM t4;
EXEC SQL OPEN cur1;

EXEC SQL WHENEVER NOT FOUND DO BREAK;

while (1)
{
    /* Put all values in the SELECT list into one structure. */
    EXEC SQL FETCH FROM cur1 INTO :compval;

    printf("intval=%d, textval=%s\n", compval.intval, compval.textval.arr);
}
...
</programlisting>
     This way, composite types can be mapped into structures almost
     seamlessly, even though ECPG does not understand the composite
     type itself.
    </para>

    <para>
     Finally, it is also possible to store composite type values in
     their external string representation in host variables of
     type <type>char[]</type> or <type>VARCHAR[]</type>.  But that
     way, it is not easily possible to access the fields of the value
     from the host program.
    </para>
   </sect3>

   <sect3 id="ecpg-variables-nonprimitive-sql-user-defined-base-types">
    <title>User-Defined Base Types</title>

    <para>
     New user-defined base types are not directly supported by ECPG.
     You can use the external string representation and host variables
     of type <type>char[]</type> or <type>VARCHAR[]</type>, and this
     solution is indeed appropriate and sufficient for many types.
    </para>

    <para>
     Here is an example using the data type <type>complex</type> from
     the example in <xref linkend="xtypes"/>.  The external string
     representation of that type is <literal>(%f,%f)</literal>,
     which is defined in the
     functions <function>complex_in()</function>
     and <function>complex_out()</function> functions
     in <xref linkend="xtypes"/>.  The following example inserts the
     complex type values <literal>(1,1)</literal>
     and <literal>(3,3)</literal> into the
     columns <literal>a</literal> and <literal>b</literal>, and select
     them from the table after that.

<programlisting>
EXEC SQL BEGIN DECLARE SECTION;
    varchar a[64];
    varchar b[64];
EXEC SQL END DECLARE SECTION;

    EXEC SQL INSERT INTO test_complex VALUES ('(1,1)', '(3,3)');

    EXEC SQL DECLARE cur1 CURSOR FOR SELECT a, b FROM test_complex;
    EXEC SQL OPEN cur1;

    EXEC SQL WHENEVER NOT FOUND DO BREAK;

    while (1)
    {
        EXEC SQL FETCH FROM cur1 INTO :a, :b;
        printf("a=%s, b=%s\n", a.arr, b.arr);
    }

    EXEC SQL CLOSE cur1;
</programlisting>

     This example shows following result:
<screen>
a=(1,1), b=(3,3)
</screen>
   </para>

    <para>
     Another workaround is avoiding the direct use of the user-defined
     types in ECPG and instead create a function or cast that converts
     between the user-defined type and a primitive type that ECPG can
     handle.  Note, however, that type casts, especially implicit
     ones, should be introduced into the type system very carefully.
    </para>

    <para>
     For example,
<programlisting>
CREATE FUNCTION create_complex(r double, i double) RETURNS complex
LANGUAGE SQL
IMMUTABLE
AS $$ SELECT $1 * complex '(1,0')' + $2 * complex '(0,1)' $$;
</programlisting>
    After this definition, the following
<programlisting>
EXEC SQL BEGIN DECLARE SECTION;
double a, b, c, d;
EXEC SQL END DECLARE SECTION;

a = 1;
b = 2;
c = 3;
d = 4;

EXEC SQL INSERT INTO test_complex VALUES (create_complex(:a, :b), create_complex(:c, :d));
</programlisting>
    has the same effect as
<programlisting>
EXEC SQL INSERT INTO test_complex VALUES ('(1,2)', '(3,4)');
</programlisting>
    </para>
   </sect3>
  </sect2>

  <sect2 id="ecpg-indicators">
   <title>Indicators</title>

   <para>
    The examples above do not handle null values.  In fact, the
    retrieval examples will raise an error if they fetch a null value

Title: ECPG: Handling Composite Types - String Representation and User-Defined Base Types
Summary
Composite types can be stored in their string representation. However, accessing the value's fields is not easily possible from the host program. User-defined base types can be handled in ECPG via string representation using char[] or VARCHAR[]. Also, one could create function or cast that converts between user-defined type and a primitive type ECPG can handle.