From c3f2a299a734494a61a49709a8e4cc335570b3d3 Mon Sep 17 00:00:00 2001 From: randomdan Date: Fri, 18 Feb 2011 12:58:59 +0000 Subject: Handle the case when the driver tries to save more data than the buffer is big enough, and doesn't bother to mention it Use the driver's bindSize as a hint as to how much buffer to allocate up front --- libodbcpp/column.cpp | 16 +++++++--------- libodbcpp/column.h | 10 +++++----- libodbcpp/selectcommand.cpp | 16 +++++++++++----- 3 files changed, 23 insertions(+), 19 deletions(-) (limited to 'libodbcpp') diff --git a/libodbcpp/column.cpp b/libodbcpp/column.cpp index b041bd4..a34946a 100644 --- a/libodbcpp/column.cpp +++ b/libodbcpp/column.cpp @@ -17,13 +17,14 @@ ODBC::Column::~Column() { } -void -ODBC::Column::resize(SQLHANDLE) +bool +ODBC::Column::resize() { + return false; } -void -ODBC::CharArrayColumn::resize(SQLHANDLE) +bool +ODBC::CharArrayColumn::resize() { if (bindLen >= SQLLEN(data.size())) { data.resize(bindLen + 1); @@ -32,12 +33,9 @@ ODBC::CharArrayColumn::resize(SQLHANDLE) paramBound = false; Param::bind(); } + return true; } -} - -void -ODBC::Column::onScroll() -{ + return false; } bool diff --git a/libodbcpp/column.h b/libodbcpp/column.h index 71118f8..e981a14 100644 --- a/libodbcpp/column.h +++ b/libodbcpp/column.h @@ -4,6 +4,7 @@ #include "../libdbpp/column.h" #include #include +#include #include "bind.h" #include "param.h" @@ -16,8 +17,7 @@ namespace ODBC { void bind(); virtual void * rwDataAddress() = 0; void rebind(DB::Command *, unsigned int idx) const; - virtual void resize(SQLHANDLE); - virtual void onScroll(); + virtual bool resize(); virtual operator int () const { throw std::bad_cast(); } virtual operator long () const { throw std::bad_cast(); } @@ -45,11 +45,11 @@ namespace ODBC { class CharArrayColumn : public Column, public Param { public: typedef std::vector CharArray; - CharArrayColumn(SelectCommand * sc, const Glib::ustring & n, unsigned int i) : + CharArrayColumn(SelectCommand * sc, const Glib::ustring & n, unsigned int i, SQLULEN sizeHint) : DB::Column(n, i), Column(sc, n, i) { - data.resize(256); + data.resize(std::max(sizeHint, 64) + 1); } virtual SQLSMALLINT ctype() const { return SQL_C_CHAR; } virtual SQLSMALLINT stype() const { return SQL_CHAR; } @@ -58,7 +58,7 @@ namespace ODBC { virtual const void * dataAddress() const { return &data.front(); } virtual void * rwDataAddress() { return &data.front(); } void operator=(const Glib::ustring & d); - void resize(SQLHANDLE); + bool resize(); virtual operator std::string () const { return std::string(&data.front(), bindLen); } virtual operator Glib::ustring () const { return std::string(&data.front(), bindLen); } virtual void apply(DB::HandleField &) const; diff --git a/libodbcpp/selectcommand.cpp b/libodbcpp/selectcommand.cpp index 32978a4..f44472f 100644 --- a/libodbcpp/selectcommand.cpp +++ b/libodbcpp/selectcommand.cpp @@ -49,7 +49,7 @@ ODBC::SelectCommand::fetch(SQLSMALLINT orientation, SQLLEN offset) if (SQL_SUCCEEDED(diagrc)) { if (!strncmp((const char*)sqlstatus, "01004", 5)) { for (Columns::iterator i = columns.begin(); i != columns.end(); i++) { - (*i)->resize(hStmt); + (*i)->resize(); } return fetch(SQL_FETCH_RELATIVE, 0); } @@ -59,10 +59,16 @@ ODBC::SelectCommand::fetch(SQLSMALLINT orientation, SQLLEN offset) } } case SQL_SUCCESS: - for (Columns::iterator i = columns.begin(); i != columns.end(); i++) { - (*i)->onScroll(); + { + bool resized = false; + for (Columns::iterator i = columns.begin(); i != columns.end(); i++) { + resized |= (*i)->resize(); + } + if (resized) { + return fetch(SQL_FETCH_RELATIVE, 0); + } + return true; } - return true; case SQL_NO_DATA: return false; } @@ -115,7 +121,7 @@ ODBC::SelectCommand::execute() columns[col] = new TimeStampColumn(this, colName, col); break; default: - columns[col] = new CharArrayColumn(this, colName, col); + columns[col] = new CharArrayColumn(this, colName, col, bindSize); break; }; columns[col]->bind(); -- cgit v1.2.3