Re: Enum binary access - Mailing list pgsql-hackers
From | Petr Chmelar |
---|---|
Subject | Re: Enum binary access |
Date | |
Msg-id | 5062F642.6000601@fit.vutbr.cz Whole thread Raw |
In response to | Re: Enum binary access (Merlin Moncure <mmoncure@gmail.com>) |
List | pgsql-hackers |
Hi Merlin, thanks, your code works perfectly. Cheers, Petr On 10.9.2012 16:33, Merlin Moncure wrote: > On Mon, Sep 10, 2012 at 8:42 AM, Petr Chmelar <chmelarp@fit.vutbr.cz> wrote: >> Hi there, >> >> we tried to create the libpqtypes enum binary send but it doesn't work: >> >> // register types >> PGregisterType user_def[] = { {"seqtype", enum_put, enum_get} }; >> PQregisterTypes(connector->getConn(), PQT_USERDEFINED, user_def, 1, 0); >> >> // enum_put throws format error >> int enum_put (PGtypeArgs *args ) { >> >> char *val = va_arg(args->ap, char *); >> char *out = NULL; >> int vallen = 0, len = 0, oid = 0; >> float sortorder = 0.0; >> >> if (!args || !val) return 0; >> >> /* expand buffer enough */ >> vallen = strlen(val); >> len = sizeof(int) + sizeof(float) + (vallen * sizeof(char)); >> if (args->put.expandBuffer(args, len) == -1) return -1; >> >> /* put header (oid, sortorder) and value */ >> out = args->put.out; >> memcpy(out, &oid, sizeof(int)); >> out += sizeof(int); >> memcpy(out, &sortorder, sizeof(float)); >> out += sizeof(float); >> memcpy(out, val, vallen); >> >> return len; >> } >> >> // enum_get (FYI, get works OK) >> int enum_get (PGtypeArgs *args) { >> char *val = PQgetvalue(args->get.result, args->get.tup_num, >> args->get.field_num); >> int len = PQgetlength(args->get.result, args->get.tup_num, >> args->get.field_num); >> char **result = va_arg(args->ap, char **); >> *result = (char *) PQresultAlloc((PGresult *) args->get.result, len * >> sizeof(char)); >> memcpy(*result, val, len * sizeof(char)); >> return 0; >> } >> >> Postgres doesn't accept enum sent like this and throws format error. This >> should be used as a prototype for derived types. There is no real "enum" >> named type. Libpqypes doesn't seem to provide simplified binary manipulation >> for enum types. >> >> What should we do, please? Can you fix it? I think there is more people that >> need access enum types in binary mode. > I was able to get it to work what I did: > > *) your 'get' routine should probably be allocating a terminating > byte. In binary situations, PQgetlength does not return the length of > the null terminator. > > *) backend binary format for enums is just the label text string both > on get and put side. So your putting the oid and sort order was > breaking the put side. Removed that and everything worked. > > *) see (very messy quickly written) code below: > > > #include "libpq-fe.h" > #include "libpqtypes.h" > #include "string.h" > > > // enum_put throws format error > int enum_put (PGtypeArgs *args ) { > > char *val = va_arg(args->ap, char *); > char *out = NULL; > int vallen = 0, len = 0, oid = 0; > float sortorder = 0.0; > > if (!args || !val) return 0; > > /* expand buffer enough */ > vallen = strlen(val); > if (args->put.expandBuffer(args, len) == -1) return -1; > > out = args->put.out; > memcpy(out, val, vallen); > > return len; > } > > // enum_get (FYI, get works OK) > int enum_get (PGtypeArgs *args) { > char *val = PQgetvalue(args->get.result, args->get.tup_num, > args->get.field_num); > int len = PQgetlength(args->get.result, args->get.tup_num, > args->get.field_num) + 1; > char **result = va_arg(args->ap, char **); > *result = (char *) PQresultAlloc((PGresult *) args->get.result, > len * sizeof(char)); > memcpy(*result, val, len * sizeof(char)); > result[len] = 0; > return 0; > } > > > int main() > { > PGtext t = "b"; > > PGconn *conn = PQconnectdb("port=5492 host=localhost"); > PQinitTypes(conn); > > PGregisterType user_def[] = { {"e", enum_put, enum_get} }; > > if(!PQregisterTypes(conn, PQT_USERDEFINED, user_def, 1, 0)) > fprintf(stderr, "*ERROR: %s\n", PQgeterror()); > > > PGresult *res = PQexecf(conn, "select %e", t); > > if(!res) > fprintf(stderr, "*ERROR: %s\n", PQgeterror()); > > if (!PQgetf(res, 0, "%e", 0, &t)) > { > fprintf(stderr, "*ERROR: %s\n", PQgeterror()); > } > > printf("%s\n", t); > > PQclear(res); > } > >
pgsql-hackers by date: