⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 results.c

📁 postgresql-odbc,跨平台应用
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * 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, SQLSetPos, SQLSetScrollOptions(NI), *					SQLSetCursorName, SQLGetCursorName * * Comments:		See "notice.txt" for copyright and license information. *------- */#include "psqlodbc.h"#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>#include <limits.h>#include "pgapifunc.h"RETCODE		SQL_APIPGAPI_RowCount(			   HSTMT hstmt,			   SQLLEN FAR * pcrow){	CSTR func = "PGAPI_RowCount";	StatementClass *stmt = (StatementClass *) hstmt;	QResultClass *res;	ConnInfo   *ci;	mylog("%s: entering...\n", func);	if (!stmt)	{		SC_log_error(func, NULL_STRING, NULL);		return SQL_INVALID_HANDLE;	}	ci = &(SC_get_conn(stmt)->connInfo);	if (stmt->proc_return > 0)	{		if (pcrow){			*pcrow = 0;inolog("returning RowCount=%d\n", *pcrow);}		return SQL_SUCCESS;	}	res = SC_get_Curres(stmt);	if (res && pcrow)	{		if (stmt->status != STMT_FINISHED)		{			SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Can't get row count while statement is still executing.", func);			return	SQL_ERROR;		}		if (res->recent_processed_row_count >= 0)		{			*pcrow = res->recent_processed_row_count;			mylog("**** %s: THE ROWS: *pcrow = %d\n", func, *pcrow);			return SQL_SUCCESS;		}		else if (QR_NumResultCols(res) > 0)		{			*pcrow = SC_is_fetchcursor(stmt) ? -1 : QR_get_num_total_tuples(res) - res->dl_count;			mylog("RowCount=%d\n", *pcrow);			return SQL_SUCCESS;		}	}	*pcrow = -1;	return SQL_SUCCESS;}static BOOL SC_pre_execute_ok(StatementClass *stmt, BOOL build_fi, int col_idx, const char *func){	Int2 num_fields = SC_pre_execute(stmt);	QResultClass	*result = SC_get_Curres(stmt);	BOOL	exec_ok = TRUE;	mylog("%s: result = %p, status = %d, numcols = %d\n", func, result, stmt->status, result != NULL ? QR_NumResultCols(result) : -1);	/****if ((!result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE))) ****/	if (!QR_command_maybe_successful(result) || num_fields < 0)	{		/* no query has been executed on this statement */		SC_set_error(stmt, STMT_EXEC_ERROR, "No query has been executed with that handle", func);		exec_ok = FALSE;	}	else if (col_idx >= 0 && col_idx < num_fields)	{		OID	reloid = QR_get_relid(result, col_idx);		IRDFields	*irdflds = SC_get_IRDF(stmt);		FIELD_INFO	*fi;		TABLE_INFO	*ti = NULL;inolog("build_fi=%d reloid=%u\n", build_fi, reloid);		if (build_fi && 0 != QR_get_attid(result, col_idx))			getCOLIfromTI(func, NULL, stmt, reloid, &ti);inolog("nfields=%d\n", irdflds->nfields);		if (irdflds->fi && col_idx < (int) irdflds->nfields)		{			fi = irdflds->fi[col_idx];			if (fi)			{				if (ti)				{					if (NULL == fi->ti)						fi->ti = ti;					if (!FI_is_applicable(fi)					    && 0 != (ti->flags & TI_COLATTRIBUTE))						fi->flag |= FIELD_COL_ATTRIBUTE;				}				fi->basetype = QR_get_field_type(result, col_idx);				if (0 == fi->columntype)					fi->columntype = fi->basetype;			}		}	}	return exec_ok;}/* *	This returns the number of columns associated with the database *	attached to "hstmt". */RETCODE		SQL_APIPGAPI_NumResultCols(					HSTMT hstmt,					SQLSMALLINT FAR * pccol){	CSTR func = "PGAPI_NumResultCols";	StatementClass *stmt = (StatementClass *) hstmt;	QResultClass *result;	char		parse_ok;	ConnInfo   *ci;	RETCODE		ret = SQL_SUCCESS;	mylog("%s: entering...\n", func);	if (!stmt)	{		SC_log_error(func, NULL_STRING, NULL);		return SQL_INVALID_HANDLE;	}	ci = &(SC_get_conn(stmt)->connInfo);	SC_clear_error(stmt);#define	return	DONT_CALL_RETURN_FROM_HERE???	/* StartRollbackState(stmt); */	if (stmt->proc_return > 0)	{		*pccol = 0;		goto cleanup;	}	parse_ok = FALSE;	if (!stmt->catalog_result && SC_is_parse_forced(stmt) && stmt->statement_type == STMT_TYPE_SELECT)	{		if (SC_parsed_status(stmt) == STMT_PARSE_NONE)		{			mylog("%s: calling parse_statement on stmt=%p\n", func, stmt);			parse_statement(stmt, FALSE);		}		if (SC_parsed_status(stmt) != STMT_PARSE_FATAL)		{			parse_ok = TRUE;			*pccol = SC_get_IRDF(stmt)->nfields;			mylog("PARSE: %s: *pccol = %d\n", func, *pccol);		}	}	if (!parse_ok)	{		if (!SC_pre_execute_ok(stmt, FALSE, -1, func))		{			ret = SQL_ERROR;			goto cleanup;		}		result = SC_get_Curres(stmt);		*pccol = QR_NumPublicResultCols(result);	}cleanup:#undef	return	if (stmt->internal)		ret = DiscardStatementSvp(stmt, ret, FALSE);	return ret;}/* *	Return information about the database column the user wants *	information about. */RETCODE		SQL_APIPGAPI_DescribeCol(				  HSTMT hstmt,				  SQLUSMALLINT icol,				  SQLCHAR FAR * szColName,				  SQLSMALLINT cbColNameMax,				  SQLSMALLINT FAR * pcbColName,				  SQLSMALLINT FAR * pfSqlType,				  SQLULEN FAR * pcbColDef,				  SQLSMALLINT FAR * pibScale,				  SQLSMALLINT FAR * pfNullable){	CSTR func = "PGAPI_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;	SQLINTEGER	decimal_digits = 0;	ConnInfo   *ci;	FIELD_INFO	*fi;	char		buf[255];	int			len = 0;	RETCODE		result = SQL_SUCCESS;	mylog("%s: entering.%d..\n", func, icol);	if (!stmt)	{		SC_log_error(func, NULL_STRING, NULL);		return SQL_INVALID_HANDLE;	}	conn = SC_get_conn(stmt);	ci = &(conn->connInfo);	SC_clear_error(stmt);#define	return	DONT_CALL_RETURN_FROM_HERE???	irdflds = SC_get_IRDF(stmt);#if (ODBCVER >= 0x0300)	if (0 == icol) /* bookmark column */	{		SQLSMALLINT	fType = stmt->options.use_bookmarks == SQL_UB_VARIABLE ? SQL_BINARY : SQL_INTEGER;inolog("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;	}#endif /* ODBCVER */	/*	 * 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) && !stmt->catalog_result && SC_is_parse_forced(stmt) && STMT_TYPE_SELECT == stmt->statement_type)	{		if (SC_parsed_status(stmt) == STMT_PARSE_NONE)		{			mylog("%s: calling parse_statement on stmt=%p\n", func, stmt);			parse_statement(stmt, FALSE);		}		mylog("PARSE: DescribeCol: icol=%d, stmt=%p, stmt->nfld=%d, stmt->fi=%p\n", icol, stmt, irdflds->nfields, irdflds->fi);		if (SC_parsed_status(stmt) != STMT_PARSE_FATAL && irdflds->fi)		{			if (icol < irdflds->nfields)				fi = irdflds->fi[icol];			else			{				SC_set_error(stmt, STMT_INVALID_COLUMN_NUMBER_ERROR, "Invalid column number in DescribeCol.", func);				result = SQL_ERROR;				goto cleanup;			}			mylog("DescribeCol: getting info for icol=%d\n", icol);		}	}	if (!FI_is_applicable(fi))	{		/*	 	 * 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.	 	 */		BOOL	build_fi = PROTOCOL_74(ci) && (NULL != pfNullable || NULL != pfSqlType);		fi = NULL;		if (!SC_pre_execute_ok(stmt, build_fi, icol, func))		{			result = SQL_ERROR;			goto cleanup;		}		res = SC_get_Curres(stmt);		if (icol >= QR_NumPublicResultCols(res))		{			SC_set_error(stmt, STMT_INVALID_COLUMN_NUMBER_ERROR, "Invalid column number in DescribeCol.", NULL);			snprintf(buf, sizeof(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];	}	if (FI_is_applicable(fi))	{		fieldtype = (conn->lobj_type == fi->columntype) ? fi->columntype : FI_type(fi);		if (NAME_IS_VALID(fi->column_alias))			col_name = GET_NAME(fi->column_alias);		else			col_name = GET_NAME(fi->column_name);		column_size = fi->column_size;		decimal_digits = fi->decimal_digits;		mylog("PARSE: fieldtype=%d, col_name='%s', column_size=%d\n", fieldtype, col_name, column_size);	}			else	{		col_name = QR_get_fieldname(res, icol);		fieldtype = QR_get_field_type(res, icol);		/* atoi(ci->unknown_sizes) */		column_size = pgtype_column_size(stmt, fieldtype, icol, ci->drivers.unknown_sizes);		decimal_digits = pgtype_decimal_digits(stmt, fieldtype, icol);	}	mylog("describeCol: col %d fieldname = '%s'\n", icol, col_name);	mylog("describeCol: col %d fieldtype = %d\n", icol, fieldtype);	mylog("describeCol: col %d column_size = %d\n", icol, column_size);	result = SQL_SUCCESS;	/*	 * COLUMN NAME	 */	len = (int) strlen(col_name);	if (pcbColName)		*pcbColName = len;	if (szColName && cbColNameMax > 0)	{		strncpy_null(szColName, col_name, cbColNameMax);		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 = pgtype_to_concise_type(stmt, fieldtype, icol);		mylog("describeCol: 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("describeCol: col %d  *pcbColDef = %d\n", icol, *pcbColDef);	}	/*	 * DECIMAL DIGITS(SCALE in 2.x)	 */	if (pibScale)	{		if (decimal_digits < 0)			decimal_digits = 0;		*pibScale = (SQLSMALLINT) decimal_digits;		mylog("describeCol: col %d  *pibScale = %d\n", icol, *pibScale);	}	/*	 * NULLABILITY	 */	if (pfNullable)	{		if (SC_has_outer_join(stmt))			*pfNullable = TRUE;		else			*pfNullable = fi ? fi->nullable : pgtype_nullable(stmt, fieldtype);		mylog("describeCol: col %d  *pfNullable = %d\n", icol, *pfNullable);	}cleanup:#undef	return	if (stmt->internal)		result = DiscardStatementSvp(stmt, result, FALSE);	return result;}/*		Returns result column descriptor information for a result set. */RETCODE		SQL_APIPGAPI_ColAttributes(					HSTMT hstmt,					SQLUSMALLINT icol,					SQLUSMALLINT fDescType,					PTR rgbDesc,					SQLSMALLINT cbDescMax,					SQLSMALLINT FAR * pcbDesc,					SQLLEN FAR * pfDesc){	CSTR func = "PGAPI_ColAttributes";	StatementClass *stmt = (StatementClass *) hstmt;	IRDFields	*irdflds;	OID		field_type = 0;	Int2		col_idx;	ConnectionClass	*conn;	ConnInfo	*ci;	int			unknown_sizes;	int			cols = 0;	RETCODE		result;	const char   *p = NULL;	SQLLEN		value = 0;	const	FIELD_INFO	*fi = NULL;	const	TABLE_INFO	*ti = NULL;	QResultClass	*res;	mylog("%s: entering..col=%d %d len=%d.\n", func, icol, fDescType,				cbDescMax);	if (!stmt)	{		SC_log_error(func, NULL_STRING, NULL);		return SQL_INVALID_HANDLE;	}	if (pcbDesc)		*pcbDesc = 0;	irdflds = SC_get_IRDF(stmt);	conn = SC_get_conn(stmt);	ci = &(conn->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.	 */	res = SC_get_Curres(stmt);#if (ODBCVER >= 0x0300)	if (0 == icol && SQL_DESC_COUNT != fDescType) /* bookmark column */	{inolog("answering bookmark info\n");		switch (fDescType)		{			case SQL_DESC_OCTET_LENGTH:				if (pfDesc)					*pfDesc = 4;				break;			case SQL_DESC_TYPE:				if (pfDesc)					*pfDesc = stmt->options.use_bookmarks == SQL_UB_VARIABLE ? SQL_BINARY : SQL_INTEGER;				break;		}		return SQL_SUCCESS;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -