SQLRETURN RsMetadataServerAPIHelper::callShowColumns()

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;
}