Вставьте двоичный файл с плавающей запятой, используя PQexecParams

Может быть, я сделал ошибку, как я могу напрямую вставить двоичный файл с плавающей запятой в мою таблицу. Я не знаю, правильно ли я все сделал. Код работает, но значения неверны Спасибо за ответ

static void to_nbo(double in, double *out) {
    uint64_t *i = (uint64_t *)∈
    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);
}
 const char command[] = "INSERT INTO car1 (id, price, sale)"
                         "VALUES($1::integer, $2::real, $3::real)";

  int nParams = 3;
  //const char *const paramValues[] = {"2.545","44.655"};

  const Oid paramTypes[] = {23, 700, 700};
  const int paramLengths[] = {sizeof(int), sizeof(int), sizeof(int)};
  const int paramFormats[] = {1, 1, 1};
  int resultFormat = 0;

  int test = htonl(45);
  double test2;
  double test3;
  to_nbo(75.585, &test2);
  to_nbo(8.4785, &test3);
  //char paramFloat[] ={0x41,0x40,0x00,0x00}; //12.0
  //char paramFloat1[] ={0x42,0x32,(char) 0x9e, (char) 0xb8}; //44.655
  //char paramFloat[] ={0x00,0x00, 0x40,0x41}; //12.0
  //char paramFloat1[] ={(char) 0xb8,(char) 0x9e,0x32,0x42}; //44.655
  //const char *const paramValues2[] = {paramFloat, paramFloat1};

 const char *const paramValues2[] = {(const char*)&test, (const char*)&test2, (const char*)&test3};

  /* PQexecParams INSERT */
  res = PQexecParams(conn, command, nParams, paramTypes, paramValues2, paramLengths, paramFormats, resultFormat);
  if (PQresultStatus(res) != PGRES_COMMAND_OK) {
      std::cout << "PQexecParams failed: " << PQresultErrorMessage(res)
                << std::endl;
  }

person Derrick    schedule 15.07.2020    source источник
comment
Примечание: считается хорошим тоном ссылаться на ваш предыдущий вопрос, даже если на него нет принятого ответа, или редактировать его.   -  person Botje    schedule 15.07.2020


Ответы (1)


Вы не предоставляете функции PQExecParams никакой информации о типе ваших двоичных данных. Он пытается проанализировать этот двоичный мусор как строку, содержащую число с плавающей запятой.

Отредактируйте свой SQL-запрос следующим образом:

const char command[] = "INSERT INTO car1 (id, price, sale)"
                         "VALUES($1::integer, $2::real, $3::real)";

это дает Postgres подсказку, какие типы вы будете вставлять.

В качестве альтернативы заполните массив paramTypes[]; у него есть следующая документация:

Указывает по OID типы данных, которые должны быть назначены символам параметров. Если paramTypes имеет значение NULL или какой-либо конкретный элемент в массиве равен нулю, сервер выводит тип данных для символа параметра так же, как и для нетипизированной литеральной строки.

Даже в этом случае вам может потребоваться выполнить замену байтов в соответствии с этим ответом

РЕДАКТИРОВАТЬ: просматривая общедоступный заголовок postgres.h, я думаю, вам нужно передать вывод Float4GetDatum в PQExecParams.

person Botje    schedule 15.07.2020
comment
В моем случае, какие значения я могу передать в ParamTypes[ ] пожалуйста? - person Derrick; 15.07.2020
comment
OID. См. этот ответ - person Botje; 15.07.2020
comment
Я изменил код, но значения в таблице по-прежнему неверны. Я не знаю, в чем ошибка. Можете ли вы помочь, пожалуйста? - person Derrick; 15.07.2020
comment
Я не могу помочь, если вы не предоставите больше информации. Как вы модифицировали код? Что не так? - person Botje; 15.07.2020
comment
Я отредактировал SQL-запрос, а затем заполнил массив paramType[ ]. - person Derrick; 15.07.2020
comment
Я тоже сделал замену байтов, но значения в таблице не совпадают со значениями в запросе - person Derrick; 15.07.2020
comment
Вы всегда пропускали doubles? Поскольку в PostgreSQL это double, а real за floatс. Если это все еще не удается, отредактируйте свой вопрос, указав входы И. Также обратите внимание, что sizeof(int) != sizeof(double) - person Botje; 15.07.2020
comment
Поэтому измените типы в запросе и в paramLengths. - person Botje; 15.07.2020
comment
Я сделал именно то, что вы описали... Теперь это работает! Спасибо - person Derrick; 15.07.2020