From 1df33cc9d9a7804c78788d5717435ede44855ca0 Mon Sep 17 00:00:00 2001 From: randomdan Date: Fri, 11 Jun 2010 09:03:42 +0000 Subject: Use Glib::ustring in libodbcpp for data and std::string for non-data Add support for parameters in SqlViews Uses parameters to implement category browse and search --- libodbcpp/Jamfile.jam | 6 ++++- libodbcpp/bind.cpp | 19 -------------- libodbcpp/bind.h | 7 ++--- libodbcpp/column.cpp | 19 +++++++++++--- libodbcpp/column.h | 13 +++++----- libodbcpp/command.cpp | 4 +-- libodbcpp/command.h | 10 +++---- libodbcpp/connection.cpp | 7 ++--- libodbcpp/connection.h | 2 +- libodbcpp/dsn.cpp | 2 +- libodbcpp/dsn.h | 10 +++---- libodbcpp/modifycommand.cpp | 2 +- libodbcpp/modifycommand.h | 2 +- libodbcpp/param.cpp | 63 +++++++++++++++++++-------------------------- libodbcpp/param.h | 2 -- libodbcpp/selectcommand.cpp | 19 ++++++-------- libodbcpp/selectcommand.h | 6 ++--- libodbcpp/ustring.cpp | 42 ------------------------------ libodbcpp/ustring.h | 21 --------------- 19 files changed, 86 insertions(+), 170 deletions(-) delete mode 100644 libodbcpp/ustring.cpp delete mode 100644 libodbcpp/ustring.h diff --git a/libodbcpp/Jamfile.jam b/libodbcpp/Jamfile.jam index 8def61d..de4fa00 100644 --- a/libodbcpp/Jamfile.jam +++ b/libodbcpp/Jamfile.jam @@ -1,2 +1,6 @@ -lib odbcpp : [ glob *.cpp ] : +alias glibmm : : : : + "`pkg-config --cflags glibmm-2.4`" + "`pkg-config --libs glibmm-2.4`" + ; +lib odbcpp : glibmm [ glob *.cpp ] : static ; diff --git a/libodbcpp/bind.cpp b/libodbcpp/bind.cpp index 0808bbb..2e40975 100644 --- a/libodbcpp/bind.cpp +++ b/libodbcpp/bind.cpp @@ -3,7 +3,6 @@ #include "param.h" ODBC::BindBase::BindBase() : - bindSize(0), bindLen(0) { } @@ -15,22 +14,4 @@ ODBC::Bind::~Bind() } } -SQLINTEGER -ODBC::BindBase::length() const -{ - return bindLen; -} - -SQLUINTEGER -ODBC::BindBase::size() const -{ - return bindSize; -} - -bool -ODBC::BindBase::isNull() const -{ - return (bindLen == SQL_NULL_DATA); -} - diff --git a/libodbcpp/bind.h b/libodbcpp/bind.h index 4465466..7dfbf34 100644 --- a/libodbcpp/bind.h +++ b/libodbcpp/bind.h @@ -9,14 +9,11 @@ namespace ODBC { public: BindBase(); virtual ~BindBase() {} - SQLINTEGER length() const; - SQLUINTEGER size() const; - bool isNull() const; - private: - SQLUINTEGER bindSize; // Allocated memory + protected: SQLINTEGER bindLen; // Used memory friend class Param; friend class Column; + friend class Command; }; template class Bind { diff --git a/libodbcpp/column.cpp b/libodbcpp/column.cpp index d4b6446..386cbfd 100644 --- a/libodbcpp/column.cpp +++ b/libodbcpp/column.cpp @@ -4,10 +4,10 @@ #include "command.h" #include "error.h" -ODBC::Column::Column(String n, unsigned int i) : +ODBC::Column::Column(const Glib::ustring & n, unsigned int i) : colNo(i), name(n), - fresh(false) + bindSize(0) { } @@ -15,6 +15,12 @@ ODBC::Column::~Column() { } +bool +ODBC::Column::isNull() const +{ + return (bindLen == SQL_NULL_DATA); +} + #define ODBC_DEFAULT_COLUMN_CAST(ctype, rtype) \ ODBC::Column::operator rtype() const { \ return (dynamic_cast& >(*this)).value; \ @@ -27,7 +33,9 @@ ODBC_DEFAULT_COLUMN_CAST(SQLINTEGER, int); ODBC_DEFAULT_COLUMN_CAST(SQLDOUBLE, double); ODBC_DEFAULT_COLUMN_CAST(SQLDOUBLE, float); ODBC_DEFAULT_COLUMN_CAST(SQLCHAR*, const unsigned char *); -ODBC_DEFAULT_COLUMN_CAST(SQLCHAR*, String); +ODBC::Column::operator Glib::ustring() const { + return Glib::ustring((const char *)((dynamic_cast& >(*this)).value)); +} ODBC::Column::operator std::string() const { return (const char*)((dynamic_cast& >(*this)).value); } @@ -65,7 +73,10 @@ namespace ODBC { REBIND(double, bindParamF) REBIND(float, bindParamF) REBIND(SQL_TIMESTAMP_STRUCT, bindParamT) - REBIND(unsigned char *, bindParamS) + template<> void _Column::rebind(Command * cmd, unsigned int col) const \ + { + cmd->bindParamS(col, (char *)value); + } template <> int diff --git a/libodbcpp/column.h b/libodbcpp/column.h index 992a958..9f3b93d 100644 --- a/libodbcpp/column.h +++ b/libodbcpp/column.h @@ -1,13 +1,13 @@ #ifndef ODBC_COLUMN_H #define ODBC_COLUMN_H -#include "ustring.h" +#include #include "bind.h" namespace ODBC { class Column : public BindBase { public: - Column(String, unsigned int); + Column(const Glib::ustring &, unsigned int); virtual ~Column(); void bind(SQLHANDLE, SQLUINTEGER, SQLSMALLINT, void*, size_t); operator int () const; @@ -19,22 +19,23 @@ namespace ODBC { operator const unsigned char * () const; operator const char * () const; operator std::string () const; - operator String () const; + operator Glib::ustring () const; operator struct tm () const; virtual void rebind(Command *, unsigned int col) const = 0; virtual int writeToBuf(char ** buf) const = 0; virtual int writeToBuf(char ** buf, const char * fmt) const = 0; + bool isNull() const; const unsigned int colNo; - const String name; + const Glib::ustring name; private: - mutable bool fresh; + SQLUINTEGER bindSize; // Allocated memory friend class SelectCommand; }; template class _Column : public Bind, public Column { public: - _Column(String, unsigned int); + _Column(const Glib::ustring &, unsigned int); ~_Column() {} void rebind(Command *, unsigned int col) const; int writeToBuf(char ** buf) const; diff --git a/libodbcpp/command.cpp b/libodbcpp/command.cpp index 217954e..4ceb825 100644 --- a/libodbcpp/command.cpp +++ b/libodbcpp/command.cpp @@ -3,7 +3,7 @@ #include "param.h" #include -ODBC::Command::Command(const Connection& c, String s) : +ODBC::Command::Command(const Connection & c, const std::string & s) : sql(s), connection(c) { @@ -11,7 +11,7 @@ ODBC::Command::Command(const Connection& c, String s) : if (rc != SQL_SUCCESS) { throw Error(rc, SQL_HANDLE_STMT, hStmt, "Allocate statement handle"); } - rc = SQLPrepare(hStmt, sql, sql.size()); + rc = SQLPrepare(hStmt, (SQLCHAR*)sql.c_str(), sql.length()); if (rc != SQL_SUCCESS) { SQLFreeHandle(SQL_HANDLE_STMT, hStmt); throw Error(rc, SQL_HANDLE_STMT, hStmt, "Prepare statement"); diff --git a/libodbcpp/command.h b/libodbcpp/command.h index 8ea24d4..1348441 100644 --- a/libodbcpp/command.h +++ b/libodbcpp/command.h @@ -3,13 +3,14 @@ #include #include "connection.h" +#include namespace ODBC { class Param; class Command { typedef std::vector Params; public: - Command(const Connection&, String sql); + Command(const Connection &, const std::string & sql); virtual ~Command() = 0; void bindParamI(unsigned int i, int val); @@ -20,15 +21,14 @@ namespace ODBC { void bindParamF(unsigned int i, double val); void bindParamF(unsigned int i, float val); void bindParamS(unsigned int i, const char *); - void bindParamS(unsigned int i, const unsigned char *); - void bindParamS(unsigned int i, const unsigned char *, size_t); + void bindParamS(unsigned int i, const char *, size_t); void bindParamS(unsigned int i, const std::string &); - void bindParamS(unsigned int i, const String &); + void bindParamS(unsigned int i, const Glib::ustring &); void bindParamT(unsigned int i, const struct tm *); void bindParamT(unsigned int i, const SQL_TIMESTAMP_STRUCT &); void bindParamT(unsigned int i, time_t); - const String sql; + const std::string sql; protected: friend class BindBase; SQLHSTMT hStmt; diff --git a/libodbcpp/connection.cpp b/libodbcpp/connection.cpp index e3e92c7..6adcf09 100644 --- a/libodbcpp/connection.cpp +++ b/libodbcpp/connection.cpp @@ -29,7 +29,8 @@ ODBC::Connection::Connection(const DSN& d) : throw Error(dberr, SQL_HANDLE_ENV, env, "Set connection attributes"); } - dberr = SQLConnect(conn, d.dsn, SQL_NTS, d.username, SQL_NTS, d.password, SQL_NTS); + dberr = SQLConnect(conn, (SQLCHAR*)d.dsn.c_str(), SQL_NTS, + (SQLCHAR*)d.username.c_str(), SQL_NTS, (SQLCHAR*)d.password.c_str(), SQL_NTS); if ((dberr != SQL_SUCCESS)) { throw Error(dberr, SQL_HANDLE_DBC, conn, "Connect"); } @@ -40,7 +41,7 @@ ODBC::Connection::Connection(const DSN& d) : } } -ODBC::Connection::Connection(const String & s) : +ODBC::Connection::Connection(const std::string & s) : env(0), conn(0), txDepth(0), @@ -66,7 +67,7 @@ ODBC::Connection::Connection(const String & s) : throw Error(dberr, SQL_HANDLE_ENV, env, "Set connection attributes"); } - dberr = SQLDriverConnect(conn, NULL, s, s.length(), NULL, 0, NULL, SQL_DRIVER_NOPROMPT); + dberr = SQLDriverConnect(conn, NULL, (SQLCHAR*)s.c_str(), s.length(), NULL, 0, NULL, SQL_DRIVER_NOPROMPT); if ((dberr != SQL_SUCCESS)) { throw Error(dberr, SQL_HANDLE_DBC, conn, "Connect"); } diff --git a/libodbcpp/connection.h b/libodbcpp/connection.h index 5fdce9e..b89a5f9 100644 --- a/libodbcpp/connection.h +++ b/libodbcpp/connection.h @@ -8,7 +8,7 @@ namespace ODBC { class Connection { public: Connection(const DSN& d); - Connection(const String& str); + Connection(const std::string & str); ~Connection(); SQLHENV env; SQLHDBC conn; diff --git a/libodbcpp/dsn.cpp b/libodbcpp/dsn.cpp index ee4f5fe..337319b 100644 --- a/libodbcpp/dsn.cpp +++ b/libodbcpp/dsn.cpp @@ -1,6 +1,6 @@ #include "dsn.h" -ODBC::DSN::DSN(String d, String u, String p) : +ODBC::DSN::DSN(const std::string & d, const std::string & u, const std::string & p) : dsn(d), username(u), password(p) diff --git a/libodbcpp/dsn.h b/libodbcpp/dsn.h index 0aee953..6be7e3b 100644 --- a/libodbcpp/dsn.h +++ b/libodbcpp/dsn.h @@ -1,16 +1,16 @@ #ifndef DSN_H #define DSN_H -#include "ustring.h" +#include namespace ODBC { class DSN { public: - DSN(String, String, String); + DSN(const std::string &, const std::string &, const std::string &); virtual ~DSN(); - String dsn; // DSN name for odbc.ini - String username; // User name - String password; // Password + const std::string dsn; // DSN name for odbc.ini + const std::string username; // User name + const std::string password; // Password }; } diff --git a/libodbcpp/modifycommand.cpp b/libodbcpp/modifycommand.cpp index 5e614b7..77adfb9 100644 --- a/libodbcpp/modifycommand.cpp +++ b/libodbcpp/modifycommand.cpp @@ -1,7 +1,7 @@ #include "modifycommand.h" #include "error.h" -ODBC::ModifyCommand::ModifyCommand(const ODBC::Connection &c, String sql) : +ODBC::ModifyCommand::ModifyCommand(const ODBC::Connection & c, const std::string & sql) : Command(c, sql) { } diff --git a/libodbcpp/modifycommand.h b/libodbcpp/modifycommand.h index ef480c9..e833518 100644 --- a/libodbcpp/modifycommand.h +++ b/libodbcpp/modifycommand.h @@ -6,7 +6,7 @@ namespace ODBC { class ModifyCommand : public Command { public: - ModifyCommand(const Connection&, String sql); + ModifyCommand(const Connection &, const std::string & sql); ~ModifyCommand(); // Execute the command and return effected row count unsigned int execute(bool allowNoChange = true); diff --git a/libodbcpp/param.cpp b/libodbcpp/param.cpp index 7d5a070..a86bce0 100644 --- a/libodbcpp/param.cpp +++ b/libodbcpp/param.cpp @@ -34,27 +34,13 @@ ODBC::Param::bind(SQLHANDLE hStmt, SQLUINTEGER col, SQLSMALLINT ctype, SQLSMALLI SQLINTEGER colsize, SQLINTEGER dp, const void* value, size_t buflen) { RETCODE rc = SQLBindParameter(hStmt, col, SQL_PARAM_INPUT, ctype, stype, - colsize, dp, (void*)value, buflen, (SQLINTEGER*)&bindLen); + colsize, dp, (void*)value, buflen, &bindLen); if (rc != SQL_SUCCESS) { throw Error(rc, SQL_HANDLE_STMT, hStmt, "%s: Bind for column %lu", __FUNCTION__, col); } } -template -void -ODBC::Param::makeBindLen(T*& p, size_t newLen) -{ - if (bindSize < newLen) { - if (bindSize) { - delete[] p; - } - bindSize = newLen; - p = new T[newLen + 1]; - } - bindLen = newLen; -} - void ODBC::Command::bindParamI(unsigned int i, int val) { @@ -64,6 +50,7 @@ ODBC::Command::bindParamI(unsigned int i, int 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; } @@ -78,6 +65,7 @@ ODBC::Command::bindParamI(unsigned int i, long 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; } @@ -92,6 +80,7 @@ ODBC::Command::bindParamI(unsigned int i, long long unsigned int 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; } @@ -106,22 +95,32 @@ ODBC::Command::bindParamF(unsigned int i, double 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 unsigned char * val, size_t length) +ODBC::Command::bindParamS(unsigned int i, const Glib::ustring & val) { if (i < params.size()) { - _Param* p = Param::makeParam(params[i]); - p->makeBindLen(p->value, length); - memcpy(p->value, val, length); - p->value[length] = '\0'; - if (!p->bound) { - p->bind(this->hStmt, i + 1, SQL_C_CHAR, SQL_CHAR, 0, 0, p->value, length); - } + _Param* p = Param::makeParam(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::bindParamS(unsigned int i, const char * val, size_t len) +{ + if (i < params.size()) { + _Param* p = Param::makeParam(params[i]); + p->value.assign(val, len); + p->bindLen = len; + 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__); @@ -135,6 +134,7 @@ ODBC::Command::bindParamT(unsigned int i, const struct tm * 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; } return; } @@ -149,6 +149,7 @@ ODBC::Command::bindParamT(unsigned int i, const SQL_TIMESTAMP_STRUCT & 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; } @@ -170,26 +171,14 @@ ODBC::Command::bindParamI(unsigned int i, unsigned int val) bindParamI(i, (long long unsigned int)val); } void -ODBC::Command::bindParamS(unsigned int i, const String & val) -{ - bindParamS(i, val.c_str(), val.size()); -} -void -ODBC::Command::bindParamS(unsigned int i, const unsigned char * val) -{ - const unsigned char * x = val; - while (*val++) ; - bindParamS(i, x, val - x); -} -void ODBC::Command::bindParamS(unsigned int i, const char * val) { - bindParamS(i, (unsigned char *)val, strlen(val)); + bindParamS(i, val, strlen(val)); } void ODBC::Command::bindParamS(unsigned int i, const std::string & val) { - bindParamS(i, (unsigned char *)val.c_str(), val.size()); + bindParamS(i, val.c_str(), val.length()); } void ODBC::Command::bindParamF(unsigned int i, float val) diff --git a/libodbcpp/param.h b/libodbcpp/param.h index a3cb347..f0d70ab 100644 --- a/libodbcpp/param.h +++ b/libodbcpp/param.h @@ -13,8 +13,6 @@ namespace ODBC { bool bound; // Has SqlBind... been called? void bind(SQLHANDLE, SQLUINTEGER, SQLSMALLINT, SQLSMALLINT, SQLINTEGER, SQLINTEGER, const void*, size_t); - template - void makeBindLen(T*&, size_t newSize); template static ODBC::_Param* makeParam(ODBC::Param*& p); diff --git a/libodbcpp/selectcommand.cpp b/libodbcpp/selectcommand.cpp index 025141a..26b6b45 100644 --- a/libodbcpp/selectcommand.cpp +++ b/libodbcpp/selectcommand.cpp @@ -4,7 +4,7 @@ #include #include -ODBC::SelectCommand::SelectCommand(const Connection& c, String s) : +ODBC::SelectCommand::SelectCommand(const Connection & c, const std::string & s) : Command(c, s) { } @@ -32,9 +32,6 @@ ODBC::SelectCommand::fetch() RETCODE rc = SQLFetch(hStmt); switch (rc) { case SQL_SUCCESS: - for (Columns::iterator col = columns.begin(); col != columns.end(); col++) { - (*col)->fresh = true; - } return true; case SQL_NO_DATA: return false; @@ -46,7 +43,7 @@ ODBC::SelectCommand::fetch() // This is here cos it needs to be referenced by (and only by) execute template -ODBC::_Column::_Column(String n, unsigned int i) : Column(n, i) +ODBC::_Column::_Column(const Glib::ustring & n, unsigned int i) : Column(n, i) { } @@ -68,16 +65,16 @@ ODBC::SelectCommand::execute() } columns.resize(colCount); for (int col = 0; col < colCount; col++) { - SQLCHAR colName[300]; + SQLCHAR _colName[300]; SQLSMALLINT nameLen, dp, nullable, bindType; SQLUINTEGER bindSize; int sqlcol = col + 1; - if ((rc = SQLDescribeCol(hStmt, sqlcol, colName, sizeof(colName), &nameLen, &bindType, + if ((rc = SQLDescribeCol(hStmt, sqlcol, _colName, sizeof(_colName), &nameLen, &bindType, &bindSize, &dp, &nullable)) != SQL_SUCCESS) { throw Error(rc, SQL_HANDLE_STMT, hStmt, "%s: SQLDescribeCol for %d", __FUNCTION__, col); } - colName[nameLen] = '\0'; + Glib::ustring colName((const char *)_colName, nameLen); switch (bindType) { case -9: case SQL_CHAR: @@ -125,7 +122,7 @@ ODBC::SelectCommand::execute() default: throw Error( "%s: Bad column type: idx=%d, name=%s, type=%d, size=%ld, dp=%d, null=%d", - __FUNCTION__, col, colName, bindType, bindSize, dp, nullable); + __FUNCTION__, col, _colName, bindType, bindSize, dp, nullable); break; }; } @@ -142,7 +139,7 @@ ODBC::SelectCommand::operator[](unsigned int col) const } const ODBC::Column& -ODBC::SelectCommand::operator[](const String & colName) const +ODBC::SelectCommand::operator[](const Glib::ustring & colName) const { for (Columns::const_iterator col = columns.begin(); col != columns.end(); col++) { if ((*col)->name == colName) { @@ -153,7 +150,7 @@ ODBC::SelectCommand::operator[](const String & colName) const } unsigned int -ODBC::SelectCommand::getOrdinal(const String & colName) const +ODBC::SelectCommand::getOrdinal(const Glib::ustring & colName) const { unsigned int n = 0; for (Columns::const_iterator col = columns.begin(); col != columns.end(); col++) { diff --git a/libodbcpp/selectcommand.h b/libodbcpp/selectcommand.h index 5a00739..541cd08 100644 --- a/libodbcpp/selectcommand.h +++ b/libodbcpp/selectcommand.h @@ -8,13 +8,13 @@ namespace ODBC { class SelectCommand : public Command { typedef std::vector Columns; public: - SelectCommand (const Connection&, String sql); + SelectCommand (const Connection &, const std::string & sql); ~SelectCommand(); bool fetch(); const Column & operator[](unsigned int col) const; - const Column & operator[](const String &) const; + const Column & operator[](const Glib::ustring &) const; unsigned int columnCount() const; - unsigned int getOrdinal(const String &) const; + unsigned int getOrdinal(const Glib::ustring &) const; private: void execute(); Columns columns; diff --git a/libodbcpp/ustring.cpp b/libodbcpp/ustring.cpp deleted file mode 100644 index dd8ee3b..0000000 --- a/libodbcpp/ustring.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include -#include "ustring.h" - -ODBC::String::String() -{ -} -ODBC::String::String(std::basic_string s) : - std::basic_string(s) -{ -} -ODBC::String::String(std::basic_string s) : - std::basic_string((unsigned char *)s.c_str()) -{ -} -ODBC::String::String(const char * s) : - std::basic_string((unsigned char *)s) -{ -} -ODBC::String::String(const unsigned char * s) : - std::basic_string(s) -{ -} - -ODBC::String::operator unsigned char * () const -{ - return (unsigned char*)c_str(); -} - -ODBC::String -ODBC::String::Format(const char * fmt, ...) -{ - char * buf; - va_list va; - va_start(va, fmt); - if (vasprintf(&buf, fmt, va)) { - buf = NULL; - } - va_end(va); - return buf; -} - diff --git a/libodbcpp/ustring.h b/libodbcpp/ustring.h deleted file mode 100644 index d3c4d41..0000000 --- a/libodbcpp/ustring.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef ODBC_STRING_H -#define ODBC_STRING_H - -#include - -namespace ODBC { - class String : public std::basic_string { - public: - String(const unsigned char *); - String(const char *); - String(std::basic_string); - String(std::basic_string); - String(); - operator unsigned char *() const; - - static String Format(const char *, ...); - }; -} - -#endif - -- cgit v1.2.3