summaryrefslogtreecommitdiff
path: root/libodbcpp/param.cpp
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2010-09-16 00:01:56 +0000
committerrandomdan <randomdan@localhost>2010-09-16 00:01:56 +0000
commit7297648c278903589beebf6fbc7511e5c1ff421d (patch)
treea2686c7d458aad2c32bcb1ae61cb4e04702fd9d4 /libodbcpp/param.cpp
parentRemove duplication in ODBC::Connection constructors (diff)
downloadlibdbpp-odbc-7297648c278903589beebf6fbc7511e5c1ff421d.tar.bz2
libdbpp-odbc-7297648c278903589beebf6fbc7511e5c1ff421d.tar.xz
libdbpp-odbc-7297648c278903589beebf6fbc7511e5c1ff421d.zip
Rewrite the whole of parameter and column binding almost from scratch
No more template rubbish, no more messy partial specialisation Add copyless rebind of column to parameter Changes in project2 to suit
Diffstat (limited to 'libodbcpp/param.cpp')
-rw-r--r--libodbcpp/param.cpp191
1 files changed, 60 insertions, 131 deletions
diff --git a/libodbcpp/param.cpp b/libodbcpp/param.cpp
index ff10d3a..1992252 100644
--- a/libodbcpp/param.cpp
+++ b/libodbcpp/param.cpp
@@ -1,173 +1,102 @@
#include <sqlext.h>
#include "param.h"
#include "command.h"
-#include "column.h"
#include "error.h"
#include <string.h>
ODBC::Param::Param() :
- bound(false)
+ paramCmd(NULL),
+ paramIdx(NULL),
+ paramBound(false)
+{
+}
+
+ODBC::Param::Param(Command * c, unsigned int i) :
+ paramCmd(c),
+ paramIdx(i),
+ paramBound(false)
{
}
ODBC::Param::~Param(){
}
-template <class t>
-ODBC::_Param<t>*
-ODBC::Param::makeParam(ODBC::Param*& p)
+template <class ParamType>
+ParamType *
+ODBC::Command::makeParam(unsigned int idx)
{
+ if (idx >= params.size()) {
+ throw Error("%s: Bind out of bounds", __FUNCTION__);
+ }
+ Param * & p = params[idx];
if (p) {
- _Param<t>* np = dynamic_cast<_Param<t>*>(p);
+ ParamType * np = dynamic_cast<ParamType *>(p);
if (np) {
return np;
}
delete p;
}
- _Param<t>* np = new _Param<t>();
+ ParamType * np = new ParamType(this, idx);
p = np;
return np;
}
void
-ODBC::Param::bind(SQLHANDLE hStmt, SQLUINTEGER col, SQLSMALLINT ctype, SQLSMALLINT stype,
- SQLINTEGER colsize, SQLINTEGER dp, const void * value, size_t buflen)
-{
- RETCODE rc = SQLBindParameter(hStmt, col, SQL_PARAM_INPUT, ctype, stype,
- colsize, dp, const_cast<void*>(value), buflen, &bindLen);
- if (rc != SQL_SUCCESS) {
- throw Error(rc, SQL_HANDLE_STMT, hStmt, "%s: Bind for column %lu",
- __FUNCTION__, col);
- }
-}
-
-void
-ODBC::Command::bindParamI(unsigned int i, int val)
-{
- if (i < params.size()) {
- _Param<SQLINTEGER>* p = Param::makeParam<SQLINTEGER>(params[i]);
- p->value = val;
- if (!p->bound) {
- p->bind(this->hStmt, i + 1, SQL_C_SLONG, SQL_C_LONG, 0, 0,
- &p->value, sizeof(SQLINTEGER));
- p->bound = true;
- }
- return;
- }
- throw Error("%s: Bind out of bounds", __FUNCTION__);
-}
-void
-ODBC::Command::bindParamI(unsigned int i, long val)
-{
- if (i < params.size()) {
- _Param<SQLINTEGER>* p = Param::makeParam<SQLINTEGER>(params[i]);
- p->value = val;
- if (!p->bound) {
- p->bind(this->hStmt, i + 1, SQL_C_SLONG, SQL_C_LONG, 0, 0,
- &p->value, sizeof(SQLINTEGER));
- p->bound = true;
- }
- return;
- }
- throw Error("%s: Bind out of bounds", __FUNCTION__);
-}
-void
-ODBC::Command::bindParamI(unsigned int i, long long unsigned int val)
-{
- if (i < params.size()) {
- _Param<SQLUINTEGER>* p = Param::makeParam<SQLUINTEGER>(params[i]);
- p->value = val;
- if (!p->bound) {
- p->bind(this->hStmt, i + 1, SQL_C_ULONG, SQL_C_ULONG, 0, 0,
- &p->value, sizeof(SQLUINTEGER));
- p->bound = true;
- }
- return;
- }
- throw Error("%s: Bind out of bounds", __FUNCTION__);
-}
-void
-ODBC::Command::bindParamF(unsigned int i, double val)
-{
- if (i < params.size()) {
- _Param<SQLDOUBLE>* p = Param::makeParam<SQLDOUBLE>(params[i]);
- p->value = val;
- if (!p->bound) {
- p->bind(this->hStmt, i + 1, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0,
- &p->value, sizeof(SQLDOUBLE));
- p->bound = true;
- }
- return;
- }
- throw Error("%s: Bind out of bounds", __FUNCTION__);
-}
-void
-ODBC::Command::bindParamS(unsigned int i, const Glib::ustring & val)
+ODBC::Param::bind() const
{
- if (i < params.size()) {
- _Param<Glib::ustring>* p = Param::makeParam<Glib::ustring>(params[i]);
- p->value = val;
- p->bindLen = p->value.bytes();
- p->bind(this->hStmt, i + 1, SQL_C_CHAR, SQL_CHAR, 0, 0, p->value.data(), p->value.bytes());
- return;
- }
- throw Error("%s: Bind out of bounds", __FUNCTION__);
-}
-void
-ODBC::Command::bindParamT(unsigned int i, const struct tm * val)
-{
- if (i < params.size()) {
- _Param<SQL_TIMESTAMP_STRUCT>* p = Param::makeParam<SQL_TIMESTAMP_STRUCT>(params[i]);
- p->value << *val;
- if (!p->bound) {
- p->bind(this->hStmt, i + 1, SQL_C_TIMESTAMP, SQL_TYPE_TIMESTAMP,
- sizeof(SQL_TIMESTAMP_STRUCT), 0, &p->value, sizeof(SQL_TIMESTAMP_STRUCT));
- p->bound = true;
+ if (!paramBound) {
+ RETCODE rc = SQLBindParameter(paramCmd->hStmt, paramIdx + 1, SQL_PARAM_INPUT, ctype(), stype(),
+ size(), dp(), const_cast<void *>(dataAddress()), size(), &bindLen);
+ if (rc != SQL_SUCCESS) {
+ throw Error(rc, SQL_HANDLE_STMT, paramCmd->hStmt, "%s: Bind for parameter %u",
+ __FUNCTION__, paramIdx);
}
- return;
+ paramBound = true;
}
- throw Error("%s: Bind out of bounds", __FUNCTION__);
}
-void
-ODBC::Command::bindParamT(unsigned int i, const SQL_TIMESTAMP_STRUCT & val)
-{
- if (i < params.size()) {
- _Param<SQL_TIMESTAMP_STRUCT>* p = Param::makeParam<SQL_TIMESTAMP_STRUCT>(params[i]);
- p->value = val;
- if (!p->bound) {
- p->bind(this->hStmt, i + 1, SQL_C_TIMESTAMP, SQL_TIMESTAMP,
- sizeof(SQL_TIMESTAMP_STRUCT), 0, &p->value, sizeof(SQL_TIMESTAMP_STRUCT));
- p->bound = true;
- }
- return;
- }
- throw Error("%s: Bind out of bounds", __FUNCTION__);
+
+#define SIMPLEBINDER(ctype, otype, suf) \
+void \
+ODBC::Command::bindParam##suf(unsigned int i, ctype val) \
+{ \
+ ODBC::otype * p = makeParam<ODBC::otype>(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(double, FloatingPointParam, F);
+SIMPLEBINDER(float, FloatingPointParam, F);
+SIMPLEBINDER(const Glib::ustring &, GlibUstringParam, S);
-// Wrappers for all the roughly compatable types
+SIMPLEBINDER(const struct tm *, TimeStampParam, T);
+SIMPLEBINDER(const SQL_TIMESTAMP_STRUCT &, TimeStampParam, T);
+SIMPLEBINDER(time_t, TimeStampParam, T);
void
-ODBC::Command::bindParamI(unsigned int i, long unsigned int val)
-{
- bindParamI(i, (long long unsigned int)val);
-}
-void
-ODBC::Command::bindParamI(unsigned int i, unsigned int val)
+ODBC::GlibUstringParam::operator=(Glib::ustring const & d)
{
- bindParamI(i, (long long unsigned int)val);
-}
-void
-ODBC::Command::bindParamF(unsigned int i, float val)
-{
- bindParamF(i, (double)val);
+ const char * addr = data.data();
+ data = d;
+ bindLen = d.bytes();
+ paramBound &= (addr == data.data());
+ if (!paramBound) {
+ paramBound = false;
+ bind();
+ }
}
+
void
-ODBC::Command::bindParamT(unsigned int i, time_t val)
+ODBC::TimeStampParam::operator=(long const & d)
{
struct tm t;
- gmtime_r(&val, &t);
- bindParamT(i, &t);
+ gmtime_r(&d, &t);
+ data << t;
}