summaryrefslogtreecommitdiff
path: root/libodbcpp
diff options
context:
space:
mode:
Diffstat (limited to 'libodbcpp')
-rw-r--r--libodbcpp/odbc-modifycommand.cpp2
-rw-r--r--libodbcpp/odbc-selectcommand.cpp25
-rw-r--r--libodbcpp/odbc-selectcommand.h3
-rw-r--r--libodbcpp/unittests/testodbc.cpp15
4 files changed, 34 insertions, 11 deletions
diff --git a/libodbcpp/odbc-modifycommand.cpp b/libodbcpp/odbc-modifycommand.cpp
index 0eeca01..60bb7c4 100644
--- a/libodbcpp/odbc-modifycommand.cpp
+++ b/libodbcpp/odbc-modifycommand.cpp
@@ -15,7 +15,7 @@ ODBC::ModifyCommand::~ModifyCommand()
unsigned int
ODBC::ModifyCommand::execute(bool anc)
{
- RETCODE rc = SQLExecute(hStmt);
+ RETCODE rc = SQLExecute(hStmt);
if (!SQL_SUCCEEDED(rc)) {
if (rc != SQL_NO_DATA || !anc) {
throw Error(rc, SQL_HANDLE_STMT, hStmt);
diff --git a/libodbcpp/odbc-selectcommand.cpp b/libodbcpp/odbc-selectcommand.cpp
index 6b28a32..5e26053 100644
--- a/libodbcpp/odbc-selectcommand.cpp
+++ b/libodbcpp/odbc-selectcommand.cpp
@@ -16,7 +16,7 @@ ODBC::SelectCommand::SelectCommand(const Connection & c, const std::string & s)
ODBC::SelectCommand::~SelectCommand()
{
- if (!columns->empty()) {
+ if (columnCount()) {
SQLCloseCursor(hStmt);
}
}
@@ -30,7 +30,7 @@ ODBC::SelectCommand::fetch()
bool
ODBC::SelectCommand::fetch(SQLSMALLINT orientation, SQLLEN offset)
{
- if (columns->empty()) {
+ if (!columnCount()) {
execute();
}
RETCODE rc = SQLFetchScroll(hStmt, orientation, offset);
@@ -42,22 +42,20 @@ ODBC::SelectCommand::fetch(SQLSMALLINT orientation, SQLLEN offset)
RETCODE diagrc = SQLGetDiagRec(SQL_HANDLE_STMT, hStmt, 1, sqlstatus, NULL, NULL, 0, NULL);
if (SQL_SUCCEEDED(diagrc)) {
if (!strncmp((const char*)sqlstatus, "01004", 5)) {
- for (Columns::iterator i = columns->begin(); i != columns->end(); ++i) {
- std::dynamic_pointer_cast<Column>(*i)->resize();
+ for (const auto & c : largeColumns) {
+ c->resize();
}
return fetch(SQL_FETCH_RELATIVE, 0);
}
- }
- if (rc != SQL_SUCCESS_WITH_INFO) {
- throw Error(rc, SQL_HANDLE_STMT, hStmt);
+ fprintf(stderr, "truncation\n");
}
}
// fall-through
case SQL_SUCCESS:
{
bool resized = false;
- for (Columns::iterator i = columns->begin(); i != columns->end(); ++i) {
- resized |= std::dynamic_pointer_cast<Column>(*i)->resize();
+ for (const auto & c : largeColumns) {
+ resized |= c->resize();
}
if (resized) {
return fetch(SQL_FETCH_RELATIVE, 0);
@@ -130,7 +128,14 @@ ODBC::SelectCommand::execute()
case SQL_UNKNOWN_TYPE:
throw DB::ColumnTypeNotSupported();
default:
- ncol = insertColumn(std::make_shared<CharArrayColumn>(this, colName, col, bindSize));
+ SQLLEN octetSize = 0;
+ if (!SQL_SUCCEEDED(rc = SQLColAttribute(hStmt, sqlcol, SQL_DESC_OCTET_LENGTH, NULL, 0, NULL, &octetSize))) {
+ throw Error(rc, SQL_HANDLE_STMT, hStmt);
+ }
+ bindSize = octetSize;
+ auto lc = std::make_shared<CharArrayColumn>(this, colName, col, bindSize);
+ ncol = insertColumn(lc);
+ largeColumns.insert(lc);
break;
};
std::dynamic_pointer_cast<Column>(ncol)->bind();
diff --git a/libodbcpp/odbc-selectcommand.h b/libodbcpp/odbc-selectcommand.h
index 2d4311a..1c71d57 100644
--- a/libodbcpp/odbc-selectcommand.h
+++ b/libodbcpp/odbc-selectcommand.h
@@ -15,6 +15,9 @@ namespace ODBC {
private:
bool fetch(SQLSMALLINT orientation = SQL_FETCH_NEXT, SQLLEN offset = 0);
+ typedef std::shared_ptr<Column> ColumnPtr;
+ typedef std::set<ColumnPtr> Columns;
+ Columns largeColumns;
};
}
diff --git a/libodbcpp/unittests/testodbc.cpp b/libodbcpp/unittests/testodbc.cpp
index bb6fd97..9a810c7 100644
--- a/libodbcpp/unittests/testodbc.cpp
+++ b/libodbcpp/unittests/testodbc.cpp
@@ -4,6 +4,7 @@
#include <definedDirs.h>
#include <modifycommand.h>
#include <selectcommand.h>
+#include <selectcommandUtil.impl.h>
#include <column.h>
#include <error.h>
#include <odbc-mock.h>
@@ -90,5 +91,19 @@ BOOST_AUTO_TEST_CASE( bindAndSelectOther )
BOOST_REQUIRE_EQUAL(1, rows);
}
+BOOST_AUTO_TEST_CASE( multibyte )
+{
+ auto ro = DB::MockDatabase::openConnectionTo("odbcmock");
+
+ auto select = ro->select("SELECT LPAD('', n, '£'), n FROM GENERATE_SERIES(1, 50000, 200) n");
+ select->execute();
+ int rows = 0;
+ for (const auto [s, n] : select->as<std::string, int64_t>()) {
+ BOOST_CHECK_EQUAL(s.length(), n * 2);
+ rows += 1;
+ }
+ BOOST_REQUIRE_EQUAL(250, rows);
+}
+
BOOST_AUTO_TEST_SUITE_END();