Reputation: 2198
I need to store the content of an std::vector<uint8_t>
in a postgresql database and be able to get it out again. I am using the library pqxx as the "wrapper" for database connection.
For storing I do this:
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();
Which does work and store it in the data base, from what I can tell, the issue then getting the damn vector out again.
What I tried to do is this:
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;
}
But when I then compare the original vector data
to rdata
like this:
assert(std::equal(data.begin(), data.end(), rdata.begin()));
I get an segmentation fault, I have tried by using rrdata->begin()
as well same problem.
Can someone help with this, it is starting to get on my nerves.
Upvotes: 0
Views: 1466
Reputation: 181825
pqxx::binarystring::data
does not return a pointer to a vector, so you can't just treat it as one like you're doing here:
std::vector<uint8_t>*rrdata = (std::vector<uint8_t>*) sblob.data();
Rather, the data()
function returns a pointer to the raw data. To construct a vector out of this, the simplest way is to use the iterators provided by pqxx::binarystring
, like so:
std::vector<uint8_t> rdata(sblob.begin(), sblob.end());
Because the iterators are typedef'd as plain old pointers, the std::vector
constructor will be able to subtract them to allocate the right size for the vector in one go.
Note that this does make a copy of the data; there is no way to construct a vector from existing memory, because a vector always¹ owns the memory it points to.
Instead of using a std::vector<uint8_t>
, it might be easier to use std::string
instead. A string in C++ is just a series of char
s (bytes), not characters, and pqxx::binarystring
has built-in conversions from and to std::string
.
¹ Nitpicker's corner: unless you use a suitable custom allocator. Not recommended.
Upvotes: 1