in src/odbc/rsodbc/rsMetadataServerAPIHelper.cpp [564:774]
SQLRETURN RsMetadataServerAPIHelper::callShowColumns(
SQLHSTMT phstmt, const std::string &catalog, const std::string &schema,
const std::string &table, const std::string &column,
std::vector<SHOWCOLUMNSResult> &intermediateRS) {
RS_STMT_INFO *pStmt = (RS_STMT_INFO *)phstmt;
SQLRETURN rc = SQL_SUCCESS;
std::string sql;
std::string quotedCatalog;
std::string quotedSchema;
std::string quotedTable;
// Input parameter check
if (catalog.empty()) {
addError(&pStmt->pErrorList, "HY000",
"callShowColumns: catalog name should not be null or empty", 0,
NULL);
return SQL_ERROR;
}
if (schema.empty()) {
addError(&pStmt->pErrorList, "HY000",
"callShowColumns: schema name should not be null or empty", 0, NULL);
return SQL_ERROR;
}
if (table.empty()) {
addError(&pStmt->pErrorList, "HY000",
"callShowColumns: table name should not be null or empty", 0, NULL);
return SQL_ERROR;
}
// Apply proper quoting and escaping for identifier
rc = callQuoteFunc(phstmt, catalog, quotedCatalog, RsMetadataAPIHelper::quotedIdentQuery);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
addError(&pStmt->pErrorList, "HY000",
"callShowColumns: Fail to call QUOTE_IDENT on catalog name", 0,
NULL);
return rc;
}
rc = callQuoteFunc(phstmt, schema, quotedSchema, RsMetadataAPIHelper::quotedIdentQuery);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
addError(&pStmt->pErrorList, "HY000",
"callShowColumns: Fail to call QUOTE_IDENT on schema name", 0,
NULL);
return rc;
}
rc = callQuoteFunc(phstmt, table, quotedTable, RsMetadataAPIHelper::quotedIdentQuery);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
addError(&pStmt->pErrorList, "HY000",
"callShowColumns: Fail to call QUOTE_IDENT on table name", 0,
NULL);
return rc;
}
// Build query for SHOW COLUMNS
if (column.empty()) {
sql = "SHOW COLUMNS FROM TABLE " + quotedCatalog + "." + quotedSchema + "." + quotedTable + ";";
} else {
// Apply proper quoting and escaping for literal
std::string quotedColumn;
rc = callQuoteFunc(phstmt, column, quotedColumn, RsMetadataAPIHelper::quotedLiteralQuery);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
addError(&pStmt->pErrorList, "HY000",
"callShowColumns: Fail to call QUOTE_LITERAL on column name", 0,
NULL);
return rc;
}
sql = "SHOW COLUMNS FROM TABLE " + quotedCatalog + "." + quotedSchema + "." + quotedTable + " LIKE " + quotedColumn + ";";
}
// Execute Server API call
RS_LOG_DEBUG("callShowColumns", "Execute SHOW query: %s", sql.c_str());
setCatalogQueryBuf(pStmt, (char *)sql.c_str());
// TODO: Support for prepare not ready yet
rc = RsExecute::RS_SQLExecDirect(phstmt, (SQLCHAR *)sql.c_str(), SQL_NTS,
TRUE, FALSE, FALSE, TRUE);
resetCatalogQueryFlag(pStmt);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
addError(&pStmt->pErrorList, "HY000",
"callShowColumns: Fail to execute SHOW COLUMNS ... ", 0,
NULL);
return rc;
}
// Clean up the column binding
rc = RS_STMT_INFO::RS_SQLFreeStmt(phstmt, SQL_UNBIND, FALSE);
if (rc != SQL_SUCCESS) {
addError(&pStmt->pErrorList, "HY000",
"callShowColumns: Fail to clean up the column binding", 0,
NULL);
return rc;
}
// Bind columns for SHOW TABLES result set
SHOWCOLUMNSResult cur;
rc += RS_STMT_INFO::RS_SQLBindCol(
pStmt,
getIndex(pStmt, RsMetadataAPIHelper::kSHOW_COLUMNS_database_name),
SQL_C_CHAR, cur.database_name, sizeof(cur.database_name),
&cur.database_name_Len);
rc += RS_STMT_INFO::RS_SQLBindCol(
pStmt, getIndex(pStmt, RsMetadataAPIHelper::kSHOW_COLUMNS_schema_name),
SQL_C_CHAR, cur.schema_name, sizeof(cur.schema_name),
&cur.schema_name_Len);
rc += RS_STMT_INFO::RS_SQLBindCol(
pStmt, getIndex(pStmt, RsMetadataAPIHelper::kSHOW_COLUMNS_table_name),
SQL_C_CHAR, cur.table_name, sizeof(cur.table_name),
&cur.table_name_Len);
rc += RS_STMT_INFO::RS_SQLBindCol(
pStmt, getIndex(pStmt, RsMetadataAPIHelper::kSHOW_COLUMNS_column_name),
SQL_C_CHAR, cur.column_name, sizeof(cur.column_name),
&cur.column_name_Len);
rc += RS_STMT_INFO::RS_SQLBindCol(
pStmt,
getIndex(pStmt, RsMetadataAPIHelper::kSHOW_COLUMNS_ordinal_position),
SQL_C_SSHORT, &cur.ordinal_position, sizeof(cur.ordinal_position),
&cur.ordinal_position_Len);
rc += RS_STMT_INFO::RS_SQLBindCol(
pStmt,
getIndex(pStmt, RsMetadataAPIHelper::kSHOW_COLUMNS_column_default),
SQL_C_CHAR, cur.column_default, sizeof(cur.column_default),
&cur.column_default_Len);
rc += RS_STMT_INFO::RS_SQLBindCol(
pStmt, getIndex(pStmt, RsMetadataAPIHelper::kSHOW_COLUMNS_is_nullable),
SQL_C_CHAR, cur.is_nullable, sizeof(cur.is_nullable),
&cur.is_nullable_Len);
rc += RS_STMT_INFO::RS_SQLBindCol(
pStmt, getIndex(pStmt, RsMetadataAPIHelper::kSHOW_COLUMNS_data_type),
SQL_C_CHAR, cur.data_type, sizeof(cur.data_type), &cur.data_type_Len);
rc += RS_STMT_INFO::RS_SQLBindCol(
pStmt,
getIndex(pStmt,
RsMetadataAPIHelper::kSHOW_COLUMNS_character_maximum_length),
SQL_C_SSHORT, &cur.character_maximum_length,
sizeof(cur.character_maximum_length),
&cur.character_maximum_length_Len);
rc += RS_STMT_INFO::RS_SQLBindCol(
pStmt,
getIndex(pStmt, RsMetadataAPIHelper::kSHOW_COLUMNS_numeric_precision),
SQL_C_SSHORT, &cur.numeric_precision, sizeof(cur.numeric_precision),
&cur.numeric_precision_Len);
rc += RS_STMT_INFO::RS_SQLBindCol(
pStmt,
getIndex(pStmt, RsMetadataAPIHelper::kSHOW_COLUMNS_numeric_scale),
SQL_C_SSHORT, &cur.numeric_scale, sizeof(cur.numeric_scale),
&cur.numeric_scale_Len);
rc += RS_STMT_INFO::RS_SQLBindCol(
pStmt, getIndex(pStmt, RsMetadataAPIHelper::kSHOW_COLUMNS_remarks),
SQL_C_CHAR, cur.remarks, sizeof(cur.remarks), &cur.remarks_Len);
if (rc != SQL_SUCCESS) {
addError(&pStmt->pErrorList, "HY000",
"callShowColumns: Fail to bind column for SHOW COLUMNS "
"result ... ",
0, NULL);
return SQL_ERROR;
}
// Retrieve result from SHOW COLUMNS
while (SQL_SUCCEEDED(
rc = RS_STMT_INFO::RS_SQLFetchScroll(phstmt, SQL_FETCH_NEXT, 0))) {
intermediateRS.push_back(cur);
}
// Unbind columns for SHOW TABLES result set
releaseDescriptorRecByNum(
pStmt->pStmtAttr->pARD,
getIndex(pStmt, RsMetadataAPIHelper::kSHOW_COLUMNS_database_name));
releaseDescriptorRecByNum(
pStmt->pStmtAttr->pARD,
getIndex(pStmt, RsMetadataAPIHelper::kSHOW_COLUMNS_schema_name));
releaseDescriptorRecByNum(
pStmt->pStmtAttr->pARD,
getIndex(pStmt, RsMetadataAPIHelper::kSHOW_COLUMNS_table_name));
releaseDescriptorRecByNum(
pStmt->pStmtAttr->pARD,
getIndex(pStmt, RsMetadataAPIHelper::kSHOW_COLUMNS_column_name));
releaseDescriptorRecByNum(
pStmt->pStmtAttr->pARD,
getIndex(pStmt, RsMetadataAPIHelper::kSHOW_COLUMNS_ordinal_position));
releaseDescriptorRecByNum(
pStmt->pStmtAttr->pARD,
getIndex(pStmt, RsMetadataAPIHelper::kSHOW_COLUMNS_column_default));
releaseDescriptorRecByNum(
pStmt->pStmtAttr->pARD,
getIndex(pStmt, RsMetadataAPIHelper::kSHOW_COLUMNS_is_nullable));
releaseDescriptorRecByNum(
pStmt->pStmtAttr->pARD,
getIndex(pStmt, RsMetadataAPIHelper::kSHOW_COLUMNS_data_type));
releaseDescriptorRecByNum(
pStmt->pStmtAttr->pARD,
getIndex(pStmt,
RsMetadataAPIHelper::kSHOW_COLUMNS_character_maximum_length));
releaseDescriptorRecByNum(
pStmt->pStmtAttr->pARD,
getIndex(pStmt, RsMetadataAPIHelper::kSHOW_COLUMNS_numeric_precision));
releaseDescriptorRecByNum(
pStmt->pStmtAttr->pARD,
getIndex(pStmt, RsMetadataAPIHelper::kSHOW_COLUMNS_numeric_scale));
releaseDescriptorRecByNum(
pStmt->pStmtAttr->pARD,
getIndex(pStmt, RsMetadataAPIHelper::kSHOW_COLUMNS_remarks));
// While loop will end if there's no more result to fetch. Therefore, rc
// will be changed to SQL_ERROR
// Simply return SQL_SUCCESS since while loop was finished with no issue
return SQL_SUCCESS;
}