void Cask::CdapOdbc::DataReader::fetchValue(const web::json::value& value, const ColumnBinding& binding) { std::wstring strValue; SQLDOUBLE dblValue = NAN; switch (binding.getTargetType()) { case SQL_CHAR: strValue = to_wstring(value); this->fetchVarchar(strValue.c_str(), binding); break; case SQL_WCHAR: strValue = to_wstring(value); this->fetchWVarchar(strValue.c_str(), binding); break; case SQL_DOUBLE: if (value.is_string()) { dblValue = std::wcstod(value.as_string().c_str(), nullptr); } else if (value.is_integer()) { dblValue = value.as_integer(); } else if (value.is_double()) { dblValue = value.as_double(); } else if (value.is_number()) { dblValue = value.as_number().to_double(); } else if (value.is_boolean()) { dblValue = value.as_bool() ? 1.0 : 0.0; } this->fetchDouble(dblValue, binding); break; } }
void Cask::CdapOdbc::ColumnsDataReader::getColumnValue(const ColumnBinding& binding) { auto& record = this->queryResult.getRows().at(this->currentRowIndex); std::wstring name; std::wstring typeName; SQLSMALLINT radix = 0; switch (binding.getColumnNumber()) { case 1: // TABLE_CAT case 2: // TABLE_SCHEM case 9: // DECIMAL_DIGITS case 12: // REMARKS case 13: // COLUMN_DEF case 15: // SQL_DATETIME_SUB case 16: // CHAR_OCTET_LENGTH this->fetchNull(binding); break; case 3: // TABLE_NAME this->fetchVarchar(this->tableName.c_str(), binding); break; case 4: // COLUMN_NAME name = record.at(L"name").as_string(); this->fetchVarchar(name.c_str(), binding); break; case 5: // DATA_TYPE case 14: // SQL_DATA_TYPE this->fetchSmallint(getDataType(record.at(L"type")), binding); break; case 6: // TYPE_NAME typeName = getTypeName(record.at(L"type")); this->fetchVarchar(typeName.c_str(), binding); break; case 7: // COLUMN_SIZE this->fetchInt(getColumnSize(record.at(L"type")), binding); break; case 8: // BUFFER_LENGTH this->fetchInt(getBufferLength(record.at(L"type")), binding); break; case 10: // NUM_PREC_RADIX radix = getRadix(record.at(L"type")); if (radix > 0) { this->fetchSmallint(radix, binding); } else { this->fetchNull(binding); } break; case 11: // NULLABLE this->fetchSmallint(getIsNull(record.at(L"type")), binding); break; case 17: // ORDINAL_POSITION this->fetchInt(this->currentRowIndex + 1, binding); break; case 18: // IS_NULLABLE this->fetchVarchar((getIsNull(record.at(L"type")) == SQL_NO_NULLS) ? L"NO" : L"YES", binding); break; } }
void Cask::CdapOdbc::QueryDataReader::getColumnValue(const ColumnBinding& binding) { auto& row = this->queryResult.getRows().at(this->currentRowIndex); auto& value = row.at(L"columns").as_array().at(binding.getColumnNumber() - 1); if (value.is_null()) { this->fetchNull(binding); } else { this->fetchValue(value, binding); } }
void Cask::CdapOdbc::TypesDataReader::getColumnValue(const ColumnBinding& binding) { switch (binding.getColumnNumber()) { case 1: // TYPE_NAME this->fetchVarchar(L"string", binding); break; case 2: // DATA_TYPE case 16: // SQL_DATA_TYPE this->fetchSmallint(SQL_VARCHAR, binding); break; case 3: // COLUMN_SIZE this->fetchSmallint(2000, binding); break; case 4: // LITERAL_PREFIX case 5: // LITERAL_SUFFIX case 10: // UNSIGNED_ATTRIBUTE case 12: // AUTO_UNIQUE_VALUE case 13: // LOCAL_TYPE_NAME case 14: // MINIMUM_SCALE case 15: // MAXIMUM_SCALE case 17: // SQL_DATETIME_SUB case 18: // NUM_PREC_RADIX case 19: // INTERVAL_PRECISION this->fetchNull(binding); break; case 6: // CREATE_PARAMS this->fetchVarchar(L"length", binding); break; case 7: // NULLABLE this->fetchSmallint(SQL_NULLABLE, binding); break; case 8: // CASE_SENSITIVE this->fetchSmallint(SQL_TRUE, binding); break; case 9: // SEARCHABLE this->fetchSmallint(SQL_SEARCHABLE, binding); break; case 11: // FIXED_PREC_SCALE this->fetchSmallint(SQL_FALSE, binding); break; } }
void Cask::CdapOdbc::DataReader::fetchWVarchar(const wchar_t* str, const ColumnBinding& binding) { assert(binding.getTargetType() == SQL_WCHAR || binding.getTargetType() == SQL_DEFAULT); if (str) { std::wstring uniStr = str; size_t maxLength = static_cast<size_t>(binding.getBufferLength()) - 1; size_t size = (uniStr.size() < maxLength) ? uniStr.size() : maxLength; if (binding.getTargetValuePtr()) { wchar_t* outString = static_cast<wchar_t*>(binding.getTargetValuePtr()); auto it = stdext::make_checked_array_iterator<wchar_t*>(outString, size); std::copy(uniStr.begin(), uniStr.begin() + size, it); outString[size] = 0; } if (binding.getStrLenOrInd()) { if (size <= maxLength) { *binding.getStrLenOrInd() = size; } else { *binding.getStrLenOrInd() = SQL_NO_TOTAL; } } } else { if (binding.getTargetValuePtr() && binding.getBufferLength() > 0) { wchar_t* outString = static_cast<wchar_t*>(binding.getTargetValuePtr()); outString[0] = 0; } if (binding.getStrLenOrInd()) { *binding.getStrLenOrInd() = SQL_NULL_DATA; } } }
void Cask::CdapOdbc::DataReader::fetchNull(const ColumnBinding& binding) { if (binding.getStrLenOrInd()) { *binding.getStrLenOrInd() = SQL_NULL_DATA; } }
void Cask::CdapOdbc::DataReader::fetchInt(SQLINTEGER value, const ColumnBinding& binding) { assert(binding.getTargetType() == SQL_C_SLONG || binding.getTargetType() == SQL_DEFAULT); *(reinterpret_cast<SQLINTEGER*>(binding.getTargetValuePtr())) = value; }
void Cask::CdapOdbc::DataReader::fetchDouble(SQLDOUBLE value, const ColumnBinding& binding) { assert(binding.getTargetType() == SQL_DOUBLE || binding.getTargetType() == SQL_DEFAULT); *(reinterpret_cast<SQLDOUBLE*>(binding.getTargetValuePtr())) = value; }
void Cask::CdapOdbc::DataReader::fetchSmallint(SQLSMALLINT value, const ColumnBinding& binding) { assert(binding.getTargetType() == SQL_C_SSHORT || binding.getTargetType() == SQL_DEFAULT); *(reinterpret_cast<SQLSMALLINT*>(binding.getTargetValuePtr())) = value; }