Thread: Problem with composite type creation in C under Linux

Problem with composite type creation in C under Linux

From
Marios Vodas
Date:
I have developed some custom composite and base types in PostgreSQL 9 which you can find in the code I provide below.
I compile my C library using GCC 4.5 under Linux and Visual Studio 2010 under Windows.

The problem is when I run this command: SELECT to_composite('((1, 2), (3, 4))'::m_segment_base).
This is the result I get in Windows and Linux respectively:

    Windows: "("(1,2)","(3,4)")"
    Linux: "("(1,)",)"

Probably the composite type is not created well in function "to_composite", but I guess the code should be OK since it works under MSVC...

So my question is why this doesn't work under Linux? And how can I fix it of course.

Here is my code in SQL and C:


***SQL code***
CREATE TYPE m_point_composite AS
(
    x double precision,
    y double precision
);

CREATE TYPE m_segment_composite AS
(
    i m_point_composite,
    e m_point_composite
);

CREATE TYPE m_point_base
(
    INTERNALLENGTH = 16,
    INPUT = m_point_base_in,
    OUTPUT = m_point_base_out,
    RECEIVE = m_point_base_recv,
    SEND = m_point_base_send,
    ALIGNMENT = double
);

CREATE TYPE m_segment_base
(
    INTERNALLENGTH = 32,
    INPUT = m_segment_base_in,
    OUTPUT = m_segment_base_out,
    RECEIVE = m_segment_base_recv,
    SEND = m_segment_base_send,
    ALIGNMENT = double
); 

CREATE OR REPLACE FUNCTION to_composite(m_segment_base)
RETURNS m_segment_composite AS
    '$libdir/myLib','to_composite'
LANGUAGE 'C' IMMUTABLE STRICT;

***C code***
struct m_point_base {
    float8 x;
    float8 y;
};

struct m_segment_base {
    m_point_base i;
    m_point_base e;
};

PGDLLEXPORT Datum to_composite(PG_FUNCTION_ARGS) {
    m_segment_base *in = (m_segment_base *) PG_GETARG_POINTER(0);

    TupleDesc tupdesc;
    bool isnull;

    Datum vi[2];
    HeapTuple i;

    Datum ve[2];
    HeapTuple e;

    Datum vout[2];
    HeapTuple out;

    TupleDesc tupdesc_m_point_composite = RelationNameGetTupleDesc("m_point_composite");

    vi[0] = Float8GetDatum(in->i.x);
    vi[1] = Float8GetDatum(in->i.y);
    i = heap_form_tuple(tupdesc_m_point_composite, vi, &isnull);

    ve[0] = Float8GetDatum(in->e.x);
    ve[1] = Float8GetDatum(in->e.y);
    e = heap_form_tuple(tupdesc_m_point_composite, ve, &isnull);

    vout[0] = HeapTupleGetDatum(i);
    vout[1] = HeapTupleGetDatum(e);

    if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
        ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context that cannot accept type record")));
    }

    BlessTupleDesc(tupdesc);
    out = heap_form_tuple(tupdesc, vout, &isnull);

    PG_RETURN_DATUM(HeapTupleGetDatum(out));
}
PG_FUNCTION_INFO_V1(to_composite)
;

Re: Problem with composite type creation in C under Linux

From
Tom Lane
Date:
Marios Vodas <mvodas@gmail.com> writes:
> I have developed some custom composite and base types in PostgreSQL 9 which
> you can find in the code I provide below.
> I compile my C library using GCC 4.5 under Linux and Visual Studio 2010
> under Windows.

> The problem is when I run this command: *SELECT to_composite('((1, 2), (3,
> 4))'::m_segment_base)*.
> This is the result I get in Windows and Linux respectively:
>     Windows: "("(1,2)","(3,4)")"
>     Linux: "("(1,)",)"

You're passing a single isnull flag to heap_form_tuple calls that are
expecting arrays of two flags ... and even the one value that's there
according to the code isn't being initialized, so it's remarkable that
this code works at all on any platform.
        regards, tom lane


Re: Problem with composite type creation in C under Linux

From
Marios Vodas
Date:
Thank you! now I understand it...<br /><br /><div class="gmail_quote">On Wed, Mar 2, 2011 at 7:35 PM, Tom Lane <span
dir="ltr"><<ahref="mailto:tgl@sss.pgh.pa.us">tgl@sss.pgh.pa.us</a>></span> wrote:<br /><blockquote
class="gmail_quote"style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div class="im">Marios Vodas
<<ahref="mailto:mvodas@gmail.com">mvodas@gmail.com</a>> writes:<br /> > I have developed some custom composite
andbase types in PostgreSQL 9 which<br /> > you can find in the code I provide below.<br /> > I compile my C
libraryusing GCC 4.5 under Linux and Visual Studio 2010<br /> > under Windows.<br /><br /> > The problem is when
Irun this command: *SELECT to_composite('((1, 2), (3,<br /> > 4))'::m_segment_base)*.<br /> > This is the result
Iget in Windows and Linux respectively:<br /> >     Windows: "("(1,2)","(3,4)")"<br /> >     Linux:
"("(1,)",)"<br/><br /></div>You're passing a single isnull flag to heap_form_tuple calls that are<br /> expecting
arraysof two flags ... and even the one value that's there<br /> according to the code isn't being initialized, so it's
remarkablethat<br /> this code works at all on any platform.<br /><br />                        regards, tom lane<br
/></blockquote></div><br/>