Как получить двойное значение с помощью libpq?

Примеры в документации libpq показано, как получить целочисленное значение, преобразовав его в представление с порядковым номером хоста.

Мне интересно, что нужно сделать, чтобы получить значение двойной точности с помощью libpq (без libpqtyppes)? я пытался reinterpret_cast без удачи

Кроме того, почему текстовые и байтовые данные не нуждаются в преобразованиях с прямым порядком байтов?

БД работает локально на Windows 7, я использую Visual C ++ 2013.

pptr это двойная завеса, которую я пытаюсь найти.

#include <iostream>
#include <memory>
#include <vector>
#include <libpq-fe.h>
#include <Winsock2.h>static void
show_binary_results(PGresult *res)
{
int i, j;
int i_fnum, n_fnum, p_fnum;

/* Use PQfnumber to avoid assumptions about field order in result */
i_fnum = PQfnumber(res, "id");
n_fnum = PQfnumber(res, "name");
p_fnum = PQfnumber(res, "price");

for (i = 0; i < PQntuples(res); i++)
{
char* iptr;
char* nptr;
char* pptr;
int         blen;
int         ival;

/* Get the field values (we ignore possibility they are null!) */
iptr = PQgetvalue(res, i, i_fnum);
nptr = PQgetvalue(res, i, n_fnum);
pptr = PQgetvalue(res, i, p_fnum); /*THIS IS A VALUE I AM TRYING TO GET*/

/*
* The binary representation of INT4 is in network byte order, which
* we'd better coerce to the local byte order.
*/
ival = ntohl(*((uint32_t *) iptr));

/*
* The binary representation of TEXT is, well, text, and since libpq
* was nice enough to append a zero byte to it, it'll work just fine
* as a C string.
*
* The binary representation of BYTEA is a bunch of bytes, which could
* include embedded nulls so we have to pay attention to field length.
*/
//blen = PQgetlength(res, i, b_fnum);

printf("tuple %d: got\n", i);
printf(" i = (%d bytes) %d\n",
PQgetlength(res, i, i_fnum), ival);
printf(" t = (%d bytes) '%s'\n",
PQgetlength(res, i, n_fnum), nptr);
printf(" p = (%d bytes) %f\n",
PQgetlength(res, i, p_fnum), *reinterpret_cast<double*>(pptr));

printf("\n\n");
}
}int main(int argc, char* argv [])
{
auto conn_string = "postgresql://postgres:pwd@localhost/db";
auto conn_deleter = [](PGconn* c) { PQfinish(c); };
auto res_deleter = [](PGresult* r) { PQclear(r); std::cout << "deleted" << std::endl; };
std::unique_ptr<PGconn, decltype(conn_deleter)> conn(PQconnectdb(conn_string), conn_deleter);

if (PQstatus(conn.get()) != ConnStatusType::CONNECTION_OK)
std::cerr << "Problem" << std::endl;

std::vector<const char *> params{ "1" };
std::unique_ptr < PGresult, decltype(res_deleter)> res(PQexecParams(conn.get(),
"SELECT * FROM table_with_double WHERE id = $1",
params.size(),       /* one param */
NULL,    /* let the backend deduce param type */
(const char * const *)&params.front(),
NULL,    /* don't need param lengths since text */
NULL,    /* default to all text params */
1), /* ask for binary results */
res_deleter);

if (PQresultStatus(res.get()) != ExecStatusType::PGRES_TUPLES_OK)
std::cout << "SELECT failed: " << PQerrorMessage(conn.get()) << std::endl;
show_binary_results(res.get());
}

3

Решение

По-видимому, данные для двойного столбца имеют порядок байтов с прямым порядком байтов и должны быть преобразованы в порядковый номер байтов. То же, что и целые. На основании этого отлично статья из этого ответ Я использовал простую функцию, чтобы поменять двойное значение.

double double_swap(double d)
{
union
{
double d;
unsigned char bytes[8];
} src, dest;

src.d = d;
dest.bytes[0] = src.bytes[7];
dest.bytes[1] = src.bytes[6];
dest.bytes[2] = src.bytes[5];
dest.bytes[3] = src.bytes[4];
dest.bytes[4] = src.bytes[3];
dest.bytes[5] = src.bytes[2];
dest.bytes[6] = src.bytes[1];
dest.bytes[7] = src.bytes[0];
return dest.d;
}

При применении этой функции правильное значение извлекается из БД.

printf(" p = (%d bytes) %lf\n",
PQgetlength(res, i, p_fnum), double_swap(*((double*) pptr)));
4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]