1
0
Fork 0
mirror of https://github.com/KingDuckZ/dindexer.git synced 2024-11-25 00:53:43 +00:00

Fix reading values from ResultSet/Row.

Send correct group_id to the db in a safer way.
This commit is contained in:
King_DuckZ 2015-12-31 00:38:44 +00:00
parent 9bb5689d48
commit 1532d3c083
4 changed files with 99 additions and 19 deletions

View file

@ -44,6 +44,8 @@ namespace pq {
std::string operator[] ( std::size_t parIndex ) const;
Row& operator= ( const Row& ) = delete;
Row& operator= ( Row&& ) = delete;
bool is_null ( std::size_t parIndex ) const;
bool is_null ( const std::string& parIndex ) const;
const_iterator begin ( void ) const;
const_iterator end ( void ) const;
@ -53,6 +55,8 @@ namespace pq {
private:
struct LocalData;
std::string get_as_str_assume_valid ( int parIndex ) const;
std::unique_ptr<LocalData> m_localData;
};

View file

@ -196,7 +196,8 @@ namespace pq {
}
ResultSet Connection::query_params (const std::string& parQuery, PGParams& parParams) {
int result_format = 1;
//TODO: make result_format parametric
int result_format = 0;
assert(parParams.get());
ResultInfo info(
PQparamExec(

View file

@ -25,8 +25,46 @@
#include <boost/lexical_cast.hpp>
#include <algorithm>
#include <boost/bind.hpp>
#include "libpqtypes.h"
namespace pq {
namespace {
int cast_col_index_or_throw (std::size_t parIndex, std::size_t parCount, const char* parFile, int parLine) {
if (parIndex >= parCount) {
std::ostringstream oss;
oss << "Requested column at index " << parIndex << " is out of range (column count is " << parCount << ')';
throw DatabaseException("Error retrieving column", oss.str(), parFile, parLine);
}
return static_cast<int>(parIndex);
}
int conv_col_index_or_throw (const std::string& parIndex, const std::map<std::string, int>& parCols, const char* parFile, int parLine) {
const auto num_index_it = parCols.find(parIndex);
if (parCols.end() == num_index_it) {
throw DatabaseException("Error retrieving column", "Requested column \"" + parIndex + "\" doesn't exist", parFile, parLine);
}
return num_index_it->second;
}
std::string binary_to_string (const char* parValue, Oid parType, int parLength) {
using boost::lexical_cast;
assert(parValue);
assert(parLength > 0);
//TODO: use libpqtypes
switch (parType) {
case 21:
return lexical_cast<std::string>(*reinterpret_cast<const uint16_t*>(parValue));
default:
//not implemented
assert(false);
return std::string();
}
}
} //unnamed namespace
struct Row::LocalData {
LocalData ( const PGresult* parResult, std::size_t parRow, const std::map<std::string, int>* parCols, std::size_t parColCount ) :
result(parResult),
@ -70,13 +108,7 @@ namespace pq {
}
std::string Row::operator[] (const std::string& parIndex) const {
assert(m_localData->columns);
const auto num_index_it = m_localData->columns->find(parIndex);
if (num_index_it == m_localData->columns->end())
throw DatabaseException("Error retrieving column", "Requested column \"" + parIndex + "\" doesn't exist", __FILE__, __LINE__);
const int num_index = num_index_it->second;
return PQgetvalue(m_localData->result, static_cast<int>(m_localData->row_index), num_index);
return get_as_str_assume_valid(conv_col_index_or_throw(parIndex, *m_localData->columns, __FILE__, __LINE__));
}
std::size_t Row::size() const {
@ -88,13 +120,47 @@ namespace pq {
}
std::string Row::operator[] (std::size_t parIndex) const {
if (parIndex >= m_localData->col_count) {
std::ostringstream oss;
oss << "Requested column at index " << parIndex << " is out of range (column count is " << m_localData->col_count << ')';
throw DatabaseException("Error retrieving column", oss.str(), __FILE__, __LINE__);
}
return get_as_str_assume_valid(cast_col_index_or_throw(parIndex, m_localData->col_count, __FILE__, __LINE__));
}
return PQgetvalue(m_localData->result, static_cast<int>(m_localData->row_index), static_cast<int>(parIndex));
std::string Row::get_as_str_assume_valid (int parIndex) const {
const int num_index = parIndex;
const auto row_index = static_cast<int>(m_localData->row_index);
const auto format = PQfformat(m_localData->result, num_index);
const int data_len = PQgetlength(m_localData->result, row_index, num_index);
switch (format) {
case 0:
//textual data
return std::string(PQgetvalue(m_localData->result, row_index, num_index), data_len);
case 1:
//binary data
if (is_null(num_index)) {
return std::string();
}
else {
return binary_to_string(
PQgetvalue(m_localData->result, row_index, num_index),
PQftype(m_localData->result, num_index),
data_len
);
}
default:
//unknown
assert(false);
return std::string();
}
}
bool Row::is_null (std::size_t parIndex) const {
const auto num_index = cast_col_index_or_throw(parIndex, m_localData->col_count, __FILE__, __LINE__);
const auto row_index = static_cast<int>(m_localData->row_index);
return (1 == PQgetisnull(m_localData->result, row_index, num_index) ? true : false);
}
bool Row::is_null (const std::string& parIndex) const {
const auto num_index = conv_col_index_or_throw(parIndex, *m_localData->columns, __FILE__, __LINE__);
const auto row_index = static_cast<int>(m_localData->row_index);
return (1 == PQgetisnull(m_localData->result, row_index, num_index) ? true : false);
}
Row::const_iterator Row::begin() const {

View file

@ -81,6 +81,7 @@ namespace din {
void write_to_db (const dinlib::SettingsDB& parDB, const std::vector<FileRecordData>& parData, const SetRecordData& parSetData) {
using std::chrono::system_clock;
using boost::lexical_cast;
if (parData.empty()) {
return;
@ -90,22 +91,30 @@ namespace din {
conn.connect();
conn.query("BEGIN;");
conn.query("INSERT INTO \"sets\" (\"desc\",\"type\") VALUES ($1, $2)",
parSetData.name,
std::string(1, parSetData.type)
);
uint32_t new_group_id;
{
auto id_res = conn.query("INSERT INTO \"sets\" (\"desc\",\"type\") VALUES ($1, $2) RETURNING \"id\";",
parSetData.name,
std::string(1, parSetData.type)
);
assert(id_res.size() == 1);
assert(id_res[0].size() == 1);
//TODO: make it possible to get the id directly as a string
new_group_id = lexical_cast<uint32_t>(id_res[0][0]);
}
for (std::size_t z = 0; z < parData.size(); ++z) {
const std::string query = "INSERT INTO \"files\" (path, hash, "
"level, group_id, is_directory, is_symlink, size, "
"access_time, modify_time, is_hash_valid, unreadable) VALUES "
"($1, $2, $3, currval('\"sets_id_seq\"'), $4, $5, $6, $7, $8, $9, $10);";
"($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11);";
const auto& itm = parData[z];
conn.query(query,
itm.path,
tiger_to_string(itm.hash),
itm.level,
new_group_id,
itm.is_directory,
itm.is_symlink,
itm.size,