support also boolean and integer data types, do not treat everything as mere strings v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Thu, 04 Jun 2020 13:24:17 +0200
branchv_0
changeset 48 c83119110c7b
parent 47 428c278af4be
child 49 1d17192565bf
support also boolean and integer data types, do not treat everything as mere strings
src/PreparedStatement.cpp
src/ResultSet.cpp
src/SqlHandler.h
--- a/src/PreparedStatement.cpp	Thu Jun 04 00:46:00 2020 +0200
+++ b/src/PreparedStatement.cpp	Thu Jun 04 13:24:17 2020 +0200
@@ -58,8 +58,7 @@
 
 void PreparedStatement::setBoolean(int parameterNumber, relpipe::reader::boolean_t value) {
 	booleanParameters.emplace_back(value);
-	// TODO: review SQL_C_TINYINT
-	SQLRETURN result = SQLBindParameter(statement, parameterNumber, SQL_PARAM_INPUT, SQL_C_TINYINT, SQL_INTEGER, 0, 0, &booleanParameters.back(), 0, nullptr);
+	SQLRETURN result = SQLBindParameter(statement, parameterNumber, SQL_PARAM_INPUT, SQL_C_BIT, SQL_INTEGER, 0, 0, &booleanParameters.back(), 0, nullptr);
 	if (OdbcCommon::isNotSuccessful(result)) throw SqlException(L"Unable to set boolean parameter in prepared statement", result, SQL_HANDLE_STMT, statement);
 }
 
--- a/src/ResultSet.cpp	Thu Jun 04 00:46:00 2020 +0200
+++ b/src/ResultSet.cpp	Thu Jun 04 13:24:17 2020 +0200
@@ -44,12 +44,18 @@
 }
 
 relpipe::writer::boolean_t ResultSet::getBoolean(unsigned short columnNumber, bool* isNull) {
-	throw SqlException(L"not yet implemented: getBoolean()");
+	relpipe::writer::string_t s = getString(columnNumber, isNull);
+	if (isNull && *isNull) return false;
+	else if (s == L"1" || s == L"true" || s == L"y" || s == L"yes" || s == L"TRUE" || s == L"Y" || s == L"YES") return true;
+	else if (s == L"0" || s == L"false" || s == L"n" || s == L"no" || s == L"FALSE" || s == L"N" || s == L"NO") return false;
+	else throw SqlException(L"Unable to parse „" + s + L"“ as boolean");
 }
 
 relpipe::writer::integer_t ResultSet::getInteger(unsigned short columnNumber, bool* isNull) {
-	throw SqlException(L"not yet implemented: getInteger()");
-
+	// TODO: get integer directly from SQLGetData() without string conversion
+	relpipe::writer::string_t s = getString(columnNumber, isNull);
+	if (isNull && *isNull) return 0;
+	else return std::stol(s);
 }
 
 relpipe::writer::string_t ResultSet::getString(unsigned short columnNumber, bool* isNull) {
@@ -85,10 +91,15 @@
 		SQLULEN columnSize;
 		SQLSMALLINT decimalDigits;
 		SQLSMALLINT nullable;
+
 		result = SQLDescribeCol(statement, columnNumber, (SQLCHAR*) nameBuffer.c_str(), nameBuffer.capacity(), &nameLength, &dataType, &columnSize, &decimalDigits, &nullable);
 		if (OdbcCommon::isNotSuccessful(result)) throw SqlException(L"Unable describe column", result, SQL_HANDLE_STMT, statement);
+
 		columnDescriptor.name = convertor.from_bytes(nameBuffer.c_str());
-		//columnDescriptor.type = … // FIXME: support also other types than string
+
+		if (dataType == SQL_INTEGER || dataType == SQL_BIGINT) columnDescriptor.type = relpipe::writer::TypeId::INTEGER;
+		else if (dataType == SQL_BIT) columnDescriptor.type = relpipe::writer::TypeId::BOOLEAN;
+
 		columnDescriptors.emplace_back(columnDescriptor);
 	}
 
--- a/src/SqlHandler.h	Thu Jun 04 00:46:00 2020 +0200
+++ b/src/SqlHandler.h	Thu Jun 04 13:24:17 2020 +0200
@@ -117,7 +117,16 @@
 
 		while (resultSet->next()) {
 			for (int columnNumber = 1; columnNumber <= columnCount; columnNumber++) {
-				relationalWriter->writeAttribute(resultSet->getString(columnNumber));
+				// TODO: null values (when supported in the format)
+				if (metadata[columnNumber - 1].typeId == relpipe::writer::TypeId::BOOLEAN) {
+					auto booleanValue = resultSet->getBoolean(columnNumber);
+					relationalWriter->writeAttribute(&booleanValue, typeid (booleanValue));
+				} else if (metadata[columnNumber - 1].typeId == relpipe::writer::TypeId::INTEGER) {
+					auto integerValue = resultSet->getInteger(columnNumber);
+					relationalWriter->writeAttribute(&integerValue, typeid (integerValue));
+				} else {
+					relationalWriter->writeAttribute(resultSet->getString(columnNumber));
+				}
 			}
 		}
 	}
@@ -146,8 +155,8 @@
 	}
 
 	relpipe::writer::string_t toSQLType(relpipe::reader::TypeId typeId) {
-		if (typeId == relpipe::reader::TypeId::BOOLEAN) return L"integer"; // TODO: map selected values back to booleans or allow optional storage as string 
-		else if (typeId == relpipe::reader::TypeId::INTEGER) return L"integer";
+		if (typeId == relpipe::reader::TypeId::BOOLEAN) return L"integer"; // TODO: bit type might fit better, but needs more testing (support in various DBMS and their drivers)
+		else if (typeId == relpipe::reader::TypeId::INTEGER) return L"bigint";
 		else return L"text";
 	}