📄 results.c
字号:
/* Module: results.c * * Description: This module contains functions related to * retrieving result information through the ODBC API. * * Classes: n/a * * API functions: SQLRowCount, SQLNumResultCols, SQLDescribeCol, SQLColAttributes, * SQLGetData, SQLFetch, SQLExtendedFetch, * SQLMoreResults(NI), SQLSetPos, SQLSetScrollOptions(NI), * SQLSetCursorName, SQLGetCursorName * * Comments: See "notice.txt" for copyright and license information. * */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <string.h>#include "psqlodbc.h"#include "dlg_specific.h"#include "environ.h"#include "connection.h"#include "statement.h"#include "bind.h"#include "qresult.h"#include "convert.h"#include "pgtypes.h" #include <stdio.h>#ifndef WIN32#include "iodbc.h"#include "isqlext.h"#else#include <windows.h>#include <sqlext.h>#endifextern GLOBAL_VALUES globals;RETCODE SQL_API SQLRowCount( HSTMT hstmt, SDWORD FAR *pcrow){static char *func="SQLRowCount";StatementClass *stmt = (StatementClass *) hstmt;QResultClass *res;char *msg, *ptr; if ( ! stmt) { SC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } if (stmt->manual_result) { if (pcrow) *pcrow = -1; return SQL_SUCCESS; } if(stmt->statement_type == STMT_TYPE_SELECT) { if (stmt->status == STMT_FINISHED) { res = SC_get_Result(stmt); if(res && pcrow) { *pcrow = globals.use_declarefetch ? -1 : QR_get_num_tuples(res); return SQL_SUCCESS; } } } else { res = SC_get_Result(stmt); if (res && pcrow) { msg = QR_get_command(res); mylog("*** msg = '%s'\n", msg); trim(msg); // get rid of trailing spaces ptr = strrchr(msg, ' '); if (ptr) { *pcrow = atoi(ptr+1); mylog("**** SQLRowCount(): THE ROWS: *pcrow = %d\n", *pcrow); } else { *pcrow = -1; mylog("**** SQLRowCount(): NO ROWS: *pcrow = %d\n", *pcrow); } return SQL_SUCCESS; } } SC_log_error(func, "Bad return value", stmt); return SQL_ERROR; }// This returns the number of columns associated with the database// attached to "hstmt".RETCODE SQL_API SQLNumResultCols( HSTMT hstmt, SWORD FAR *pccol){ static char *func="SQLNumResultCols";StatementClass *stmt = (StatementClass *) hstmt;QResultClass *result;char parse_ok; if ( ! stmt) { SC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } SC_clear_error(stmt); parse_ok = FALSE; if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT) { if (stmt->parse_status == STMT_PARSE_NONE) { mylog("SQLNumResultCols: calling parse_statement on stmt=%u\n", stmt); parse_statement(stmt); } if (stmt->parse_status != STMT_PARSE_FATAL) { parse_ok = TRUE; *pccol = stmt->nfld; mylog("PARSE: SQLNumResultCols: *pccol = %d\n", *pccol); } } if ( ! parse_ok) { SC_pre_execute(stmt); result = SC_get_Result(stmt); mylog("SQLNumResultCols: result = %u, status = %d, numcols = %d\n", result, stmt->status, result != NULL ? QR_NumResultCols(result) : -1); if (( ! result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)) ) { /* no query has been executed on this statement */ stmt->errornumber = STMT_SEQUENCE_ERROR; stmt->errormsg = "No query has been executed with that handle"; SC_log_error(func, "", stmt); return SQL_ERROR; } *pccol = QR_NumResultCols(result); } return SQL_SUCCESS;}// - - - - - - - - -// Return information about the database column the user wants// information about.RETCODE SQL_API SQLDescribeCol( HSTMT hstmt, UWORD icol, UCHAR FAR *szColName, SWORD cbColNameMax, SWORD FAR *pcbColName, SWORD FAR *pfSqlType, UDWORD FAR *pcbColDef, SWORD FAR *pibScale, SWORD FAR *pfNullable){static char *func="SQLDescribeCol"; /* gets all the information about a specific column */StatementClass *stmt = (StatementClass *) hstmt;QResultClass *res;char *col_name = NULL;Int4 fieldtype = 0;int precision = 0;ConnInfo *ci;char parse_ok;char buf[255];int len = 0;RETCODE result; mylog("%s: entering...\n", func); if ( ! stmt) { SC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } ci = &(stmt->hdbc->connInfo); SC_clear_error(stmt); /* Dont check for bookmark column. This is the responsibility of the driver manager. */ icol--; /* use zero based column numbers */ parse_ok = FALSE; if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT) { if (stmt->parse_status == STMT_PARSE_NONE) { mylog("SQLDescribeCol: calling parse_statement on stmt=%u\n", stmt); parse_statement(stmt); } mylog("PARSE: DescribeCol: icol=%d, stmt=%u, stmt->nfld=%d, stmt->fi=%u\n", icol, stmt, stmt->nfld, stmt->fi); if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol]) { if (icol >= stmt->nfld) { stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR; stmt->errormsg = "Invalid column number in DescribeCol."; SC_log_error(func, "", stmt); return SQL_ERROR; } mylog("DescribeCol: getting info for icol=%d\n", icol); fieldtype = stmt->fi[icol]->type; col_name = stmt->fi[icol]->name; precision = stmt->fi[icol]->precision; mylog("PARSE: fieldtype=%d, col_name='%s', precision=%d\n", fieldtype, col_name, precision); if (fieldtype > 0) parse_ok = TRUE; } } /* If couldn't parse it OR the field being described was not parsed (i.e., because it was a function or expression, etc, then do it the old fashioned way. */ if ( ! parse_ok) { SC_pre_execute(stmt); res = SC_get_Result(stmt); mylog("**** SQLDescribeCol: res = %u, stmt->status = %d, !finished=%d, !premature=%d\n", res, stmt->status, stmt->status != STMT_FINISHED, stmt->status != STMT_PREMATURE); if ( (NULL == res) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE))) { /* no query has been executed on this statement */ stmt->errornumber = STMT_SEQUENCE_ERROR; stmt->errormsg = "No query has been assigned to this statement."; SC_log_error(func, "", stmt); return SQL_ERROR; } if (icol >= QR_NumResultCols(res)) { stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR; stmt->errormsg = "Invalid column number in DescribeCol."; sprintf(buf, "Col#=%d, #Cols=%d", icol, QR_NumResultCols(res)); SC_log_error(func, buf, stmt); return SQL_ERROR; } col_name = QR_get_fieldname(res, icol); fieldtype = QR_get_field_type(res, icol); precision = pgtype_precision(stmt, fieldtype, icol, globals.unknown_sizes); // atoi(ci->unknown_sizes) } mylog("describeCol: col %d fieldname = '%s'\n", icol, col_name); mylog("describeCol: col %d fieldtype = %d\n", icol, fieldtype); mylog("describeCol: col %d precision = %d\n", icol, precision); result = SQL_SUCCESS; /************************/ /* COLUMN NAME */ /************************/ len = strlen(col_name); if (pcbColName) *pcbColName = len; if (szColName) { strncpy_null(szColName, col_name, cbColNameMax); if (len >= cbColNameMax) { result = SQL_SUCCESS_WITH_INFO; stmt->errornumber = STMT_TRUNCATED; stmt->errormsg = "The buffer was too small for the result."; } } /************************/ /* SQL TYPE */ /************************/ if (pfSqlType) { *pfSqlType = pgtype_to_sqltype(stmt, fieldtype); mylog("describeCol: col %d *pfSqlType = %d\n", icol, *pfSqlType); } /************************/ /* PRECISION */ /************************/ if (pcbColDef) { if ( precision < 0) precision = 0; // "I dont know" *pcbColDef = precision; mylog("describeCol: col %d *pcbColDef = %d\n", icol, *pcbColDef); } /************************/ /* SCALE */ /************************/ if (pibScale) { Int2 scale; scale = pgtype_scale(stmt, fieldtype); if(scale == -1) { scale = 0; } *pibScale = scale; mylog("describeCol: col %d *pibScale = %d\n", icol, *pibScale); } /************************/ /* NULLABILITY */ /************************/ if (pfNullable) { *pfNullable = (parse_ok) ? stmt->fi[icol]->nullable : pgtype_nullable(stmt, fieldtype); mylog("describeCol: col %d *pfNullable = %d\n", icol, *pfNullable); } return result;}// Returns result column descriptor information for a result set.RETCODE SQL_API SQLColAttributes( HSTMT hstmt, UWORD icol, UWORD fDescType, PTR rgbDesc, SWORD cbDescMax, SWORD FAR *pcbDesc, SDWORD FAR *pfDesc){static char *func = "SQLColAttributes";StatementClass *stmt = (StatementClass *) hstmt;Int4 field_type = 0;ConnInfo *ci;int unknown_sizes;int cols = 0;char parse_ok;RETCODE result;char *p = NULL;int len = 0, value = 0; mylog("%s: entering...\n", func); if( ! stmt) { SC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } ci = &(stmt->hdbc->connInfo); /* Dont check for bookmark column. This is the responsibility of the driver manager. For certain types of arguments, the column number is ignored anyway, so it may be 0. */ icol--; unknown_sizes = globals.unknown_sizes; // atoi(ci->unknown_sizes); if (unknown_sizes == UNKNOWNS_AS_DONTKNOW) // not appropriate for SQLColAttributes() unknown_sizes = UNKNOWNS_AS_MAX; parse_ok = FALSE; if (globals.parse && stmt->statement_type == STMT_TYPE_SELECT) { if (stmt->parse_status == STMT_PARSE_NONE) { mylog("SQLColAttributes: calling parse_statement\n"); parse_statement(stmt); } cols = stmt->nfld; /* Column Count is a special case. The Column number is ignored in this case. */ if (fDescType == SQL_COLUMN_COUNT) { if (pfDesc) *pfDesc = cols; return SQL_SUCCESS; } if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol]) { if (icol >= cols) { stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR; stmt->errormsg = "Invalid column number in DescribeCol."; SC_log_error(func, "", stmt); return SQL_ERROR; } field_type = stmt->fi[icol]->type; if (field_type > 0) parse_ok = TRUE; } } if ( ! parse_ok) { SC_pre_execute(stmt); mylog("**** SQLColAtt: result = %u, status = %d, numcols = %d\n", stmt->result, stmt->status, stmt->result != NULL ? QR_NumResultCols(stmt->result) : -1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -