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

📄 statement.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
}/* Pre-execute a statement (SQLPrepare/SQLDescribeCol) */void SC_pre_execute(StatementClass *self){	mylog("SC_pre_execute: status = %d\n", self->status);	if (self->status == STMT_READY) {		mylog("              preprocess: status = READY\n");		SQLExecute(self);		if (self->status == STMT_FINISHED) {			mylog("              preprocess: after status = FINISHED, so set PREMATURE\n");			self->status = STMT_PREMATURE;		}	}  }/* This is only called from SQLFreeStmt(SQL_UNBIND) */char SC_unbind_cols(StatementClass *self){Int2 lf;	for(lf = 0; lf < self->bindings_allocated; lf++) {		self->bindings[lf].data_left = -1;		self->bindings[lf].buflen = 0;		self->bindings[lf].buffer = NULL;		self->bindings[lf].used = NULL;		self->bindings[lf].returntype = SQL_C_CHAR;	}	self->bookmark.buffer = NULL;	self->bookmark.used = NULL;    return 1;}void SC_clear_error(StatementClass *self){	self->errornumber = 0;	self->errormsg = NULL;	self->errormsg_created = FALSE;}//	This function creates an error msg which is the concatenation//	of the result, statement, connection, and socket messages.char *SC_create_errormsg(StatementClass *self){QResultClass *res = self->result;ConnectionClass *conn = self->hdbc;int pos;static char msg[4096];	msg[0] = '\0';	if (res && res->message)		strcpy(msg, res->message);	else if (self->errormsg)		strcpy(msg, self->errormsg);	if (conn) {		SocketClass *sock = conn->sock;		if (conn->errormsg && conn->errormsg[0] != '\0') {			pos = strlen(msg);			sprintf(&msg[pos], ";\n%s", conn->errormsg);		}		if (sock && sock->errormsg && sock->errormsg[0] != '\0') {			pos = strlen(msg);			sprintf(&msg[pos], ";\n%s", sock->errormsg);		}	}	return msg;}char SC_get_error(StatementClass *self, int *number, char **message){char rv;	//	Create a very informative errormsg if it hasn't been done yet.	if ( ! self->errormsg_created) {		self->errormsg = SC_create_errormsg(self);		self->errormsg_created = TRUE;	}	if ( self->errornumber) {		*number = self->errornumber;		*message = self->errormsg;		self->errormsg = NULL;	}	rv = (self->errornumber != 0);	self->errornumber = 0;	return rv;}/*	Currently, the driver offers very simple bookmark support -- it is	just the current row number.  But it could be more sophisticated 	someday, such as mapping a key to a 32 bit value*/unsigned longSC_get_bookmark(StatementClass *self){	return (self->currTuple + 1);	}RETCODESC_fetch(StatementClass *self){static char *func = "SC_fetch";QResultClass *res = self->result;int retval, result;Int2 num_cols, lf;Oid type;char *value;ColumnInfoClass *ci;// TupleField *tupleField;	self->last_fetch_count = 0;	ci = QR_get_fields(res);		/* the column info */	mylog("manual_result = %d, use_declarefetch = %d\n", self->manual_result, globals.use_declarefetch); 	if ( self->manual_result || ! globals.use_declarefetch) {		if (self->currTuple >= QR_get_num_tuples(res) -1 || 			(self->options.maxRows > 0 && self->currTuple == self->options.maxRows - 1)) {			/*	if at the end of the tuples, return "no data found" 				and set the cursor past the end of the result set 			*/			self->currTuple = QR_get_num_tuples(res);				return SQL_NO_DATA_FOUND;		} 		mylog("**** SQLFetch: manual_result\n");		(self->currTuple)++;	}	else {		// read from the cache or the physical next tuple		retval = QR_next_tuple(res);		if (retval < 0) {			mylog("**** SQLFetch: end_tuples\n");			return SQL_NO_DATA_FOUND;		}		else if (retval > 0)			(self->currTuple)++;		// all is well		else {			mylog("SQLFetch: error\n");			self->errornumber = STMT_EXEC_ERROR;			self->errormsg = "Error fetching next row";			SC_log_error(func, "", self);			return SQL_ERROR;		}	}	num_cols = QR_NumResultCols(res);	result = SQL_SUCCESS;	self->last_fetch_count = 1;	/*	If the bookmark column was bound then return a bookmark.		Since this is used with SQLExtendedFetch, and the rowset size 		may be greater than 1, and an application can use row or column wise		binding, use the code in copy_and_convert_field() to handle that.	*/	if (self->bookmark.buffer) {		char buf[32];		sprintf(buf, "%ld", SC_get_bookmark(self));		result = copy_and_convert_field(self, 0, buf, 								SQL_C_ULONG, self->bookmark.buffer, 0, self->bookmark.used);	}	for (lf=0; lf < num_cols; lf++) {		mylog("fetch: cols=%d, lf=%d, self = %u, self->bindings = %u, buffer[] = %u\n", num_cols, lf, self, self->bindings, self->bindings[lf].buffer);		/*	reset for SQLGetData */		self->bindings[lf].data_left = -1;		if (self->bindings[lf].buffer != NULL) {            // this column has a binding            // type = QR_get_field_type(res, lf);			type = CI_get_oid(ci, lf);		/* speed things up */			mylog("type = %d\n", type);			if (self->manual_result) {				value = QR_get_value_manual(res, self->currTuple, lf);				mylog("manual_result\n");			}			else if (globals.use_declarefetch)				value = QR_get_value_backend(res, lf);			else {				value = QR_get_value_backend_row(res, self->currTuple, lf);			}			mylog("value = '%s'\n",  (value==NULL)?"<NULL>":value);			retval = copy_and_convert_field_bindinfo(self, type, value, lf);			mylog("copy_and_convert: retval = %d\n", retval);			switch(retval) {			case COPY_OK:				break;	/*	OK, do next bound column */			case COPY_UNSUPPORTED_TYPE:				self->errormsg = "Received an unsupported type from Postgres.";				self->errornumber = STMT_RESTRICTED_DATA_TYPE_ERROR;				SC_log_error(func, "", self);				result = SQL_ERROR;				break;			case COPY_UNSUPPORTED_CONVERSION:				self->errormsg = "Couldn't handle the necessary data type conversion.";				self->errornumber = STMT_RESTRICTED_DATA_TYPE_ERROR;				SC_log_error(func, "", self);				result = SQL_ERROR;				break;			case COPY_RESULT_TRUNCATED:				self->errornumber = STMT_TRUNCATED;				self->errormsg = "The buffer was too small for the result.";				result = SQL_SUCCESS_WITH_INFO;				break;			case COPY_GENERAL_ERROR:	/* error msg already filled in */				SC_log_error(func, "", self);				result = SQL_ERROR;				break;			/*  This would not be meaningful in SQLFetch. */			case COPY_NO_DATA_FOUND:				break;			default:				self->errormsg = "Unrecognized return value from copy_and_convert_field.";				self->errornumber = STMT_INTERNAL_ERROR;				SC_log_error(func, "", self);				result = SQL_ERROR;				break;			}		}	}	return result;}RETCODE SC_execute(StatementClass *self){static char *func="SC_execute";ConnectionClass *conn;QResultClass *res;char ok, was_ok, was_nonfatal;Int2 oldstatus, numcols;QueryInfo qi;	conn = SC_get_conn(self);	/*	Begin a transaction if one is not already in progress */	/*	The reason is because we can't use declare/fetch cursors without		starting a transaction first.	*/	if ( ! self->internal && ! CC_is_in_trans(conn) && (globals.use_declarefetch || STMT_UPDATE(self))) {		mylog("   about to begin a transaction on statement = %u\n", self);		res = CC_send_query(conn, "BEGIN", NULL);		if ( ! res) {			self->errormsg = "Could not begin a transaction";			self->errornumber = STMT_EXEC_ERROR;			SC_log_error(func, "", self);			return SQL_ERROR;		}				ok = QR_command_successful(res);   				mylog("SQLExecute: ok = %d, status = %d\n", ok, QR_get_status(res));				QR_Destructor(res);				if (!ok) {			self->errormsg = "Could not begin a transaction";			self->errornumber = STMT_EXEC_ERROR;			SC_log_error(func, "", self);			return SQL_ERROR;		}		else			CC_set_in_trans(conn);	}	oldstatus = conn->status;	conn->status = CONN_EXECUTING;	self->status = STMT_EXECUTING;	//	If its a SELECT statement, use a cursor.	//	Note that the declare cursor has already been prepended to the statement	//	in copy_statement...	if (self->statement_type == STMT_TYPE_SELECT) {		char fetch[128];		mylog("       Sending SELECT statement on stmt=%u, cursor_name='%s'\n", self, self->cursor_name);		/*	send the declare/select */		self->result = CC_send_query(conn, self->stmt_with_params, NULL);		if (globals.use_declarefetch && self->result != NULL) {			QR_Destructor(self->result);			/*	That worked, so now send the fetch to start getting data back */			qi.result_in = NULL;			qi.cursor = self->cursor_name;			qi.row_size = globals.fetch_max;			/*	Most likely the rowset size will not be set by the application until 				after the statement	is executed, so might as well use the cache size.  				The qr_next_tuple() function will correct for any discrepancies in 				sizes and adjust the cache accordingly.			*/			sprintf(fetch, "fetch %d in %s", qi.row_size, self->cursor_name);						self->result = CC_send_query( conn, fetch, &qi);		}		mylog("     done sending the query:\n");			}	else  { // not a SELECT statement so don't use a cursor 		 		mylog("      its NOT a select statement: stmt=%u\n", self);		self->result = CC_send_query(conn, self->stmt_with_params, NULL);				//	If we are in autocommit, we must send the commit.		if ( ! self->internal && CC_is_in_autocommit(conn) && STMT_UPDATE(self)) {			CC_send_query(conn, "COMMIT", NULL);			CC_set_no_trans(conn);		}			}	conn->status = oldstatus;	self->status = STMT_FINISHED;	/*	Check the status of the result */	if (self->result) {		was_ok = QR_command_successful(self->result);		was_nonfatal = QR_command_nonfatal(self->result);				if ( was_ok)			self->errornumber = STMT_OK;		else			self->errornumber = was_nonfatal ? STMT_INFO_ONLY : STMT_ERROR_TAKEN_FROM_BACKEND;				self->currTuple = -1; /* set cursor before the first tuple in the list */		self->current_col = -1;		self->rowset_start = -1;				/* see if the query did return any result columns */		numcols = QR_NumResultCols(self->result);				/* now allocate the array to hold the binding info */		if (numcols > 0) {			extend_bindings(self, numcols);			if (self->bindings == NULL) {				self->errornumber = STMT_NO_MEMORY_ERROR;				self->errormsg = "Could not get enough free memory to store the binding information";				SC_log_error(func, "", self);				return SQL_ERROR;			}		}			} else {		/* Bad Error -- The error message will be in the Connection */		if (self->statement_type == STMT_TYPE_CREATE) {			self->errornumber = STMT_CREATE_TABLE_ERROR;			self->errormsg = "Error creating the table";			/*	This would allow the table to already exists, thus appending				rows to it.  BUT, if the table didn't have the same attributes,				it would fail.				return SQL_SUCCESS_WITH_INFO;			*/		}		else {			self->errornumber = STMT_EXEC_ERROR;			self->errormsg = "Error while executing the query";		}		if ( ! self->internal)			CC_abort(conn);	}	if (self->errornumber == STMT_OK)		return SQL_SUCCESS;	else if (self->errornumber == STMT_INFO_ONLY)		return SQL_SUCCESS_WITH_INFO;	else {		SC_log_error(func, "", self);		return SQL_ERROR;	}}voidSC_log_error(char *func, char *desc, StatementClass *self){	if (self) {		qlog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, self->errormsg);		mylog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, self->errormsg);		qlog("                 ------------------------------------------------------------\n");		qlog("                 hdbc=%u, stmt=%u, result=%u\n", self->hdbc, self, self->result);		qlog("                 manual_result=%d, prepare=%d, internal=%d\n", self->manual_result, self->prepare, self->internal);		qlog("                 bindings=%u, bindings_allocated=%d\n", self->bindings, self->bindings_allocated);		qlog("                 parameters=%u, parameters_allocated=%d\n", self->parameters, self->parameters_allocated);		qlog("                 statement_type=%d, statement='%s'\n", self->statement_type, self->statement);		qlog("                 stmt_with_params='%s'\n", self->stmt_with_params);		qlog("                 data_at_exec=%d, current_exec_param=%d, put_data=%d\n", self->data_at_exec, self->current_exec_param, self->put_data);		qlog("                 currTuple=%d, current_col=%d, lobj_fd=%d\n", self->currTuple, self->current_col, self->lobj_fd);		qlog("                 maxRows=%d, rowset_size=%d, keyset_size=%d, cursor_type=%d, scroll_concurrency=%d\n", self->options.maxRows, self->options.rowset_size, self->options.keyset_size, self->options.cursor_type, self->options.scroll_concurrency);		qlog("                 cursor_name='%s'\n", self->cursor_name);		qlog("                 ----------------QResult Info -------------------------------\n");		if (self->result) {		QResultClass *res = self->result;		qlog("                 fields=%u, manual_tuples=%u, backend_tuples=%u, tupleField=%d, conn=%u\n", res->fields, res->manual_tuples, res->backend_tuples, res->tupleField, res->conn);		qlog("                 fetch_count=%d, fcount=%d, num_fields=%d, cursor='%s'\n", res->fetch_count, res->fcount, res->num_fields, res->cursor);		qlog("                 message='%s', command='%s', notice='%s'\n", res->message, res->command, res->notice);		qlog("                 status=%d, inTuples=%d\n", res->status, res->inTuples);		}			//	Log the connection error if there is one		CC_log_error(func, desc, self->hdbc);	}	else		qlog("INVALID STATEMENT HANDLE ERROR: func=%s, desc='%s'\n", func, desc);}

⌨️ 快捷键说明

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