#include "odbc-param.h" #include "command.h" #include "odbc-command.h" #include "odbc-error.h" #include "odbc-param_fwd.h" #include #include #include #include #include namespace Glib { class ustring; } ODBC::Param::Param() : paramCmd(nullptr), paramIdx(0), paramBound(false), dataLength(0) { } ODBC::Param::Param(Command * c, unsigned int i) : paramCmd(c), paramIdx(i), paramBound(false), dataLength(0) { } template ParamType * ODBC::Command::makeParam(unsigned int idx) { if (idx >= params.size()) { throw DB::ParameterOutOfRange(); } auto & p = params[idx]; if (p) { if (auto np = dynamic_cast(p.get())) { return np; } } p = std::make_unique(this, idx); return static_cast(p.get()); } void ODBC::Param::bind() const { if (!paramBound) { SQLRETURN rc = SQLBindParameter(paramCmd->hStmt, static_cast(paramIdx + 1), SQL_PARAM_INPUT, ctype(), stype(), size(), dp(), const_cast(dataAddress()), static_cast(size()), &bindLen); if (!SQL_SUCCEEDED(rc)) { throw Error(rc, SQL_HANDLE_STMT, paramCmd->hStmt); } paramBound = true; } } #define SIMPLEBINDER(ctype, otype, suf) \ void ODBC::Command::bindParam##suf(unsigned int i, ctype val) \ { \ ODBC::otype * p = makeParam(i); \ *p = val; \ p->bind(); \ } SIMPLEBINDER(int, SignedIntegerParam, I) SIMPLEBINDER(long, SignedIntegerParam, I) SIMPLEBINDER(long long, SignedIntegerParam, I) SIMPLEBINDER(unsigned int, UnsignedIntegerParam, I) SIMPLEBINDER(unsigned long int, UnsignedIntegerParam, I) SIMPLEBINDER(unsigned long long int, UnsignedIntegerParam, I) SIMPLEBINDER(bool, BooleanParam, B) SIMPLEBINDER(double, FloatingPointParam, F) SIMPLEBINDER(float, FloatingPointParam, F) SIMPLEBINDER(const Glib::ustring &, StdStringParam, S) SIMPLEBINDER(const std::string_view &, StdStringParam, S) SIMPLEBINDER(const boost::posix_time::ptime &, TimeStampParam, T) SIMPLEBINDER(const boost::posix_time::time_duration &, IntervalParam, T) void ODBC::Command::bindNull(unsigned int i) { makeParam(i)->bind(); } ODBC::StdStringParam & ODBC::StdStringParam::operator=(Glib::ustring const & d) { const char * addr = data.data(); data = d; bindLen = static_cast(d.bytes()); // cppcheck-suppress invalidContainer if (addr != data.data()) { paramBound = false; bind(); } return *this; } ODBC::StdStringParam & ODBC::StdStringParam::operator=(std::string_view const & d) { const char * addr = data.data(); data = d; bindLen = static_cast(d.length()); // cppcheck-suppress invalidContainer if (addr != data.data()) { paramBound = false; bind(); } return *this; } ODBC::TimeStampParam & ODBC::TimeStampParam::operator=(const boost::posix_time::ptime & d) { data.year = static_cast(d.date().year()); data.month = d.date().month(); data.day = d.date().day(); data.hour = static_cast(d.time_of_day().hours()); data.minute = static_cast(d.time_of_day().minutes()); data.second = static_cast(d.time_of_day().seconds()); data.fraction = static_cast(d.time_of_day().fractional_seconds()); return *this; } ODBC::IntervalParam & ODBC::IntervalParam::operator=(const boost::posix_time::time_duration & d) { data.interval_type = SQL_IS_DAY_TO_SECOND; data.interval_sign = d.is_negative(); data.intval.day_second.day = static_cast(d.hours() / 24); data.intval.day_second.hour = static_cast(d.hours() % 24); data.intval.day_second.minute = static_cast(d.minutes()); data.intval.day_second.second = static_cast(d.seconds()); data.intval.day_second.fraction = static_cast(d.fractional_seconds()); return *this; }