in src/odbc/rsodbc/rslibpq.c [3478:3695]
SQLRETURN libpqCreateSQLColumnsCustomizedResultSet(
RS_STMT_INFO *pStmt, short columnNum,
const std::vector<SHOWCOLUMNSResult> &intermediateRS) {
int intermediateRSLen = intermediateRS.size();
int columnSize = 0, bufferLen = 0, charOctetLen = 0;
short sqlType = 0, sqlDataType = 0, sqlDateSub = 0, precisions = 0,
decimalDigit = 0, num_pre_radix = 0;
std::string intStr = {0};
std::string shortStr = {0};
bool dateTimeCustomizePrecision = false;
std::string rsType;
PGresult *res = pStmt->pResultHead->pgResult;
PQsetNumAttributes(res, columnNum);
for (int i = 0; i < intermediateRSLen; i++) {
// Reset the variable
columnSize = 0;
bufferLen = 0;
charOctetLen = 0;
sqlType = 0;
sqlDataType = 0;
sqlDateSub = 0;
precisions = 0;
decimalDigit = 0;
num_pre_radix = 0;
dateTimeCustomizePrecision = false;
rsType.clear();
// Retrieve customize precision for second fraction
std::regex dateTimeRegex(
"(time|timetz|timestamp|timestamptz)\\(\\d+\\).*");
std::regex intervalRegex("interval.*.\\(\\d+\\)");
std::string dataType = char2String(intermediateRS[i].data_type);
if (std::regex_match(dataType, dateTimeRegex) ||
std::regex_match(dataType, intervalRegex)) {
std::string cleanedDataType =
std::regex_replace(dataType, std::regex("\\(\\d+\\)"), "");
trim(cleanedDataType);
auto it = RsMetadataAPIHelper::typeInfoMap.find(cleanedDataType);
if (it != RsMetadataAPIHelper::typeInfoMap.end()) {
const auto &typeInfo = it->second;
sqlType = typeInfo.sqlType;
sqlDataType = typeInfo.sqlDataType;
sqlDateSub = typeInfo.sqlDateSub;
rsType = typeInfo.typeName;
} else {
rsType = cleanedDataType;
}
std::smatch match;
if (std::regex_search(dataType, match,
std::regex(".*\\(([0-9]+)\\).*"))) {
precisions = std::stoi(match[1]);
dateTimeCustomizePrecision = true;
}
} else {
auto it = RsMetadataAPIHelper::typeInfoMap.find(
(char *)intermediateRS[i].data_type);
if (it != RsMetadataAPIHelper::typeInfoMap.end()) {
const auto &typeInfo = it->second;
sqlType = typeInfo.sqlType;
sqlDataType = typeInfo.sqlDataType;
sqlDateSub = typeInfo.sqlDateSub;
rsType = typeInfo.typeName;
} else {
rsType = std::string(reinterpret_cast<const char *>(
intermediateRS[i].data_type));
}
}
columnSize = RsMetadataAPIHelper::getColumnSize(
rsType, intermediateRS[i].character_maximum_length,
intermediateRS[i].numeric_precision);
bufferLen = RsMetadataAPIHelper::getBufferLen(
rsType, intermediateRS[i].character_maximum_length,
intermediateRS[i].numeric_precision);
decimalDigit = RsMetadataAPIHelper::getDecimalDigit(
rsType, intermediateRS[i].numeric_scale, precisions,
dateTimeCustomizePrecision);
num_pre_radix = RsMetadataAPIHelper::getNumPrecRadix(rsType);
charOctetLen = RsMetadataAPIHelper::getCharOctetLen(
rsType, intermediateRS[i].character_maximum_length);
// Catalog name
PQsetvalue(res, i, kSQLColumns_TABLE_CAT,
(char *)intermediateRS[i].database_name,
intermediateRS[i].database_name_Len);
// Schema name
PQsetvalue(res, i, kSQLColumns_TABLE_SCHEM,
(char *)intermediateRS[i].schema_name,
intermediateRS[i].schema_name_Len);
// Table name
PQsetvalue(res, i, kSQLColumns_TABLE_NAME,
(char *)intermediateRS[i].table_name,
intermediateRS[i].table_name_Len);
// Column name
PQsetvalue(res, i, kSQLColumns_COLUMN_NAME,
(char *)intermediateRS[i].column_name,
intermediateRS[i].column_name_Len);
// SQL type (concise data type)
shortStr = std::to_string(sqlType);
PQsetvalue(res, i, kSQLColumns_DATA_TYPE, shortStr.data(),
shortStr.size());
// Redshift type name
PQsetvalue(res, i, kSQLColumns_TYPE_NAME, (char *)rsType.c_str(),
rsType.size());
// Column size
if (columnSize == kNotApplicable) {
PQsetvalue(res, i, kSQLColumns_COLUMN_SIZE, NULL, NULL_LEN);
} else {
intStr = std::to_string(columnSize);
PQsetvalue(res, i, kSQLColumns_COLUMN_SIZE, intStr.data(),
intStr.size());
}
// Buffer length
if (bufferLen == kNotApplicable) {
PQsetvalue(res, i, kSQLColumns_BUFFER_LENGTH, NULL, NULL_LEN);
} else {
intStr = std::to_string(bufferLen);
PQsetvalue(res, i, kSQLColumns_BUFFER_LENGTH, intStr.data(),
intStr.size());
}
// Decimal digits
if (decimalDigit == kNotApplicable) {
// Return NULL where DECIMAL_DIGITS is not applicable
PQsetvalue(res, i, kSQLColumns_DECIMAL_DIGITS, NULL, NULL_LEN);
} else {
shortStr = std::to_string(decimalDigit);
PQsetvalue(res, i, kSQLColumns_DECIMAL_DIGITS, shortStr.data(),
shortStr.size());
}
// Num prec radix
if (num_pre_radix == kNotApplicable) {
// Return NULL where NUM_PREC_RADIX is not applicable
PQsetvalue(res, i, kSQLColumns_NUM_PREC_RADIX, NULL, NULL_LEN);
} else {
shortStr = std::to_string(num_pre_radix);
PQsetvalue(res, i, kSQLColumns_NUM_PREC_RADIX, shortStr.data(),
shortStr.size());
}
// Nullable
shortStr = std::to_string(RsMetadataAPIHelper::getNullable(
char2String(intermediateRS[i].is_nullable)));
PQsetvalue(res, i, kSQLColumns_NULLABLE, shortStr.data(),
shortStr.size());
// Remarks
PQsetvalue(res, i, kSQLColumns_REMARKS,
(char *)intermediateRS[i].remarks,
intermediateRS[i].remarks_Len);
// Column default
PQsetvalue(res, i, kSQLColumns_COLUMN_DEF,
(char *)intermediateRS[i].column_default,
intermediateRS[i].column_default_Len);
// SQL Data type (non-concise data type)
shortStr = std::to_string(sqlDataType);
PQsetvalue(res, i, kSQLColumns_SQL_DATA_TYPE, shortStr.data(),
shortStr.size());
// SQL Date data type subtype code
if (sqlDateSub == kNotApplicable) {
PQsetvalue(res, i, kSQLColumns_SQL_DATETIME_SUB, NULL, NULL_LEN);
} else {
shortStr = std::to_string(sqlDateSub);
PQsetvalue(res, i, kSQLColumns_SQL_DATETIME_SUB, shortStr.data(),
shortStr.size());
}
// char octet length
if (charOctetLen == kNotApplicable) {
PQsetvalue(res, i, kSQLColumns_CHAR_OCTET_LENGTH, NULL, NULL_LEN);
} else {
intStr = std::to_string(charOctetLen);
PQsetvalue(res, i, kSQLColumns_CHAR_OCTET_LENGTH, intStr.data(),
intStr.size());
}
// Ordinal position
intStr = std::to_string(intermediateRS[i].ordinal_position);
PQsetvalue(res, i, kSQLColumns_ORDINAL_POSITION, intStr.data(),
intStr.size());
// Is nullable
PQsetvalue(res, i, kSQLColumns_IS_NULLABLE,
(char *)intermediateRS[i].is_nullable,
intermediateRS[i].is_nullable_Len);
}
// Set the total row number
pStmt->pResultHead->iNumberOfRowsInMem = intermediateRSLen;
// Reset the current row number for fetching result
pStmt->pResultHead->iCurRow = -1;
return SQL_SUCCESS;
}