in sql-odbc/src/sqlodbc/results.c [760:1003]
RETCODE SQL_API OPENSEARCHAPI_GetData(HSTMT hstmt, SQLUSMALLINT icol,
SQLSMALLINT fCType, PTR rgbValue,
SQLLEN cbValueMax, SQLLEN *pcbValue) {
CSTR func = "OPENSEARCHAPI_GetData";
QResultClass *res;
StatementClass *stmt = (StatementClass *)hstmt;
UInt2 num_cols;
SQLLEN num_rows;
OID field_type;
int atttypmod;
void *value = NULL;
RETCODE result = SQL_SUCCESS;
char get_bookmark = FALSE;
SQLSMALLINT target_type;
int precision = -1;
#ifdef WITH_UNIXODBC
SQLCHAR dum_rgb[2] = "\0\0";
#endif /* WITH_UNIXODBC */
MYLOG(OPENSEARCH_TRACE, "entering stmt=%p icol=%d\n", stmt, icol);
if (!stmt) {
SC_log_error(func, NULL_STRING, NULL);
return SQL_INVALID_HANDLE;
}
res = SC_get_Curres(stmt);
if (STMT_EXECUTING == stmt->status) {
SC_set_error(stmt, STMT_SEQUENCE_ERROR,
"Can't get data while statement is still executing.",
func);
return SQL_ERROR;
}
if (stmt->status != STMT_FINISHED) {
SC_set_error(stmt, STMT_STATUS_ERROR,
"GetData can only be called after the successful "
"execution on a SQL statement",
func);
return SQL_ERROR;
}
#ifdef WITH_UNIXODBC
if (NULL == rgbValue) /* unixODBC allows rgbValue is NULL? */
{
cbValueMax = 0;
rgbValue = dum_rgb; /* to avoid a crash */
}
#endif /* WITH_UNIXODBC */
if (SQL_ARD_TYPE == fCType) {
ARDFields *opts;
BindInfoClass *binfo = NULL;
opts = SC_get_ARDF(stmt);
if (0 == icol)
binfo = opts->bookmark;
else if (icol <= opts->allocated && opts->bindings)
binfo = &opts->bindings[icol - 1];
if (binfo) {
target_type = binfo->returntype;
MYLOG(OPENSEARCH_DEBUG, "SQL_ARD_TYPE=%d\n", target_type);
precision = binfo->precision;
} else {
SC_set_error(stmt, STMT_STATUS_ERROR,
"GetData can't determine the type via ARD", func);
return SQL_ERROR;
}
} else
target_type = fCType;
if (icol == 0) {
if (stmt->options.use_bookmarks == SQL_UB_OFF) {
SC_set_error(
stmt, STMT_COLNUM_ERROR,
"Attempt to retrieve bookmark with bookmark usage disabled",
func);
return SQL_ERROR;
}
/* Make sure it is the bookmark data type */
switch (target_type) {
case SQL_C_BOOKMARK:
case SQL_C_VARBOOKMARK:
break;
default:
MYLOG(
OPENSEARCH_ALL,
"GetData Column 0 is type %d not of type SQL_C_BOOKMARK\n",
target_type);
SC_set_error(stmt, STMT_PROGRAM_TYPE_OUT_OF_RANGE,
"Column 0 is not of type SQL_C_BOOKMARK", func);
return SQL_ERROR;
}
get_bookmark = TRUE;
} else {
/* use zero-based column numbers */
icol--;
/* make sure the column number is valid */
num_cols = QR_NumPublicResultCols(res);
if (icol >= num_cols) {
SC_set_error(stmt, STMT_INVALID_COLUMN_NUMBER_ERROR,
"Invalid column number.", func);
return SQL_ERROR;
}
}
#ifdef __APPLE__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wkeyword-macro"
#endif // __APPLE__
#define return DONT_CALL_RETURN_FROM_HERE ? ? ?
#ifdef __APPLE__
#pragma clang diagnostic pop
#endif // __APPLE__
if (!SC_is_fetchcursor(stmt)) {
/* make sure we're positioned on a valid row */
num_rows = QR_get_num_total_tuples(res);
if ((stmt->currTuple < 0) || (stmt->currTuple >= num_rows)) {
SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR,
"Not positioned on a valid row for GetData.", func);
result = SQL_ERROR;
goto cleanup;
}
MYLOG(OPENSEARCH_DEBUG, " num_rows = " FORMAT_LEN "\n", num_rows);
if (!get_bookmark) {
SQLLEN curt = GIdx2CacheIdx(stmt->currTuple, stmt, res);
value = QR_get_value_backend_row(res, curt, icol);
MYLOG(OPENSEARCH_DEBUG,
"currT=" FORMAT_LEN " base=" FORMAT_LEN " rowset=" FORMAT_LEN
"\n",
stmt->currTuple, QR_get_rowstart_in_cache(res),
SC_get_rowset_start(stmt));
MYLOG(OPENSEARCH_DEBUG, " value = '%s'\n", NULL_IF_NULL(value));
}
} else {
/* it's a SOCKET result (backend data) */
if (stmt->currTuple == -1 || !res || !res->tupleField) {
SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR,
"Not positioned on a valid row for GetData.", func);
result = SQL_ERROR;
goto cleanup;
}
if (!get_bookmark) {
/** value = QR_get_value_backend(res, icol); maybe thiw doesn't work
*/
SQLLEN curt = GIdx2CacheIdx(stmt->currTuple, stmt, res);
value = QR_get_value_backend_row(res, curt, icol);
}
MYLOG(OPENSEARCH_DEBUG, " socket: value = '%s'\n", NULL_IF_NULL(value));
}
if (get_bookmark) {
BOOL contents_get = FALSE;
if (rgbValue) {
if (SQL_C_BOOKMARK == target_type
|| (SQLLEN)sizeof(UInt4) <= cbValueMax) {
Int4 bookmark = (int)SC_make_int4_bookmark(stmt->currTuple);
contents_get = TRUE;
memcpy(rgbValue, &bookmark, sizeof(bookmark));
}
}
if (pcbValue)
*pcbValue = sizeof(Int4);
if (contents_get)
result = SQL_SUCCESS;
else {
SC_set_error(stmt, STMT_TRUNCATED,
"The buffer was too small for the GetData.", func);
result = SQL_SUCCESS_WITH_INFO;
}
goto cleanup;
}
field_type = QR_get_field_type(res, icol);
atttypmod = QR_get_atttypmod(res, icol);
MYLOG(OPENSEARCH_DEBUG,
"**** icol = %d, target_type = %d, field_type = %d, value = '%s'\n",
icol, target_type, field_type, NULL_IF_NULL(value));
SC_set_current_col(stmt, icol);
result = (RETCODE)copy_and_convert_field(stmt, field_type, atttypmod, value,
target_type, precision, rgbValue,
cbValueMax, pcbValue, pcbValue);
switch (result) {
case COPY_OK:
result = SQL_SUCCESS;
break;
case COPY_UNSUPPORTED_TYPE:
SC_set_error(stmt, STMT_RESTRICTED_DATA_TYPE_ERROR,
"Received an unsupported type from OpenSearch.",
func);
result = SQL_ERROR;
break;
case COPY_UNSUPPORTED_CONVERSION:
SC_set_error(stmt, STMT_RESTRICTED_DATA_TYPE_ERROR,
"Couldn't handle the necessary data type conversion.",
func);
result = SQL_ERROR;
break;
case COPY_RESULT_TRUNCATED:
SC_set_error(stmt, STMT_TRUNCATED,
"The buffer was too small for the GetData.", func);
result = SQL_SUCCESS_WITH_INFO;
break;
case COPY_INVALID_STRING_CONVERSION: /* invalid string */
SC_set_error(stmt, STMT_STRING_CONVERSION_ERROR,
"invalid string conversion occured.", func);
result = SQL_ERROR;
break;
case COPY_GENERAL_ERROR: /* error msg already filled in */
result = SQL_ERROR;
break;
case COPY_NO_DATA_FOUND:
/* SC_log_error(func, "no data found", stmt); */
result = SQL_NO_DATA_FOUND;
break;
default:
SC_set_error(
stmt, STMT_INTERNAL_ERROR,
"Unrecognized return value from copy_and_convert_field.", func);
result = SQL_ERROR;
break;
}
cleanup:
#undef return
MYLOG(OPENSEARCH_TRACE, "leaving %d\n", result);
return result;
}