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

📄 qresult.c

📁 postgresql-odbc,跨平台应用
💻 C
📖 第 1 页 / 共 3 页
字号:
	 * more rows so don't call next_tuple again!	 */	if (conn != NULL)	{		ConnInfo   *ci = &(conn->connInfo);		BOOL		fetch_cursor = (cursor && cursor[0]);		QR_set_conn(self, conn);		mylog("%s: cursor = '%s', self->cursor=%p\n", func, (cursor == NULL) ? "" : cursor, QR_get_cursor(self));		if (cursor && !cursor[0])			cursor = NULL;		if (fetch_cursor)		{			if (!cursor)			{				QR_set_rstatus(self, PORES_INTERNAL_ERROR);				QR_set_message(self, "Internal Error -- no cursor for fetch");				return FALSE;			}		}		QR_set_cursor(self, cursor);		/*		 * Read the field attributes.		 *		 * $$$$ Should do some error control HERE! $$$$		 */		if (CI_read_fields(self->fields, QR_get_conn(self)))		{			QR_set_rstatus(self, PORES_FIELDS_OK);			self->num_fields = CI_get_num_fields(self->fields);			if (QR_haskeyset(self))				self->num_fields -= self->num_key_fields;		}		else		{			QR_set_rstatus(self, PORES_BAD_RESPONSE);			QR_set_message(self, "Error reading field information");			return FALSE;		}		mylog("%s: past CI_read_fields: num_fields = %d\n", func, self->num_fields);		if (fetch_cursor)		{			if (self->cache_size <= 0)				self->cache_size = ci->drivers.fetch_max;			tuple_size = self->cache_size;		}		else			tuple_size = TUPLE_MALLOC_INC;		/* allocate memory for the tuple cache */		mylog("MALLOC: tuple_size = %d, size = %d\n", tuple_size, self->num_fields * sizeof(TupleField) * tuple_size);		self->count_backend_allocated = self->count_keyset_allocated = 0;		if (self->num_fields > 0)		{			QR_MALLOC_return_with_error(self->backend_tuples, TupleField, self->num_fields * sizeof(TupleField) * tuple_size, self, "Could not get memory for tuple cache.", FALSE);			self->count_backend_allocated = tuple_size;		}		if (QR_haskeyset(self))		{			if (self->keyset = (KeySet *) calloc(sizeof(KeySet), tuple_size), !self->keyset)			{				QR_set_rstatus(self, PORES_FATAL_ERROR);				QR_set_message(self, "Could not get memory for tuple cache.");				return FALSE;			}			self->count_keyset_allocated = tuple_size;		}		QR_set_fetching_tuples(self);		/* Force a read to occur in next_tuple */		QR_set_num_cached_rows(self, 0);		QR_set_next_in_cache(self, 0);		QR_set_rowstart_in_cache(self, 0);		self->key_base = 0;		return QR_next_tuple(self, NULL);	}	else	{		/*		 * Always have to read the field attributes. But we dont have to		 * reallocate memory for them!		 */		if (!CI_read_fields(NULL, QR_get_conn(self)))		{			QR_set_rstatus(self, PORES_BAD_RESPONSE);			QR_set_message(self, "Error reading field information");			return FALSE;		}		return TRUE;	}}/* *	Close the cursor and end the transaction (if no cursors left) *	We only close the cursor if other cursors are used. */intQR_close(QResultClass *self){	ConnectionClass	*conn;	QResultClass *res;	int	ret = TRUE;	conn = QR_get_conn(self);	if (self && QR_get_cursor(self))	{		if (CC_is_in_error_trans(conn))		{			if (QR_is_withhold(self))				CC_mark_a_object_to_discard(conn, 'p', QR_get_cursor(self));		}		else		{			UDWORD		flag = ROLLBACK_ON_ERROR | IGNORE_ABORT_ON_CONN;			char		buf[64];			snprintf(buf, sizeof(buf), "close \"%s\"", QR_get_cursor(self));			/* End the transaction if there are no cursors left on this conn */			if (CC_is_in_autocommit(conn) && CC_cursor_count(conn) <= 1)			{				mylog("QResult: END transaction on conn=%p\n", conn);				strncat(buf, ";commit", sizeof(buf));				flag |= END_WITH_COMMIT;			}			res = CC_send_query(conn, buf, NULL, flag, NULL);			QR_Destructor(res);		}		QR_set_no_fetching_tuples(self);		self->cursTuple = -1;		QR_set_cursor(self, NULL);		if (!ret)			return ret;#ifdef	NOT_USED		/* End the transaction if there are no cursors left on this conn */		if (CC_is_in_autocommit(conn) && CC_cursor_count(conn) == 0)		{			mylog("QResult: END transaction on conn=%p\n", conn);			if (!CC_commit(conn))			{				QR_set_rstatus(self, PORES_FATAL_ERROR);				QR_set_message(self, "Error ending transaction.");				ret = FALSE;			}		}#endif /* NOT_USED */	}	return ret;}BOOLQR_get_tupledata(QResultClass *self, BOOL binary){	BOOL	haskeyset = QR_haskeyset(self);	SQLULEN num_total_rows = QR_get_num_total_tuples(self);inolog("QR_get_tupledata num_fields=%d\n", self->num_fields);	if (!QR_get_cursor(self))	{ 		if (self->num_fields > 0 &&		    num_total_rows >= self->count_backend_allocated)		{			SQLLEN	tuple_size = self->count_backend_allocated;			mylog("REALLOC: old_count = %d, size = %d\n", tuple_size, self->num_fields * sizeof(TupleField) * tuple_size);			if (tuple_size < 1)				tuple_size = TUPLE_MALLOC_INC;			else				tuple_size *= 2;			QR_REALLOC_return_with_error(self->backend_tuples, TupleField, tuple_size * self->num_fields * sizeof(TupleField), self, "Out of memory while reading tuples.", FALSE);			self->count_backend_allocated = tuple_size;		}		if (haskeyset &&		    self->num_cached_keys >= self->count_keyset_allocated)		{			SQLLEN	tuple_size = self->count_keyset_allocated;			if (tuple_size < 1)				tuple_size = TUPLE_MALLOC_INC;			else				tuple_size *= 2;			QR_REALLOC_return_with_error(self->keyset, KeySet, sizeof(KeySet) * tuple_size, self, "Out of mwmory while allocating keyset", FALSE);			self->count_keyset_allocated = tuple_size;		}	}	if (!QR_read_a_tuple_from_db(self, (char) binary))	{		QR_set_rstatus(self, PORES_BAD_RESPONSE);		QR_set_message(self, "Error reading the tuple");		return FALSE;	}inolog("!!%p->cursTup=%d total_read=%d\n", self, self->cursTuple, self->num_total_read);	if (!QR_once_reached_eof(self) && self->cursTuple >= (Int4) self->num_total_read)		self->num_total_read = self->cursTuple + 1;inolog("!!cursTup=%d total_read=%d\n", self->cursTuple, self->num_total_read);	if (self->num_fields > 0)	{		QR_inc_num_cache(self);	}	else if (haskeyset)		self->num_cached_keys++;	return TRUE;}static SQLLEN enlargeKeyCache(QResultClass *self, SQLLEN add_size, const char *message){	size_t	alloc, alloc_req;	Int4	num_fields = self->num_fields;	BOOL	curs = (NULL != QR_get_cursor(self));	if (add_size <= 0)		return self->count_keyset_allocated;	alloc = self->count_backend_allocated;	if (num_fields > 0 && ((alloc_req = (Int4)self->num_cached_rows + add_size) > alloc || !self->backend_tuples))	{		if (1 > alloc)		{			if (curs)				alloc = alloc_req;			else				alloc = (alloc_req > TUPLE_MALLOC_INC ? alloc_req : TUPLE_MALLOC_INC);		}		else		{			do			{ 				alloc *= 2;			} while (alloc < alloc_req);		}		self->count_backend_allocated = 0;		QR_REALLOC_return_with_error(self->backend_tuples, TupleField, num_fields * sizeof(TupleField) * alloc, self, message, -1);		self->count_backend_allocated = alloc;	}	alloc = self->count_keyset_allocated;	if (QR_haskeyset(self) && ((alloc_req = (Int4)self->num_cached_keys + add_size) > alloc || !self->keyset))	{		if (1 > alloc)		{			if (curs)				alloc = alloc_req;			else				alloc = (alloc_req > TUPLE_MALLOC_INC ? alloc_req : TUPLE_MALLOC_INC);		}		else		{			do			{ 				alloc *= 2;			} while (alloc < alloc_req);		}		self->count_keyset_allocated = 0;		QR_REALLOC_return_with_error(self->keyset, KeySet, sizeof(KeySet) * alloc, self, message, -1); 		self->count_keyset_allocated = alloc;	}	return alloc;}/*	This function is called by fetch_tuples() AND SQLFetch() */intQR_next_tuple(QResultClass *self, StatementClass *stmt){	CSTR	func = "QR_next_tuple";	int			id, ret = TRUE;	SocketClass *sock;	/* Speed up access */	SQLLEN		fetch_number = self->fetch_number, cur_fetch = 0;	SQLLEN		num_total_rows;	SQLLEN		num_backend_rows = self->num_cached_rows, num_rows_in;	Int4		num_fields = self->num_fields, fetch_size, req_size;	SQLLEN		offset = 0, end_tuple;	char		boundary_adjusted = FALSE;	TupleField *the_tuples = self->backend_tuples;	/* ERROR_MSG_LENGTH is sufficient */	char msgbuffer[ERROR_MSG_LENGTH + 1];	/* QR_set_command() dups this string so doesn't need static */	char		cmdbuffer[ERROR_MSG_LENGTH + 1];	char		fetch[128];	QueryInfo	qi;	ConnectionClass	*conn;	ConnInfo   *ci = NULL;	BOOL		msg_truncated, rcvend, internally_invoked = FALSE;	BOOL		reached_eof_now = FALSE, curr_eof; /* detecting EOF is pretty important */	BOOL		ExecuteRequest = FALSE;	Int4		response_length;inolog("Oh %p->fetch_number=%d\n", self, self->fetch_number);inolog("in total_read=%d cursT=%d currT=%d ad=%d total=%d rowsetSize=%d\n", self->num_total_read, self->cursTuple, stmt ? stmt->currTuple : -1, self->ad_count, QR_get_num_total_tuples(self), self->rowset_size_include_ommitted);	num_total_rows = QR_get_num_total_tuples(self);	conn = QR_get_conn(self);	curr_eof = FALSE;	req_size = self->rowset_size_include_ommitted;	if (QR_once_reached_eof(self) && self->cursTuple >= (Int4) QR_get_num_total_read(self))		curr_eof = TRUE;	if (0 != self->move_offset)	{		char		movecmd[256];		QResultClass	*mres;		SQLULEN		movement, moved;		movement = self->move_offset;		if (QR_is_moving_backward(self))		{			if (self->cache_size > req_size)			{				SQLLEN	incr_move = self->cache_size - (req_size < 0 ? 1 : req_size);								movement += incr_move;				if (movement > (UInt4)(self->cursTuple + 1))					movement = self->cursTuple + 1;			}			else				self->cache_size = req_size;inolog("cache=%d rowset=%d movement=" FORMAT_ULEN "\n", self->cache_size, req_size, movement);			sprintf(movecmd, "move backward " FORMAT_ULEN " in \"%s\"", movement, QR_get_cursor(self));		}		else if (QR_is_moving_forward(self))			sprintf(movecmd, "move " FORMAT_ULEN " in \"%s\"", movement, QR_get_cursor(self));		else		{			sprintf(movecmd, "move all in \"%s\"", QR_get_cursor(self));			movement = INT_MAX;		}		mres = CC_send_query(conn, movecmd, NULL, 0, stmt);		if (!QR_command_maybe_successful(mres))		{			QR_Destructor(mres);			if (stmt)				SC_set_error(stmt, STMT_EXEC_ERROR, "move error occured", func);			return -1;		}		moved = movement;		if (sscanf(mres->command, "MOVE %lu", &moved) > 0)		{inolog("moved=%d ? " FORMAT_ULEN "\n", moved, movement);        		if (moved < movement)			{				if (0 <  moved)					moved++;				else if (QR_is_moving_backward(self) && self->cursTuple < 0)					;				else if (QR_is_moving_not_backward(self) && curr_eof)					;				else					moved++;				if (QR_is_moving_not_backward(self))				{					curr_eof = TRUE;					if (!QR_once_reached_eof(self))					{						self->num_total_read = self->cursTuple + moved;						QR_set_reached_eof(self);					}				}				if (QR_is_moving_from_the_last(self))  /* in case of FETCH LAST */				{					SQLULEN	bmovement, mback;					SQLLEN	rowset_start = self->cursTuple + 1, back_offset = self->move_offset, backpt;inolog("FETCH LAST case\n");					if (getNthValid(self, QR_get_num_total_tuples(self) - 1, SQL_FETCH_PRIOR, self->move_offset, &backpt) < 0)					{						/* the rowset_start is on BOF */						self->tupleField = NULL;						SC_set_rowset_start(stmt, -1, TRUE);						stmt->currTuple = -1;						return -1;					}					back_offset = QR_get_num_total_tuples(self) - backpt;inolog("back_offset=%d and move_offset=%d\n", back_offset, self->move_offset);					if (back_offset + 1 > (Int4) self->ad_count)					{						bmovement = back_offset + 1 - self->ad_count;						sprintf(movecmd, "move backward " FORMAT_ULEN " in \"%s\"", bmovement, QR_get_cursor(self));						QR_Destructor(mres);						mres = CC_send_query(conn, movecmd, NULL, 0, stmt);						if (!QR_command_maybe_successful(mres))						{							QR_Destructor(mres);							if (stmt)								SC_set_error(stmt, STMT_EXEC_ERROR, "move error occured", func);							return -1;						}						if (sscanf(mres->command, "MOVE %lu", &mback) > 0)						{							if (mback < bmovement)								mback++;							if (moved < mback)							{								QR_set_move_backward(self);								mback -= moved;								moved = mback;								self->move_offset = moved;								rowset_start = self->cursTuple - moved + 1;							}							else							{								QR_set_move_forward(self);								moved-= mback;								self->move_offset = moved;								rowset_start = self->cursTuple + moved + 1;							}						}					}					else					{						QR_set_move_forward(self);						self->move_offset = moved + self->ad_count - back_offset - 1;						rowset_start = self->cursTuple +self->move_offset + 1;						/* adjust move_offset */						/*** self->move_offset++; ***/					}					if (stmt)					{						SC_set_rowset_start(stmt, rowset_start, TRUE); /* affects the result's rowset_start but it is reset immediately ... */						stmt->currTuple = RowIdx2GIdx(-1, stmt);					}				}			}		}		/* ... by the following call */ 		QR_set_rowstart_in_cache(self, -1);		if (QR_is_moving_backward(self))		{			self->cursTuple -= moved;			offset = moved - self->move_offset;		}		else		{			self->cursTuple += moved;			offset = self->move_offset - moved;		}		QR_Destructor(mres);		self->move_offset = 0;		num_backend_rows = self->num_cached_rows;	}	else if (fetch_number < num_backend_rows)	{		/* return a row from cache */		mylog("%s: fetch_number < fcount: returning tuple %d, fcount = %d\n", func, fetch_number, num_backend_rows);		self->tupleField = the_tuples + (fetch_number * num_fields);inolog("tupleField=%p\n", self->tupleField);		/* move to next row */		QR_inc_next_in_cache(self);		return TRUE;	}	else if (QR_once_reached_eof(self))	{		BOOL	reached_eod = FALSE;		SQLULEN	num_total_read = self->num_total_read;		if (stmt)		{			if (stmt->currTuple + 1 >= num_total_rows)				reached_eod = TRUE;		}		else if (self->cursTuple + 1 >= (Int4)num_total_read)		{			if (self->ad_count == 0)				reached_eod = TRUE;		}		if (reached_eod)		{			mylog("next_tuple: fetch end\n");			self->tupleField = NULL;			/* end of tuples */			return -1;		}	}	end_tuple = req_size + QR_get_rowstart_in_cache(self);	/*	 * See if we need to fetch another group of rows. We may be being	 * called from send_query(), and if so, don't send another fetch,	 * just fall through and read the tuples.	 */	self->tupleField = NULL;	fetch_size = 0;	if (!QR_is_fetching_tuples(self))	{		ci = &(conn->connInfo);		if (!QR_get_cursor(self))		{			mylog("%s: ALL_ROWS: done, fcount = %d, fetch_number = %d\n", func, QR_get_num_total_tuples(self), fetch_number);			self->tupleField = NULL;			QR_set_reached_eof(self);			return -1;		/* end of tuples */		}		if (QR_get_rowstart_in_cache(self) >= num_backend_rows ||		    QR_is_moving(self))

⌨️ 快捷键说明

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