Date: Monday, March 20, 2006 @ 22:18:18
Author: marc
Path: /cvsroot/carob/odbsequoia/src
Modified: descriptors_records.cpp (1.6 -> 1.7)
Implemented SQLFetch() to signed integers, floating-point types and strings
(both CHAR and WCHAR).
-------------------------+
descriptors_records.cpp | 168 ++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 162 insertions(+), 6 deletions(-)
Index: odbsequoia/src/descriptors_records.cpp
diff -u odbsequoia/src/descriptors_records.cpp:1.6
odbsequoia/src/descriptors_records.cpp:1.7
--- odbsequoia/src/descriptors_records.cpp:1.6 Thu Mar 9 15:10:21 2006
+++ odbsequoia/src/descriptors_records.cpp Mon Mar 20 22:18:18 2006
@@ -24,7 +24,11 @@
#include "odbc_exception.hpp"
+
#include "DriverResultSet.hpp"
+#include "StringCodecs.hpp" //for toString
+
+#include "util.hpp"
using namespace ODBSeqNS;
@@ -44,6 +48,34 @@
AppDescRecord::bind_col(SQLSMALLINT TargetType, SQLPOINTER TargetValuePtr,
SQLINTEGER BufferLength, SQLLEN * StrLen_or_Ind)
{
+ switch (TargetType) {
+
+ // list of supported types so far
+ case (SQL_C_SHORT): //ODBC 2.0
+ case (SQL_C_SSHORT):
+ case (SQL_C_LONG): // ODBC 2.0
+ case (SQL_C_SLONG):
+ case (SQL_C_TINYINT): // ODBC 2.0
+ case (SQL_C_STINYINT):
+// case (SQL_C_SBIGINT): see below
+
+ case (SQL_C_FLOAT):
+ case (SQL_C_DOUBLE):
+
+ case (SQL_C_WCHAR):
+ case (SQL_C_CHAR):
+ break;
+
+ // else unsupported type
+ default:
+ throw ODBSeqException (L"HYC00",
+ L"internal error: unsupported conversion in
SQLBindCol()");
+
+ // We are assuming someone trapped invalid arguments and
+ // throwed "HY003" before us. "Someone" should be either DM
+ // or set_type()
+ }
+
set_type(TargetType);
octet_length = BufferLength;
@@ -58,6 +90,9 @@
ODBSeqException *
AppDescRecord::fetch_col(CarobNS::DriverResultSet& rs, int rs_col)
{
+
+ ODBSeqException *warning(0);
+
if (rs.isNull(rs_col))
{
if (0 == indicator_ptr)
@@ -66,18 +101,139 @@
L"because indicator_ptr is null");
* indicator_ptr = SQL_NULL_DATA;
- return 0;
+ return warning;
}
- // case (type == SQL_C_INT)
- * static_cast<int *>(data_ptr) = rs.getAsInt(rs_col);
- if (octet_length_ptr != 0)
- * octet_length_ptr = sizeof(int);
+ // TODO: split this switch into separate methods, one for each
+ // target type. Then replace this switch by pointers to these
+ // methods assigned earlier at SQLBindCol() time. Do it for: (1)
+ // clarity (smaller functions); (2) performance
+
+ // TODO: for each target type, throw "07006" when the (source,
+ // target) types conversion is not allowed in the big SQL->C type
+ // conversion table ("Converting Data from SQL to C Data
+ // Types"). Check that carob does not do it already.
+ switch (concise_type) {
+
+
+ /*** Integer types ***/
+
+ // FIXME: currently not checking for bounds (22003). And no
+ // warnings on fractional truncation either, because carob does
+ // them, see CAROB-77.
+
+ case (SQL_C_SHORT): // ODBC 2.0
+ case (SQL_C_SSHORT):
+ * static_cast<SQLSMALLINT *>(data_ptr) = rs.getAsInt(rs_col);
+ if (octet_length_ptr != 0)
+ * octet_length_ptr = sizeof(SQLSMALLINT);
+ break;
+
+ case (SQL_C_LONG): // ODBC 2.0
+ case (SQL_C_SLONG):
+ // FIXME: here we assume sizeof(long) <= 64
+ * static_cast<SQLINTEGER *>(data_ptr) = rs.getAsInt64(rs_col);
+ if (octet_length_ptr != 0)
+ * octet_length_ptr = sizeof(SQLINTEGER);
+ break;
+
+ // Despite SQL Server's TINYINT being unsigned, ODBC'
+ // SQL_C_TINYINT is signed as we can see here:
+ // http://support.microsoft.com/kb/131382/en-us or in DB2
+ // documentation here:
+ // http://www.google.com/search?q=DB2+C+data+types+for+CLI+applications
+ // TODO: check Microsoft ODBC 2.0 Programmer's Reference and
+ // SDK Guide
+ case (SQL_C_TINYINT): // ODBC 2.0
+ case (SQL_C_STINYINT):
+ * static_cast<SQLSCHAR *>(data_ptr) = rs.getAsInt(rs_col);
+ if (octet_length_ptr != 0)
+ * octet_length_ptr = sizeof(SQLSCHAR);
+ break;
+
+ case (SQL_C_SBIGINT):
+ // * static_cast<SQLBIGINT *>(data_ptr) = rs.getAsInt64(rs_col);
+ * static_cast<int64_t *>(data_ptr) = rs.getAsInt64(rs_col);
+ // TODO: big portability mess here again: long long and
+ // uint64_t are from C99. Reinterpret_casting 2x32bits struct
+ // SQLBIGINT may cause endianness issues? Should we try
+ // ODBCINT64?
+ if (octet_length_ptr != 0)
+ * octet_length_ptr = sizeof(int64_t);
+ break;
+
+
+ /*** Binary floating-point types ***/
+
+ case (SQL_C_FLOAT):
+ * static_cast<SQLREAL *>(data_ptr) = rs.getAsFloat(rs_col);
+ if (octet_length_ptr != 0)
+ * octet_length_ptr = sizeof(SQLREAL);
+ break;
+
+ case (SQL_C_DOUBLE):
+ * static_cast<SQLDOUBLE *>(data_ptr) = rs.getAsDouble(rs_col);
+ if (octet_length_ptr != 0)
+ * octet_length_ptr = sizeof(SQLDOUBLE);
+ break;
+
+
+ /*** String types ***/
+ // FIXME: UNTESTED: check for corner cases (like truncated null
terminator)
+
+ case (SQL_C_WCHAR): {
+
+ const std::wstring wsres = rs.getAsString(rs_col);
+
+ if (octet_length_ptr != 0)
+ *octet_length_ptr = wsres.size() * sizeof(SQLWCHAR);
+
+ bool truncated =
+ toSQLW (wsres, static_cast<SQLWCHAR *>(data_ptr),
+ octet_length/(SQLINTEGER)sizeof(SQLWCHAR), 0);
+
+ if (truncated)
+ warning = new ODBSeqException(L"01004", L"string truncated");
+ break;
+ }
+
+ case (SQL_C_CHAR): {
+
+ std::string nsres =
CarobNS::StaticCodecs::toString(rs.getAsString(rs_col));
+
+ if (octet_length_ptr != 0)
+ *octet_length_ptr = nsres.size();
+
+ if (octet_length == 0) {
+ warning = new ODBSeqException(L"01004", L"empty buffer");
+ break;
+ }
+
+ const std::string::size_type final_size =
+// nsres.copy(static_cast<SQLCHAR *>(data_ptr), octet_length-1); //
_unsigned_ char!
+ nsres.copy(static_cast<char *> (data_ptr), octet_length-1);
+
+ // Now let's null-terminate the C string
+ * (static_cast<char *>(data_ptr) + final_size) = 0;
+
+ if (final_size != nsres.size())
+ warning = new ODBSeqException(L"01004", L"string truncated");
+
+ break;
+
+ }
+ /*** Unsupported types ***/
+ default:
+ // catching sooner is better (in bind_col() method above),
+ // but we are still allowed to throw HYC00 later here
+ throw ODBSeqException (L"HYC00",
+ L"internal error: unsupported conversion in
SQLFetch()");
+ }
if (indicator_ptr != 0 && indicator_ptr != octet_length_ptr)
*indicator_ptr = 0;
- return 0;
+ return warning;
}
/*
* Local Variables:
_______________________________________________
Carob-commits mailing list
[email protected]
https://forge.continuent.org/mailman/listinfo/carob-commits