connection.c

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

C
2,634
字号
							if (PROTOCOL_74(&(self->connInfo)))								SOCK_put_char(sock, 'p');							SOCK_put_int(sock, (Int4) (4 + strlen(ci->password) + 1), 4);							SOCK_put_n_char(sock, ci->password, (Int4) strlen(ci->password) + 1);							sockerr = SOCK_flush_output(sock);							mylog("past flush %dbytes\n", sockerr);							break;						case AUTH_REQ_CRYPT:							CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Password crypt authentication not supported", func);							return 0;						case AUTH_REQ_MD5:							mylog("in AUTH_REQ_MD5\n");							if (ci->password[0] == '\0')							{								CC_set_error(self, CONNECTION_NEED_PASSWORD, "A password is required for this connection.", func);								if (salt_para)									memcpy(salt_para, salt, sizeof(salt));								return -areq; /* need password */							}							if (md5_auth_send(self, salt))							{								CC_set_error(self, CONN_INVALID_AUTHENTICATION, "md5 hashing failed", func);								return 0;							}							break;						case AUTH_REQ_SCM_CREDS:							CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Unix socket credential authentication not supported", func);							return 0;						default:							CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Unknown authentication type", func);							return 0;					}					break;				case 'S': /* parameter status */					getParameterValues(self);					break;				case 'K':		/* Secret key (6.4 protocol) */					self->be_pid = SOCK_get_int(sock, 4);		/* pid */					self->be_key = SOCK_get_int(sock, 4);		/* key */					break;				case 'Z':		/* Backend is ready for new query (6.4) */					EatReadyForQuery(self);					ReadyForQuery = TRUE;					break;				case 'N':	/* Notices may come */					handle_notice_message(self, notice, sizeof(notice), self->sqlstate, "CC_connect", NULL);					break;				default:					snprintf(notice, sizeof(notice), "Unexpected protocol character='%c' during authentication", beresp);					CC_set_error(self, CONN_INVALID_AUTHENTICATION, notice, func);					return 0;			}			if (retry)			{	/* retry older version */				if (PROTOCOL_63(ci))					strncpy(ci->protocol, PG62, sizeof(ci->protocol));				else if (PROTOCOL_64(ci))					strncpy(ci->protocol, PG63, sizeof(ci->protocol));				else 					strncpy(ci->protocol, PG64, sizeof(ci->protocol));				SOCK_Destructor(sock);				self->sock = (SocketClass *) 0;				CC_initialize_pg_version(self);				goto another_version_retry;			}			/*			 * There were no ReadyForQuery responce before 6.4.			 */			if (beforeV2 && areq == AUTH_REQ_OK)				ReadyForQuery = TRUE;		} while (!ReadyForQuery);	}sockerr_proc:	if (0 != (sockerr = SOCK_get_errcode(sock)))	{		if (0 == CC_get_errornumber(self))		{			if (SOCKET_CLOSED == sockerr)				CC_set_error(self, CONN_INVALID_AUTHENTICATION, "Communication closed during authentication", func);			else				CC_set_error(self, CONN_INVALID_AUTHENTICATION, "Communication error during authentication", func);		}		return 0;	}	CC_clear_error(self);		/* clear any password error */	/*	 * send an empty query in order to find out whether the specified	 * database really exists on the server machine	 */	if (!PROTOCOL_74(ci))	{		mylog("sending an empty query...\n");		res = CC_send_query(self, " ", NULL, 0, NULL);		if (res == NULL ||		    (QR_get_rstatus(res) != PORES_EMPTY_QUERY &&		     QR_command_nonfatal(res)))		{			CC_set_error(self, CONNECTION_NO_SUCH_DATABASE, "The database does not exist on the server\nor user authentication failed.", func);			QR_Destructor(res);		return 0;		}		QR_Destructor(res);		mylog("empty query seems to be OK.\n");		/* 		 * Get the version number first so we can check it before		 * sending options that are now obsolete. DJP 21/06/2002		 */inolog("CC_lookup_pg_version\n");		CC_lookup_pg_version(self);	/* Get PostgreSQL version for						   SQLGetInfo use */		CC_setenv(self);	}	return 1;}	charCC_connect(ConnectionClass *self, char password_req, char *salt_para){	// StartupPacket sp;	// StartupPacket6_2 sp62;	// QResultClass *res;	// SocketClass *sock;	ConnInfo   *ci = &(self->connInfo);	// int			areq = -1;	// int			beresp;	// char		msgbuffer[ERROR_MSG_LENGTH];	// char		salt[5], notice[512];	CSTR		func = "CC_connect";	char	   ret;	// char	   *encoding;	// BOOL	startPacketReceived = FALSE;	mylog("%s: entering...\n", func);	mylog("sslmode=%s\n", self->connInfo.sslmode);	if (self->connInfo.sslmode[0] != 'd' ||	    self->connInfo.username[0] == '\0')		ret = LIBPQ_CC_connect(self, password_req, salt_para);	else	{		ret = original_CC_connect(self, password_req, salt_para);		if (0 == ret && CONN_AUTH_TYPE_UNSUPPORTED == CC_get_errornumber(self))		{			SOCK_Destructor(self->sock);			self->sock = (SocketClass *) 0;			ret = LIBPQ_CC_connect(self, password_req, salt_para);		}	}	if (ret <= 0)		return ret;	CC_set_translation(self);	/*	 * Send any initial settings	 */	/*	 * Since these functions allocate statements, and since the connection	 * is not established yet, it would violate odbc state transition	 * rules.  Therefore, these functions call the corresponding local	 * function instead.	 */inolog("CC_send_settings\n");	CC_send_settings(self);	CC_clear_error(self);			/* clear any error */	CC_lookup_lo(self);			/* a hack to get the oid of						   our large object oid type */	/*	 *	Multibyte handling is available ?	 */	if (PG_VERSION_GE(self, 6.4))	{		CC_lookup_characterset(self);		if (CC_get_errornumber(self) > 0)			return 0;#ifdef UNICODE_SUPPORT		if (CC_is_in_unicode_driver(self))		{			if (!self->original_client_encoding ||			    UTF8 != self->ccsc)			{				QResultClass	*res;				if (PG_VERSION_LT(self, 7.1))				{					CC_set_error(self, CONN_NOT_IMPLEMENTED_ERROR, "UTF-8 conversion isn't implemented before 7.1", func);					return 0;				}				if (self->original_client_encoding)					free(self->original_client_encoding);				self->original_client_encoding = NULL;				if (res = CC_send_query(self, "set client_encoding to 'UTF8'", NULL, 0, NULL), QR_command_maybe_successful(res))				{					self->original_client_encoding = strdup("UNICODE");					self->ccsc = pg_CS_code(self->original_client_encoding);				}				QR_Destructor(res);			}		}#else		{		}#endif /* UNICODE_SUPPORT */	}#ifdef UNICODE_SUPPORT	else if (CC_is_in_unicode_driver(self))	{		CC_set_error(self, CONN_NOT_IMPLEMENTED_ERROR, "Unicode isn't supported before 6.4", func);		return 0;	}#endif /* UNICODE_SUPPORT */	ci->updatable_cursors = DISALLOW_UPDATABLE_CURSORS; 	if (ci->allow_keyset &&		PG_VERSION_GE(self, 7.0)) /* Tid scan since 7.0 */	{		if (ci->drivers.lie || !ci->drivers.use_declarefetch)			ci->updatable_cursors |= (ALLOW_STATIC_CURSORS | ALLOW_KEYSET_DRIVEN_CURSORS | ALLOW_BULK_OPERATIONS | SENSE_SELF_OPERATIONS);		else		{			if (PG_VERSION_GE(self, 7.4)) /* HOLDABLE CURSORS since 7.4 */				ci->updatable_cursors |= (ALLOW_STATIC_CURSORS | SENSE_SELF_OPERATIONS);		}	}	if (CC_get_errornumber(self) > 0)		CC_clear_error(self);		/* clear any initial command errors */	self->status = CONN_CONNECTED;	if (CC_is_in_unicode_driver(self)	    && 0 < ci->bde_environment)		self->unicode |= CONN_DISALLOW_WCHAR;mylog("conn->unicode=%d\n", self->unicode);	mylog("%s: returning...\n", func);	return 1;}charCC_add_statement(ConnectionClass *self, StatementClass *stmt){	int	i;	char	ret = TRUE;	mylog("CC_add_statement: self=%p, stmt=%p\n", self, stmt);	CONNLOCK_ACQUIRE(self);	for (i = 0; i < self->num_stmts; i++)	{		if (!self->stmts[i])		{			stmt->hdbc = self;			self->stmts[i] = stmt;			break;		}	}	if (i >= self->num_stmts) /* no more room -- allocate more memory */	{		self->stmts = (StatementClass **) realloc(self->stmts, sizeof(StatementClass *) * (STMT_INCREMENT + self->num_stmts));		if (!self->stmts)			ret = FALSE;		else		{			memset(&self->stmts[self->num_stmts], 0, sizeof(StatementClass *) * STMT_INCREMENT);			stmt->hdbc = self;			self->stmts[self->num_stmts] = stmt;			self->num_stmts += STMT_INCREMENT;		}	}	CONNLOCK_RELEASE(self);	return TRUE;}static voidCC_set_error_statements(ConnectionClass *self){	int	i;	mylog("CC_error_statements: self=%p\n", self);	for (i = 0; i < self->num_stmts; i++)	{		if (NULL != self->stmts[i])			SC_ref_CC_error(self->stmts[i]);	}}charCC_remove_statement(ConnectionClass *self, StatementClass *stmt){	int	i;	char	ret = FALSE;	CONNLOCK_ACQUIRE(self);	for (i = 0; i < self->num_stmts; i++)	{		if (self->stmts[i] == stmt && stmt->status != STMT_EXECUTING)		{			self->stmts[i] = NULL;			ret = TRUE;			break;		}	}	CONNLOCK_RELEASE(self);	return ret;}int	CC_get_max_idlen(ConnectionClass *self){	int	len = self->max_identifier_length;	if  (len < 0)	{		QResultClass	*res;		res = CC_send_query(self, "show max_identifier_length", NULL, ROLLBACK_ON_ERROR | IGNORE_ABORT_ON_CONN, NULL);		if (QR_command_maybe_successful(res))			len = self->max_identifier_length = atoi(res->command);		QR_Destructor(res);	}mylog("max_identifier_length=%d\n", len);	return len < 0 ? 0 : len; }/* *	Create a more informative error message by concatenating the connection *	error message with its socket error message. */static char *CC_create_errormsg(ConnectionClass *self){	SocketClass *sock = self->sock;	size_t	pos;	char	msg[4096];	const char *sockerrmsg;	mylog("enter CC_create_errormsg\n");	msg[0] = '\0';	if (CC_get_errormsg(self))		strncpy(msg, CC_get_errormsg(self), sizeof(msg));	mylog("msg = '%s'\n", msg);	if (sock && NULL != (sockerrmsg = SOCK_get_errmsg(sock)) && '\0' != sockerrmsg[0])	{		pos = strlen(msg);		snprintf(&msg[pos], sizeof(msg) - pos, ";\n%s", sockerrmsg);	}	mylog("exit CC_create_errormsg\n");	return msg ? strdup(msg) : NULL;}voidCC_set_error(ConnectionClass *self, int number, const char *message, const char *func){	CONNLOCK_ACQUIRE(self);	if (self->__error_message)		free(self->__error_message);	self->__error_number = number;	self->__error_message = message ? strdup(message) : NULL;	if (0 != number)		CC_set_error_statements(self);	if (func && number != 0)		CC_log_error(func, "", self); 	CONNLOCK_RELEASE(self);}voidCC_set_errormsg(ConnectionClass *self, const char *message){	CONNLOCK_ACQUIRE(self);	if (self->__error_message)		free(self->__error_message);	self->__error_message = message ? strdup(message) : NULL;	CONNLOCK_RELEASE(self);}charCC_get_error(ConnectionClass *self, int *number, char **message){	int			rv;	char *msgcrt;	mylog("enter CC_get_error\n");	CONNLOCK_ACQUIRE(self);	/* Create a very informative errormsg if it hasn't been done yet. */	if (!self->errormsg_created)	{		msgcrt = CC_create_errormsg(self);		if (self->__error_message)			free(self->__error_message);		self->__error_message = msgcrt;		self->errormsg_created = TRUE;	}	if (CC_get_errornumber(self))	{		*number = CC_get_errornumber(self);		*message = CC_get_errormsg(self);	}	rv = (CC_get_errornumber(self) != 0);	self->__error_number = 0;		/* clear the error */	CONNLOCK_RELEASE(self);	mylog("exit CC_get_error\n");	return rv;}static void CC_clear_cursors(ConnectionClass *self, BOOL on_abort){	int	i;	StatementClass	*stmt;	QResultClass	*res;	if (!self->ncursors)		return;	CONNLOCK_ACQUIRE(self);	for (i = 0; i < self->num_stmts; i++)	{		stmt = self->stmts[i];		if (stmt && (res = SC_get_Result(stmt)) &&			QR_get_cursor(res))		{			if ((on_abort && !QR_is_permanent(res)) ||				!QR_is_withhold(res))			/*			 * non-holdable cursors are automatically closed			 * at commit time.			 * all non-permanent cursors are automatically closed			 * at rollback time.			 */					QR_set_cursor(res, NULL);			else if (!QR_is_permanent(res))			{				QResultClass	*wres;				char	cmd[64];				snprintf(cmd, sizeof(cmd), "MOVE 0 in \"%s\"", QR_get_cursor(res));				CONNLOCK_RELEASE(self);				wres = CC_send_query(self, cmd, NULL, ROLLBACK_ON_ERROR | IGNORE_ABORT_ON_CONN, NULL);				if (QR_command_maybe_successful(wres))					QR_set_permanent(res);				else					QR_set_cursor(res, NULL);				QR_Destructor(wres);				CONNLOCK_ACQUIRE(self);			}		}	}	CONNLOCK_RELEASE(self);}	void	CC_on_commit(ConnectionClass *conn){	CONNLOCK_ACQUIRE(conn);	if (CC_is_in_trans(conn))	{		CC_set_no_trans(conn);		CC_set_no_manual_trans(conn);	}	CC_clear_cursors(conn, FALSE);	CONNLOCK_RELEASE(conn);	CC_discard_marked_objects(conn);	CONNLOCK_ACQUIRE(conn);	if (conn->result_uncommitted)	{		CONNLOCK_RELEASE(conn);		ProcessRollback(conn, FALSE, FALSE);		CONNLOCK_ACQUIRE(conn);		conn->result_uncommitted = 0;	}	CONNLOCK_RELEASE(conn);}void	CC_on_abort(ConnectionClass *conn, UDWORD opt){	BOOL	set_no_trans = FALSE;mylog("CC_on_abort in\n");	CONNLOCK_ACQUIRE(conn);	if (0 != (opt & CONN_DEAD)) /* CONN_DEAD implies NO_TRANS also */		opt |= NO_TRANS;	if (CC_is_in_trans(conn))	{		if (0 != (opt & NO_TRANS))		{			CC_set_no_trans(conn);			CC_set_no_manual_trans(conn);			set_no_trans = TRUE;		}	}	CC_clear_cursors(conn, TRUE);	if (0 != (opt & CONN_DEAD))	{		conn->status = CONN_DOWN;		if (conn->sock)		{

⌨️ 快捷键说明

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