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

📄 results.c

📁 postgresql-odbc,跨平台应用
💻 C
📖 第 1 页 / 共 5 页
字号:
			/*			 * From the odbc spec... If positioned after the end of the			 * RESULT SET, then this should be equivalent to			 * SQL_FETCH_LAST.			 */			if (SC_get_rowset_start(stmt) <= 0)			{				EXTFETCH_RETURN_BOF(stmt, res)			}			if (SC_get_rowset_start(stmt) >= num_tuples)			{				if (rowsetSize > num_tuples)				{					SC_set_error(stmt, STMT_POS_BEFORE_RECORDSET, "fetch prior from eof and before the beginning", func);				}				SC_set_rowset_start(stmt, num_tuples <= 0 ? 0 : (num_tuples - rowsetSize), TRUE);			}			else if (QR_haskeyset(res))			{				if (i = getNthValid(res, SC_get_rowset_start(stmt) - 1, SQL_FETCH_PRIOR, rowsetSize, &rowset_start), i < -1)				{					SC_set_error(stmt, STMT_POS_BEFORE_RECORDSET, "fetch prior and before the beggining", func);					SC_set_rowset_start(stmt, 0, TRUE);				}				else if (i <= 0)				{					EXTFETCH_RETURN_BOF(stmt, res)				}				else					should_set_rowset_start = TRUE;			}			else if (SC_get_rowset_start(stmt) < rowsetSize)			{				SC_set_error(stmt, STMT_POS_BEFORE_RECORDSET, "fetch prior from eof and before the beggining", func);				SC_set_rowset_start(stmt, 0, TRUE);			}			else				SC_inc_rowset_start(stmt, -rowsetSize);			break;		case SQL_FETCH_FIRST:			mylog("SQL_FETCH_FIRST: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple);			SC_set_rowset_start(stmt, 0, TRUE);			break;		case SQL_FETCH_LAST:			mylog("SQL_FETCH_LAST: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple);			if (!reached_eof)			{				QR_set_move_from_the_last(res);				res->move_offset = rowsetSize;			}			SC_set_rowset_start(stmt, num_tuples <= 0 ? 0 : (num_tuples - rowsetSize), TRUE);			break;		case SQL_FETCH_ABSOLUTE:			mylog("SQL_FETCH_ABSOLUTE: num_tuples=%d, currtuple=%d, irow=%d\n", num_tuples, stmt->currTuple, irow);			/* Position before result set, but dont fetch anything */			if (irow == 0)			{				EXTFETCH_RETURN_BOF(stmt, res)			}			/* Position before the desired row */			else if (irow > 0)			{				if (getNthValid(res, 0, SQL_FETCH_NEXT, irow, &rowset_start) <= 0)				{					EXTFETCH_RETURN_EOF(stmt, res)				}				else					should_set_rowset_start = TRUE;			}			/* Position with respect to the end of the result set */			else			{				if (getNthValid(res, num_tuples - 1, SQL_FETCH_PRIOR, -irow, &rowset_start) <= 0)				{					EXTFETCH_RETURN_BOF(stmt, res)				}				else				{					if (!reached_eof)					{						QR_set_move_from_the_last(res);						res->move_offset = -irow;					}					should_set_rowset_start = TRUE;				}			}			break;		case SQL_FETCH_RELATIVE:			/*			 * Refresh the current rowset -- not currently implemented,			 * but lie anyway			 */			if (irow == 0)				break;			if (irow > 0)			{				if (getNthValid(res, SC_get_rowset_start(stmt) + 1, SQL_FETCH_NEXT, irow, &rowset_start) <= 0)				{					EXTFETCH_RETURN_EOF(stmt, res)				}				else					should_set_rowset_start = TRUE;			}			else			{				if (getNthValid(res, SC_get_rowset_start(stmt) - 1, SQL_FETCH_PRIOR, -irow, &rowset_start) <= 0)				{					EXTFETCH_RETURN_BOF(stmt, res)				}				else					should_set_rowset_start = TRUE;			}			break;		case SQL_FETCH_BOOKMARK:			{			SQLLEN	bidx = SC_resolve_bookmark(irow);			if (bidx < 0)			{				if (!reached_eof)				{					QR_set_move_from_the_last(res);					res->move_offset = 1 + res->ad_count + bidx;				}				bidx = num_tuples - 1 - res->ad_count - bidx;			} 			rowset_start = bidx;			if (bookmark_offset >= 0)			{				if (getNthValid(res, bidx, SQL_FETCH_NEXT, bookmark_offset + 1, &rowset_start) <= 0)				{					EXTFETCH_RETURN_EOF(stmt, res)				}				else					should_set_rowset_start = TRUE;			}			else if (getNthValid(res, bidx, SQL_FETCH_PRIOR, 1 - bookmark_offset, &rowset_start) <= 0)			{				stmt->currTuple = -1;				EXTFETCH_RETURN_BOF(stmt, res)			}			else				should_set_rowset_start = TRUE;			}			break;		default:			SC_set_error(stmt, STMT_FETCH_OUT_OF_RANGE, "Unsupported PGAPI_ExtendedFetch Direction", func);			return SQL_ERROR;	}	/*	 * CHECK FOR PROPER CURSOR STATE	 */	/*	 * Handle Declare Fetch style specially because the end is not really	 * the end...	 */	if (!should_set_rowset_start)		rowset_start = SC_get_rowset_start(stmt);	if (SC_is_fetchcursor(stmt))	{		if (reached_eof &&		    rowset_start >= num_tuples)		{			EXTFETCH_RETURN_EOF(stmt, res)		}	}	else	{		/* If *new* rowset is after the result_set, return no data found */		if (rowset_start >= num_tuples)		{			EXTFETCH_RETURN_EOF(stmt, res)		}	}	/* If *new* rowset is prior to result_set, return no data found */	if (rowset_start < 0)	{		if (rowset_start + rowsetSize <= 0)		{			EXTFETCH_RETURN_BOF(stmt, res)		}		else		{	/* overlap with beginning of result set,			 * so get first rowset */			SC_set_rowset_start(stmt, 0, TRUE);		}		should_set_rowset_start = FALSE;	}#define	return DONT_CALL_RETURN_FROM_HERE???	/* increment the base row in the tuple cache */	QR_set_rowset_size(res, (Int4) rowsetSize);	/* set the rowset_start if needed */	if (should_set_rowset_start)		SC_set_rowset_start(stmt, rowset_start, TRUE);	/* currTuple is always 1 row prior to the rowset start */	stmt->currTuple = RowIdx2GIdx(-1, stmt);	if (SC_is_fetchcursor(stmt) ||	    SQL_CURSOR_KEYSET_DRIVEN == stmt->options.cursor_type)	{		move_cursor_position_if_needed(stmt, res);	}	else		QR_set_rowstart_in_cache(res, SC_get_rowset_start(stmt));	if (res->keyset && !QR_get_cursor(res))	{		UDWORD	flag = 0;		SQLLEN	rowset_end, req_size;		getNthValid(res, rowset_start, SQL_FETCH_NEXT, rowsetSize, &rowset_end);		req_size = rowset_end - rowset_start + 1;		if (SQL_CURSOR_KEYSET_DRIVEN == stmt->options.cursor_type)		{			if (fFetchType != SQL_FETCH_NEXT ||		    		QR_get_rowstart_in_cache(res) + req_size > QR_get_num_cached_tuples(res))				flag = 1;		}		if (SQL_RD_ON == stmt->options.retrieve_data ||		    flag != 0)		{			SC_pos_reload_needed(stmt, req_size, flag);		}	}	/* Physical Row advancement occurs for each row fetched below */	mylog("PGAPI_ExtendedFetch: new currTuple = %d\n", stmt->currTuple);	truncated = error = FALSE;	currp = -1;	stmt->bind_row = 0;		/* set the binding location */	result = SC_fetch(stmt);	if (SQL_ERROR == result)		goto cleanup;	if (SQL_NO_DATA_FOUND != result && res->keyset)	{		currp = GIdx2KResIdx(SC_get_rowset_start(stmt), stmt, res);inolog("currp=%d\n", currp);		if (currp < 0)		{			result = SQL_ERROR;			mylog("rowset_start=%d but currp=%d\n", SC_get_rowset_start(stmt), currp);			SC_set_error(stmt, STMT_INTERNAL_ERROR, "rowset_start not in the keyset", func);			goto cleanup;		}	}	for (i = 0, fc_io = 0; SQL_NO_DATA_FOUND != result && SQL_ERROR != result; currp++)	{		fc_io++;		currp_is_valid = FALSE;		if (res->keyset)		{			if (currp < res->num_cached_keys)			{				currp_is_valid = TRUE;				res->keyset[currp].status &= ~CURS_IN_ROWSET; /* Off the flag first */			}			else			{				mylog("Umm current row is out of keyset\n");				break;			}		}inolog("ExtFetch result=%d\n", result);		if (currp_is_valid && SQL_SUCCESS_WITH_INFO == result && 0 == stmt->last_fetch_count)		{inolog("just skipping deleted row %d\n", currp);			QR_set_rowset_size(res, (Int4) (rowsetSize - i + fc_io));			result = SC_fetch(stmt);			if (SQL_ERROR == result)				break;			continue;		}		/* Determine Function status */		if (result == SQL_SUCCESS_WITH_INFO)			truncated = TRUE;		else if (result == SQL_ERROR)			error = TRUE;		/* Determine Row Status */		if (rgfRowStatus)		{			if (result == SQL_ERROR)				*(rgfRowStatus + i) = SQL_ROW_ERROR;			else if (currp_is_valid)			{				pstatus = (res->keyset[currp].status & KEYSET_INFO_PUBLIC);				if (pstatus != 0 && pstatus != SQL_ROW_ADDED)				{					rgfRowStatus[i] = pstatus;				}				else					rgfRowStatus[i] = SQL_ROW_SUCCESS;				/* refresh the status */				/* if (SQL_ROW_DELETED != pstatus) */				res->keyset[currp].status &= (~KEYSET_INFO_PUBLIC);			}			else				*(rgfRowStatus + i) = SQL_ROW_SUCCESS;		}		if (SQL_ERROR != result && currp_is_valid)			res->keyset[currp].status |= CURS_IN_ROWSET; /* This is the unique place where the CURS_IN_ROWSET bit is turned on */		i++;		if (i >= rowsetSize)			break;		stmt->bind_row = (SQLSETPOSIROW) i; /* set the binding location */		result = SC_fetch(stmt);	}	if (SQL_ERROR == result)		goto cleanup;	/* Save the fetch count for SQLSetPos */	stmt->last_fetch_count = i;	/*	currp = KResIdx2GIdx(currp, stmt, res);	stmt->last_fetch_count_include_ommitted = GIdx2RowIdx(currp, stmt);	*/	stmt->last_fetch_count_include_ommitted = fc_io;	/* Reset next binding row */	stmt->bind_row = 0;	/* Move the cursor position to the first row in the result set. */	stmt->currTuple = RowIdx2GIdx(0, stmt);	/* For declare/fetch, need to reset cursor to beginning of rowset */	if (SC_is_fetchcursor(stmt))		QR_set_position(res, 0);	/* Set the number of rows retrieved */	if (pcrow)		*pcrow = i;inolog("pcrow=%d\n", i);	if (i == 0)		/* Only DeclareFetch should wind up here */		result = SQL_NO_DATA_FOUND;	else if (error)		result = SQL_ERROR;	else if (truncated)		result = SQL_SUCCESS_WITH_INFO;	else if (SC_get_errornumber(stmt) == STMT_POS_BEFORE_RECORDSET)		result = SQL_SUCCESS_WITH_INFO;	else		result = SQL_SUCCESS;cleanup:#undef	return	if (stmt->internal)		result = DiscardStatementSvp(stmt, result, FALSE);	return result;}/* *		This determines whether there are more results sets available for *		the "hstmt". *//* CC: return SQL_NO_DATA_FOUND since we do not support multiple result sets */RETCODE		SQL_APIPGAPI_MoreResults(				  HSTMT hstmt){	CSTR func = "PGAPI_MoreResults";	StatementClass	*stmt = (StatementClass *) hstmt;	QResultClass	*res;	RETCODE		ret = SQL_SUCCESS;	mylog("%s: entering...\n", func);	if (stmt && (res = SC_get_Curres(stmt)))		SC_set_Curres(stmt, res->next);	if (res = SC_get_Curres(stmt), res)	{		SQLSMALLINT	num_p;		if (stmt->multi_statement < 0)			PGAPI_NumParams(stmt, &num_p);		if (stmt->multi_statement > 0)		{ 			const char *cmdstr;			SC_initialize_cols_info(stmt, FALSE, TRUE);			stmt->statement_type = STMT_TYPE_UNKNOWN;			if (cmdstr = QR_get_command(res), NULL != cmdstr)				stmt->statement_type = statement_type(cmdstr);			stmt->join_info = 0;			SC_clear_parse_method(stmt);		}		stmt->diag_row_count = res->recent_processed_row_count;		SC_set_rowset_start(stmt, -1, FALSE);		stmt->currTuple = -1;	}	else	{		PGAPI_FreeStmt(hstmt, SQL_CLOSE);		ret = SQL_NO_DATA_FOUND;	}	mylog("%s: returning %d\n", func, ret);	return ret;}/* *	Stuff for updatable cursors. */static Int2	getNumResultCols(const QResultClass *res){	Int2	res_cols = QR_NumPublicResultCols(res);	return res_cols;}static OID	getOid(const QResultClass *res, SQLLEN index){	return res->keyset[index].oid;}static void getTid(const QResultClass *res, SQLLEN index, UInt4 *blocknum, UInt2 *offset){	*blocknum = res->keyset[index].blocknum;	*offset = res->keyset[index].offset;}static void KeySetSet(const TupleField *tuple, int num_fields, int num_key_fields, KeySet *keyset){	sscanf(tuple[num_fields - num_key_fields].value, "(%u,%hu)",			&keyset->blocknum, &keyset->offset);	if (num_key_fields > 1)		sscanf(tuple[num_fields - 1].value, "%u", &keyset->oid);	else		keyset->oid = 0;}static void AddRollback(StatementClass *stmt, QResultClass *res, SQLLEN index, const KeySet *keyset, Int4 dmlcode){	ConnectionClass	*conn = SC_get_conn(stmt);	Rollback *rollback;	if (!CC_is_in_trans(conn))		return;inolog("AddRollback %d(%d,%d) %s\n", index, keyset->blocknum, keyset->offset, dmlcode == SQL_ADD ? "ADD" : (dmlcode == SQL_UPDATE ? "UPDATE" : (dmlcode == SQL_DELETE ? "DELETE" : "REFRESH")));	if (!res->rollback)	{		res->rb_count = 0;		res->rb_alloc = 10;		rollback = res->rollback = malloc(sizeof(Rollback) * res->rb_alloc);	}	else	{		if (res->rb_count >= res->rb_alloc)		{			res->rb_alloc *= 2; 			if (rollback = realloc(res->rollback, sizeof(Rollback) * res->rb_alloc), !rollback)			{				res->rb_alloc = res->rb_count = 0;				return;			}			res->rollback = rollback; 		}		rollback = res->rollback + res->rb_count;	}	rollback->index = index;	rollback->option = dmlcode;	rollback->offset = 0;	rollback->blocknum = 0;	if (keyset)	{		rollback->blocknum = keyset->blocknum;		rollback->offset = keyset->offset;	}	conn->result_uncommitted = 1;	res->rb_count++;	}SQLLEN ClearCachedRows(TupleField *tuple, int num_fields, SQLLEN num_rows){	SQLLEN	i;	for (i = 0; i < num_fields * num_rows; i++, tuple++)	{		if (tuple->value)		{inolog("freeing tuple[%d][%d].value=%p\n", i / num_fields, i % num_fields, tuple->value);			free(tuple->value);			tuple->value = NULL;		}		tuple->len = -1;	}	return i;}SQLLEN ReplaceCachedRows(TupleField *otuple, const TupleField *ituple, int num_fields, SQLLEN num_rows){	SQLLEN	i;

⌨️ 快捷键说明

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