Сохранение std :: vector в postgresql с помощью pqxx и извлечение его из базы данных. - PullRequest
0 голосов
/ 30 октября 2018

Мне нужно сохранить содержимое std::vector<uint8_t> в базе данных postgresql и иметь возможность снова его получить. Я использую библиотеку pqxx в качестве «оболочки» для подключения к базе данных. Для хранения я делаю это:

      std::string query = "INSERT INTO file_pivot(file_id, p_id, deviation) VALUES($1, $2, $3) RETURNING id";

      pqxx::binarystring deviation((void*)&(data), data.size());

      conn.prepare("file_insert", query);
      pqxx::result res = worker.prepared("file_insert")(1)(pivot_id)(deviation).exec();

      worker.commit();

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

То, что я пытался сделать, это:

      pqxx::work sworker(conn);
      std::string squery = "SELECT * FROM file_pivot WHERE file_id = $1";

      conn.prepare("select_file", squery);
      pqxx::result sres = sworker.prepared("select_file")(file_id).exec();

      std::vector<uint8_t> rdata;
      if(sres.size() > 0)
      {
          pqxx::binarystring sblob(res[0][3]);
          std::vector<uint8_t>*rrdata = (std::vector<uint8_t>*) sblob.data();
          rdata = *rrdata;
      }

Но когда я тогда сравниваю исходный вектор data с rdata, вот так:

      assert(std::equal(data.begin(), data.end(), rdata.begin()));

Я получаю ошибку сегментации, я пытался использовать rrdata->begin(), а также ту же проблему. Может кто-нибудь помочь с этим, это начинает действовать мне на нервы.

1 Ответ

0 голосов
/ 30 октября 2018

pqxx::binarystring::data не возвращает указатель на вектор, поэтому вы не можете просто рассматривать его как тот, который вы делаете здесь:

          std::vector<uint8_t>*rrdata = (std::vector<uint8_t>*) sblob.data();

Скорее, функция data() возвращает указатель на необработанные данные. Чтобы построить вектор из этого, самый простой способ - использовать итераторы, предоставляемые pqxx::binarystring, например:

std::vector<uint8_t> rdata(sblob.begin(), sblob.end());

Поскольку итераторы определены по типу как простые старые указатели, конструктор std::vector сможет вычесть их, чтобы выделить правильный размер для вектора за один раз.

Обратите внимание, что это делает копию данных; нет способа построить вектор из существующей памяти, потому что вектору всегда принадлежит память, на которую он указывает.


Вместо использования std::vector<uint8_t> может быть проще использовать std::string. Строка в C ++ - это просто последовательность char с (байтов), а не символов, и pqxx::binarystring имеет встроенные преобразования из и в std::string.


corner Угол Нитпикера: если вы не используете подходящий пользовательский распределитель. Не рекомендуется.

...