Oops, I forgot to mention that we slightly modified libpq to request resulting fields formats (since Postgres protocol v3 supports this). See our additions in Bold:
PQexec(PGconn *conn, const char *query, int resultFormatCount, const int* resultFormats)
{
if (!PQexecStart(conn))
return NULL;
if (!PQsendQuery(conn, query, resultFormatCount, resultFormats))
return NULL;
return PQexecFinish(conn, 0);
}
where PQsendQuery passes requested format in the Bind message:
/* construct the Bind message */
if (pqPutMsgStart('B', false, conn) < 0 ||
pqPuts("", conn) < 0 ||
pqPuts(""/* use unnamed statement */, conn) < 0)
goto sendFailed;
/* no parameters formats */
if (pqPutInt(0, 2, conn) < 0)
goto sendFailed;
if (pqPutInt(0, 2, conn) < 0)
goto sendFailed;
if (pqPutInt(resultFormatCount, 2, conn) < 0)
goto sendFailed;
for (i = 0; i < resultFormatCount; i++)
{
if (pqPutInt(resultFormats[i], 2, conn) < 0)
goto sendFailed;
}The above is being used for about 10 years in our variant of libpq. It works for everything except for the case with ARRAY.