#include "pq-command.h" #include #include #include #include #include namespace Glib { class ustring; } namespace PQ { class Connection; } NAMEDFACTORY("postgresql", PQ::CommandOptions, DB::CommandOptionsFactory) AdHocFormatter(PQCommondStatement, "pStatement_id%?"); PQ::Command::Command(Connection * conn, const std::string & sql, const DB::CommandOptionsCPtr & opts) : DB::Command(sql), hash(opts && opts->hash ? *opts->hash : std::hash()(sql)), stmntName(PQCommondStatement::get(hash)), c(conn) { } PQ::CommandOptions::CommandOptions(std::size_t hash, const DB::CommandOptionsMap & map) : DB::CommandOptions(hash), fetchTuples(get(map, "page-size", DEFAULT_FETCH_TUPLES)), useCursor(!isSet(map, "no-cursor")), fetchBinary(isSet(map, "fetch-binary")) { } PQ::CommandOptions::CommandOptions(std::size_t hash, unsigned int fetchTuples, bool useCursor, bool fetchBinary) : DB::CommandOptions(hash), fetchTuples(fetchTuples), useCursor(useCursor), fetchBinary(fetchBinary) { } AdHocFormatter(PQCommandParamName, "$%?"); void PQ::Command::prepareSql(std::stringstream & psql, const std::string & sql) const { if (values.empty()) { psql << sql; return; } int paramNo = 1; bool inquote = false; for (const auto & sqlChr : sql) { if (sqlChr == '?' && !inquote) { PQCommandParamName::write(psql, paramNo++); } else if (sqlChr == '\'') { inquote = !inquote; psql << sqlChr; } else { psql << sqlChr; } } } void PQ::Command::paramsAtLeast(unsigned int n) { if (values.size() <= n) { values.resize(n + 1, nullptr); lengths.resize(n + 1, 0); formats.resize(n + 1, 0); bufs.resize(n + 1); } } AdHocFormatter(PQCommandParamFmt, "%?"); template void PQ::Command::paramSet(unsigned int n, T &&... paramValues) { paramsAtLeast(n); // cppcheck-suppress constStatement bufs[n] = std::make_unique(PQCommandParamFmt::get(std::forward(paramValues)...)); lengths[n] = static_cast(bufs[n]->length()); formats[n] = 0; values[n] = bufs[n]->data(); } void PQ::Command::paramSet(unsigned int n, const std::string_view paramValue) { paramsAtLeast(n); bufs[n] = std::make_unique(paramValue); lengths[n] = static_cast(paramValue.length()); formats[n] = 0; values[n] = bufs[n]->data(); } void PQ::Command::bindParamI(unsigned int n, int paramValue) { paramSet(n, paramValue); } void PQ::Command::bindParamI(unsigned int n, long int paramValue) { paramSet(n, paramValue); } void PQ::Command::bindParamI(unsigned int n, long long int paramValue) { paramSet(n, paramValue); } void PQ::Command::bindParamI(unsigned int n, unsigned int paramValue) { paramSet(n, paramValue); } void PQ::Command::bindParamI(unsigned int n, long unsigned int paramValue) { paramSet(n, paramValue); } void PQ::Command::bindParamI(unsigned int n, long long unsigned int paramValue) { paramSet(n, paramValue); } void PQ::Command::bindParamB(unsigned int n, bool paramValue) { paramSet(n, paramValue); } void PQ::Command::bindParamF(unsigned int n, double paramValue) { paramSet(n, paramValue); } void PQ::Command::bindParamF(unsigned int n, float paramValue) { paramSet(n, paramValue); } void PQ::Command::bindParamS(unsigned int n, const Glib::ustring & paramValue) { paramSet(n, std::string_view(paramValue.data(), paramValue.bytes())); } void PQ::Command::bindParamS(unsigned int n, const std::string_view paramValue) { paramSet(n, paramValue); } void PQ::Command::bindParamT(unsigned int n, const boost::posix_time::time_duration paramValue) { paramSet(n, boost::posix_time::to_simple_string(paramValue)); } void PQ::Command::bindParamT(unsigned int n, const boost::posix_time::ptime paramValue) { paramSet(n, boost::posix_time::to_iso_extended_string(paramValue)); } void PQ::Command::bindParamBLOB(unsigned int n, const DB::Blob & paramValue) { paramsAtLeast(n); lengths[n] = static_cast(paramValue.len); formats[n] = 1; values[n] = static_cast(paramValue.data); bufs[n].reset(); } void PQ::Command::bindNull(unsigned int n) { paramsAtLeast(n); lengths[n] = 0; formats[n] = 0; values[n] = nullptr; bufs[n].reset(); }