connection.c

来自「postgresql-odbc,跨平台应用」· C语言 代码 · 共 2,634 行 · 第 1/5 页

C
2,634
字号
		mylog("CC_commit:  sending COMMIT!\n");		ret = QR_command_maybe_successful(res);		QR_Destructor(res);	}	return ret;}/* *	Used to cancel a transaction. *	We are almost always in the middle of a transaction. */charCC_abort(ConnectionClass *self){	char	ret = TRUE;	if (CC_is_in_trans(self))	{		QResultClass *res = CC_send_query(self, rbkcmd, NULL, 0, NULL);		mylog("CC_abort:  sending ABORT!\n");		ret = QR_command_maybe_successful(res);		QR_Destructor(res);	}	return ret;}/* This is called by SQLSetConnectOption etc also */charCC_set_autocommit(ConnectionClass *self, BOOL on){	CSTR func = "CC_set_autocommit";	BOOL currsts = CC_is_in_autocommit(self);	if ((on && currsts) ||	    (!on && !currsts))		return on;	mylog("%s: %d->%d\n", func, currsts, on);	if (CC_is_in_trans(self))		CC_commit(self);	if (on)		self->transact_status |= CONN_IN_AUTOCOMMIT;	else		self->transact_status &= ~CONN_IN_AUTOCOMMIT;	return on;}/* This is called by SQLDisconnect also */charCC_cleanup(ConnectionClass *self){	int			i;	StatementClass *stmt;	DescriptorClass *desc;	if (self->status == CONN_EXECUTING)		return FALSE;	mylog("in CC_Cleanup, self=%p\n", self);	/* Cancel an ongoing transaction */	/* We are always in the middle of a transaction, */	/* even if we are in auto commit. */	if (self->sock)	{		CC_abort(self);		mylog("after CC_abort\n");		/* This actually closes the connection to the dbase */		SOCK_Destructor(self->sock);		self->sock = NULL;	}	mylog("after SOCK destructor\n");	/* Free all the stmts on this connection */	for (i = 0; i < self->num_stmts; i++)	{		stmt = self->stmts[i];		if (stmt)		{			stmt->hdbc = NULL;	/* prevent any more dbase interactions */			SC_Destructor(stmt);			self->stmts[i] = NULL;		}	}#if (ODBCVER >= 0x0300)	/* Free all the descs on this connection */	for (i = 0; i < self->num_descs; i++)	{		desc = self->descs[i];		if (desc)		{			DC_get_conn(desc) = NULL;	/* prevent any more dbase interactions */			DC_Destructor(desc);			free(desc);			self->descs[i] = NULL;		}	}#endif /* ODBCVER */	/* Check for translation dll */#ifdef WIN32	if (self->translation_handle)	{		FreeLibrary(self->translation_handle);		self->translation_handle = NULL;	}#endif	self->status = CONN_NOT_CONNECTED;	self->transact_status = CONN_IN_AUTOCOMMIT;	CC_conninfo_init(&(self->connInfo));	if (self->original_client_encoding)	{		free(self->original_client_encoding);		self->original_client_encoding = NULL;	}	if (self->current_client_encoding)	{		free(self->current_client_encoding);		self->current_client_encoding = NULL;	}	if (self->server_encoding)	{		free(self->server_encoding);		self->server_encoding = NULL;	}	reset_current_schema(self);	/* Free cached table info */	if (self->col_info)	{		for (i = 0; i < self->ntables; i++)		{			if (self->col_info[i]->result)	/* Free the SQLColumns result structure */				QR_Destructor(self->col_info[i]->result);			NULL_THE_NAME(self->col_info[i]->schema_name);			NULL_THE_NAME(self->col_info[i]->table_name);			free(self->col_info[i]);		}		free(self->col_info);		self->col_info = NULL;	}	self->ntables = 0;	self->coli_allocated = 0;	if (self->num_discardp > 0 && self->discardp)	{		for (i = 0; i < self->num_discardp; i++)			free(self->discardp[i]);		self->num_discardp = 0;	}	if (self->discardp)	{		free(self->discardp);		self->discardp = NULL;	}	mylog("exit CC_Cleanup\n");	return TRUE;}intCC_set_translation(ConnectionClass *self){#ifdef WIN32	CSTR	func = "CC_set_translation";	if (self->translation_handle != NULL)	{		FreeLibrary(self->translation_handle);		self->translation_handle = NULL;	}	if (self->connInfo.translation_dll[0] == 0)		return TRUE;	self->translation_option = atoi(self->connInfo.translation_option);	self->translation_handle = LoadLibrary(self->connInfo.translation_dll);	if (self->translation_handle == NULL)	{		CC_set_error(self, CONN_UNABLE_TO_LOAD_DLL, "Could not load the translation DLL.", func);		return FALSE;	}	self->DataSourceToDriver		= (DataSourceToDriverProc) GetProcAddress(self->translation_handle,												"SQLDataSourceToDriver");	self->DriverToDataSource		= (DriverToDataSourceProc) GetProcAddress(self->translation_handle,												"SQLDriverToDataSource");	if (self->DataSourceToDriver == NULL || self->DriverToDataSource == NULL)	{		CC_set_error(self, CONN_UNABLE_TO_LOAD_DLL, "Could not find translation DLL functions.", func);		return FALSE;	}#endif	return TRUE;}static	intmd5_auth_send(ConnectionClass *self, const char *salt){	char	*pwd1 = NULL, *pwd2 = NULL;	ConnInfo   *ci = &(self->connInfo);	SocketClass	*sock = self->sock;	size_t		md5len;inolog("md5 pwd=%s user=%s salt=%02x%02x%02x%02x%02x\n", ci->password, ci->username, (UCHAR)salt[0], (UCHAR)salt[1], (UCHAR)salt[2], (UCHAR)salt[3], (UCHAR)salt[4]);	if (!(pwd1 = malloc(MD5_PASSWD_LEN + 1)))		return 1;	if (!EncryptMD5(ci->password, ci->username, strlen(ci->username), pwd1))	{		free(pwd1);		return 1;	} 	if (!(pwd2 = malloc(MD5_PASSWD_LEN + 1)))	{		free(pwd1);		return 1;	} 	if (!EncryptMD5(pwd1 + strlen("md5"), salt, 4, pwd2))	{		free(pwd2);		free(pwd1);		return 1;	}	free(pwd1);	if (PROTOCOL_74(&(self->connInfo))){inolog("putting p and %s\n", pwd2);		SOCK_put_char(sock, 'p');}	md5len = strlen(pwd2);	SOCK_put_int(sock, (Int4) (4 + md5len + 1), 4);	SOCK_put_n_char(sock, pwd2, (Int4) (md5len + 1));	SOCK_flush_output(sock);inolog("sockerr=%d\n", SOCK_get_errcode(sock));	free(pwd2);	return 0; }intEatReadyForQuery(ConnectionClass *conn){	int	id = 0;	if (PROTOCOL_74(&(conn->connInfo)))	{		BOOL	is_in_error_trans = CC_is_in_error_trans(conn);		switch (id = SOCK_get_char(conn->sock))		{			case 'I':				if (CC_is_in_trans(conn))				{					if (is_in_error_trans)						CC_on_abort(conn, NO_TRANS);					else						CC_on_commit(conn);				}				break;			case 'T':				CC_set_in_trans(conn);				CC_set_no_error_trans(conn);				if (is_in_error_trans)					CC_on_abort_partial(conn);				break;			case 'E':				CC_set_in_error_trans(conn);				break;			}	}	return id;	}inthandle_error_message(ConnectionClass *self, char *msgbuf, size_t buflen, char *sqlstate, const char *comment, QResultClass *res){	BOOL	new_format = FALSE, msg_truncated = FALSE, truncated, hasmsg = FALSE;	SocketClass	*sock = self->sock;	char	msgbuffer[ERROR_MSG_LENGTH];	UDWORD	abort_opt;inolog("handle_error_message prptocol=%s\n", self->connInfo.protocol);	if (PROTOCOL_74(&(self->connInfo)))		new_format = TRUE;inolog("new_format=%d\n", new_format);	if (new_format)	{		size_t	msgl;		msgbuf[0] = '\0';		for (;;)		{			truncated = SOCK_get_string(sock, msgbuffer, sizeof(msgbuffer));			if (!msgbuffer[0])				break;			mylog("%s: 'E' - %s\n", comment, msgbuffer);			qlog("ERROR from backend during %s: '%s'\n", comment, msgbuffer);			msgl = strlen(msgbuffer + 1);			switch (msgbuffer[0])			{				case 'S':					if (buflen > 0)					{						strncat(msgbuf, msgbuffer + 1, buflen);						buflen -= msgl;					}					if (buflen > 0)					{						strncat(msgbuf, ": ", buflen);						buflen -= 2;					}					break;				case 'M':				case 'D':					if (buflen > 0)					{						if (hasmsg)						{							strcat(msgbuf, "\n");							buflen--;						}						if (buflen > 0)						{							strncat(msgbuf, msgbuffer + 1, buflen);							buflen -= msgl;						}					}					if (truncated)						msg_truncated = truncated;					hasmsg = TRUE;					break;				case 'C':					if (sqlstate)						strncpy(sqlstate, msgbuffer + 1, 8);					break;			}			if (buflen < 0)				buflen = 0;			while (truncated)				truncated = SOCK_get_string(sock, msgbuffer, sizeof(msgbuffer));		}	}	else	{		msg_truncated = SOCK_get_string(sock, msgbuf, (Int4) buflen);		/* Remove a newline */		if (msgbuf[0] != '\0' && msgbuf[(int)strlen(msgbuf) - 1] == '\n')			msgbuf[(int)strlen(msgbuf) - 1] = '\0';		mylog("%s: 'E' - %s\n", comment, msgbuf);		qlog("ERROR from backend during %s: '%s'\n", comment, msgbuf);		for (truncated = msg_truncated; truncated;)			truncated = SOCK_get_string(sock, msgbuffer, sizeof(msgbuffer));	}	abort_opt = 0;	if (!strncmp(msgbuffer, "FATAL", 5))	{		CC_set_errornumber(self, CONNECTION_SERVER_REPORTED_ERROR);		abort_opt = CONN_DEAD;	}	else	{		CC_set_errornumber(self, CONNECTION_SERVER_REPORTED_WARNING);		if (CC_is_in_trans(self))			CC_set_in_error_trans(self);	}	if (0 != abort_opt#ifdef	_LEGACY_MODE_	    || TRUE#endif /* _LEGACY_NODE_ */	   )		CC_on_abort(self, abort_opt);	if (res)	{		QR_set_rstatus(res, PORES_FATAL_ERROR);		QR_set_message(res, msgbuf);		QR_set_aborted(res, TRUE);	}	return msg_truncated;}inthandle_notice_message(ConnectionClass *self, char *msgbuf, size_t buflen, char *sqlstate, const char *comment, QResultClass *res){	BOOL	new_format = FALSE, msg_truncated = FALSE, truncated, hasmsg = FALSE;	SocketClass	*sock = self->sock;	char	msgbuffer[ERROR_MSG_LENGTH];	if (PROTOCOL_74(&(self->connInfo)))		new_format = TRUE;	if (new_format)	{		size_t	msgl;		msgbuf[0] = '\0';		for (;;)		{			truncated = SOCK_get_string(sock, msgbuffer, sizeof(msgbuffer));			if (!msgbuffer[0])				break;			mylog("%s: 'N' - %s\n", comment, msgbuffer);			qlog("NOTICE from backend during %s: '%s'\n", comment, msgbuffer);			msgl = strlen(msgbuffer + 1);			switch (msgbuffer[0])			{				case 'S':					if (buflen > 0)					{						strncat(msgbuf, msgbuffer + 1, buflen);						buflen -= msgl;					}					if (buflen > 0)					{						strncat(msgbuf, ": ", buflen);						buflen -= 2;					}					break;				case 'M':				case 'D':					if (buflen > 0)					{						if (hasmsg)						{							strcat(msgbuf, "\n");							buflen--;						}						if (buflen > 0)						{							strncat(msgbuf, msgbuffer + 1, buflen);							buflen -= msgl;						}					}					else						msg_truncated = TRUE;					if (truncated)						msg_truncated = truncated;					hasmsg = TRUE;					break;				case 'C':					if (sqlstate && !sqlstate[0] && strcmp(msgbuffer + 1, "00000"))						strncpy(sqlstate, msgbuffer + 1, 8);					break;			}			if (buflen < 0)				msg_truncated = TRUE;			while (truncated)				truncated = SOCK_get_string(sock, msgbuffer, sizeof(msgbuffer));		}	}	else	{		msg_truncated = SOCK_get_string(sock, msgbuf, (Int4) buflen);		/* Remove a newline */		if (msgbuf[0] != '\0' && msgbuf[strlen(msgbuf) - 1] == '\n')			msgbuf[strlen(msgbuf) - 1] = '\0';		mylog("%s: 'N' - %s\n", comment, msgbuf);		qlog("NOTICE from backend during %s: '%s'\n", comment, msgbuf);		for (truncated = msg_truncated; truncated;)			truncated = SOCK_get_string(sock, msgbuffer, sizeof(msgbuffer));	}	if (res)	{		if (QR_command_successful(res))			QR_set_rstatus(res, PORES_NONFATAL_ERROR);		QR_set_notice(res, msgbuf);  /* will dup this string */	}	return msg_truncated;}CSTR std_cnf_strs = "standard_conforming_strings";void	getParameterValues(ConnectionClass *conn){	SocketClass	*sock = conn->sock;	/* ERROR_MSG_LENGTH is suffcient */	char msgbuffer[ERROR_MSG_LENGTH + 1];		SOCK_get_string(sock, msgbuffer, sizeof(msgbuffer));inolog("parameter name=%s\n", msgbuffer);	if (stricmp(msgbuffer, "server_encoding") == 0)	{		SOCK_get_string(sock, msgbuffer, sizeof(msgbuffer));		if (conn->server_encoding)			free(conn->server_encoding);		conn->server_encoding = strdup(msgbuffer);	}	else if (stricmp(msgbuffer, "client_encoding") == 0)	{		SOCK_get_string(sock, msgbuffer, sizeof(msgbuffer));		if (conn->current_client_encoding)			free(conn->current_client_encoding);		conn->current_client_encoding = strdup(msgbuffer);	}	else if (stricmp(msgbuffer, std_cnf_strs) == 0)	{		SOCK_get_string(sock, msgbuffer, sizeof(msgbuffer));		if (stricmp(msgbuffer, "on") == 0)		{			mylog("%s=%s\n", std_cnf_strs, msgbuffer); 			conn->escape_in_literal = '\0';		}	}	else if (stricmp(msgbuffer, "server_version") == 0)	{		char	szVersion[32];		int	major, minor;

⌨️ 快捷键说明

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