PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Вмъкване на число с плаваща запетая в таблица с помощта на libpq

Във вашия код има две грешки:

  • Опитвате се да изпратите двоични данни, но не казвате на PQexecParams кой тип е.

    Това не може да работи. При липса на информация за типа PostgreSQL ще използва типа unknown и го третира като низ. Това означава, че вашето двоично представяне ще бъде подадено към float8in функция, която преобразува низове в стойности с двойна точност, което ще се провали ужасно. Вероятно това е, което наблюдавате.

    Ще трябва да използвате четвърти параметър с Oid[] който съдържа 701 (или FLOAT8OID ако предпочитате да използвате #define на PostgreSQL , но ще трябва да #include <postgres.h> и <catalog/pg_type.h> за това).

  • Погрешно приемате, че двоичното представяне на PostgreSQL на double precision type е двоичният формат за double в употреба на вашата клиентска машина.

    Това може случайно да проработи, ако програмата ви работи на big-endian машина, тъй като почти всяка архитектура в днешно време използва IEEE числа с плаваща запетая .

    Ако прочетете изходния код, ще откриете, че двоичният формат на PostgreSQL по кабела е дефиниран в pq_sendfloat8 в src/backend/libpq/pqformat.c , който извиква pq_sendint64 , който преобразува 8-байтовата стойност в мрежов ред на байтовете (което е същото като представянето с голям ред).

Така че ще трябва да дефинирате функция за преобразуване, подобна на тази:

static void to_nbo(double in, double *out) {
    uint64_t *i = (uint64_t *)&in;
    uint32_t *r = (uint32_t *)out;

    /* convert input to network byte order */
    r[0] = htonl((uint32_t)((*i) >> 32));
    r[1] = htonl((uint32_t)*i);
}

Тогава вашият код може да изглежда така:

Oid types[1];
double converted;

...

types[0] = FLOAT8OID;
to_nbo(value, &converted);
values[0] = (char *)&converted;

Но честно казано, би било много по-лесно да се използва представянето на текст. Това ще направи кода ви независим от вътрешността на PostgreSQL и вероятно не е много по-бавен.

Не изглежда така, но ако double precision стойностите се изтеглят от таблица на PostgreSQL някъде другаде, можете да зададете extra_float_digits = 3 така че да е гарантирано, че няма да загубите никаква точност, когато стойностите се преобразуват в тяхното низово представяне.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да направите заявка без значение за главни букви в Postgresql?

  2. Отменете текущата/активната заявка в Ruby on Rails

  3. Генерирайте времеви редове с ежедневна статистика, като използвате заявка на PostgreSQL

  4. pgAdmin - Споделяне на дефиниции за връзка с DB

  5. Задаването на схема в PostgreSQL JDBC изглежда не работи