in sql-odbc/src/sqlodbc/results.c [96:311]
RETCODE SQL_API OPENSEARCHAPI_DescribeCol(HSTMT hstmt, SQLUSMALLINT icol,
SQLCHAR *szColName, SQLSMALLINT cbColNameMax,
SQLSMALLINT *pcbColName,
SQLSMALLINT *pfSqlType, SQLULEN *pcbColDef,
SQLSMALLINT *pibScale,
SQLSMALLINT *pfNullable) {
CSTR func = "OPENSEARCHAPI_DescribeCol";
/* gets all the information about a specific column */
StatementClass *stmt = (StatementClass *)hstmt;
ConnectionClass *conn;
IRDFields *irdflds;
QResultClass *res = NULL;
char *col_name = NULL;
OID fieldtype = 0;
SQLLEN column_size = 0;
int unknown_sizes;
SQLINTEGER decimal_digits = 0;
ConnInfo *ci;
FIELD_INFO *fi;
char buf[255];
int len = 0;
RETCODE result = SQL_SUCCESS;
MYLOG(OPENSEARCH_TRACE, "entering.%d..\n", icol);
if (!stmt) {
SC_log_error(func, NULL_STRING, NULL);
return SQL_INVALID_HANDLE;
}
conn = SC_get_conn(stmt);
ci = &(conn->connInfo);
unknown_sizes = DEFAULT_UNKNOWNSIZES;
SC_clear_error(stmt);
#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__
irdflds = SC_get_IRDF(stmt);
if (0 == icol) /* bookmark column */
{
SQLSMALLINT fType = stmt->options.use_bookmarks == SQL_UB_VARIABLE
? SQL_BINARY
: SQL_INTEGER;
MYLOG(OPENSEARCH_ALL, "answering bookmark info\n");
if (szColName && cbColNameMax > 0)
*szColName = '\0';
if (pcbColName)
*pcbColName = 0;
if (pfSqlType)
*pfSqlType = fType;
if (pcbColDef)
*pcbColDef = 10;
if (pibScale)
*pibScale = 0;
if (pfNullable)
*pfNullable = SQL_NO_NULLS;
result = SQL_SUCCESS;
goto cleanup;
}
/*
* Dont check for bookmark column. This is the responsibility of the
* driver manager.
*/
icol--; /* use zero based column numbers */
fi = NULL;
if (icol < irdflds->nfields && irdflds->fi)
fi = irdflds->fi[icol];
if (!FI_is_applicable(fi)) {
fi = NULL;
res = SC_get_Curres(stmt);
if (icol >= QR_NumPublicResultCols(res)) {
SC_set_error(stmt, STMT_INVALID_COLUMN_NUMBER_ERROR,
"Invalid column number in DescribeCol.", func);
SPRINTF_FIXED(buf, "Col#=%d, #Cols=%d,%d keys=%d", icol,
QR_NumResultCols(res), QR_NumPublicResultCols(res),
res->num_key_fields);
SC_log_error(func, buf, stmt);
result = SQL_ERROR;
goto cleanup;
}
if (icol < irdflds->nfields && irdflds->fi)
fi = irdflds->fi[icol];
}
res = SC_get_Curres(stmt);
#ifdef SUPPRESS_LONGEST_ON_CURSORS
if (UNKNOWNS_AS_LONGEST == unknown_sizes) {
if (QR_once_reached_eof(res))
unknown_sizes = UNKNOWNS_AS_LONGEST;
else
unknown_sizes = UNKNOWNS_AS_MAX;
}
#endif /* SUPPRESS_LONGEST_ON_CURSORS */
/* handle constants */
if (res && -2 == QR_get_fieldsize(res, icol))
unknown_sizes = UNKNOWNS_AS_LONGEST;
if (FI_is_applicable(fi)) {
fieldtype = getEffectiveOid(conn, fi);
if (NAME_IS_VALID(fi->column_alias))
col_name = GET_NAME(fi->column_alias);
else
col_name = GET_NAME(fi->column_name);
if (USE_FI(fi, unknown_sizes)) {
column_size = fi->column_size;
decimal_digits = fi->decimal_digits;
} else {
column_size = opensearchtype_column_size(stmt, fieldtype, icol,
unknown_sizes);
decimal_digits =
opensearchtype_decimal_digits(stmt, fieldtype, icol);
}
MYLOG(OPENSEARCH_DEBUG,
"PARSE: fieldtype=%u, col_name='%s', column_size=" FORMAT_LEN
"\n",
fieldtype, NULL_IF_NULL(col_name), column_size);
} else {
col_name = QR_get_fieldname(res, icol);
fieldtype = QR_get_field_type(res, icol);
column_size =
opensearchtype_column_size(stmt, fieldtype, icol, unknown_sizes);
decimal_digits = opensearchtype_decimal_digits(stmt, fieldtype, icol);
}
MYLOG(OPENSEARCH_DEBUG, "col %d fieldname = '%s'\n", icol, NULL_IF_NULL(col_name));
MYLOG(OPENSEARCH_DEBUG, "col %d fieldtype = %d\n", icol, fieldtype);
MYLOG(OPENSEARCH_DEBUG, "col %d column_size = " FORMAT_LEN "\n", icol, column_size);
result = SQL_SUCCESS;
/*
* COLUMN NAME
*/
len = col_name ? (int)strlen(col_name) : 0;
if (pcbColName)
*pcbColName = (SQLSMALLINT)len;
if (szColName && cbColNameMax > 0) {
if (NULL != col_name)
strncpy_null((char *)szColName, col_name, cbColNameMax);
else
szColName[0] = '\0';
if (len >= cbColNameMax) {
result = SQL_SUCCESS_WITH_INFO;
SC_set_error(stmt, STMT_TRUNCATED,
"The buffer was too small for the colName.", func);
}
}
/*
* CONCISE(SQL) TYPE
*/
if (pfSqlType) {
*pfSqlType = opensearchtype_to_concise_type(stmt, fieldtype, icol,
unknown_sizes);
MYLOG(OPENSEARCH_DEBUG, "col %d *pfSqlType = %d\n", icol, *pfSqlType);
}
/*
* COLUMN SIZE(PRECISION in 2.x)
*/
if (pcbColDef) {
if (column_size < 0)
column_size = 0; /* "I dont know" */
*pcbColDef = column_size;
MYLOG(OPENSEARCH_DEBUG, "Col: col %d *pcbColDef = " FORMAT_ULEN "\n", icol,
*pcbColDef);
}
/*
* DECIMAL DIGITS(SCALE in 2.x)
*/
if (pibScale) {
if (decimal_digits < 0)
decimal_digits = 0;
*pibScale = (SQLSMALLINT)decimal_digits;
MYLOG(OPENSEARCH_DEBUG, "col %d *pibScale = %d\n", icol, *pibScale);
}
/*
* NULLABILITY
*/
if (pfNullable) {
if (SC_has_outer_join(stmt))
*pfNullable = TRUE;
else
*pfNullable = fi ? fi->nullable : opensearchtype_nullable(conn, fieldtype);
MYLOG(OPENSEARCH_DEBUG, "col %d *pfNullable = %d\n", icol, *pfNullable);
}
cleanup:
#undef return
return result;
}