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

📄 connection.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 3 页
字号:
StartupPacket6_2 sp62;QResultClass *res;SocketClass *sock;ConnInfo *ci = &(self->connInfo);int areq = -1;int beresp;char msgbuffer[ERROR_MSG_LENGTH]; char salt[2];static char *func="CC_connect";	mylog("%s: entering...\n", func);	if ( do_password)		sock = self->sock;		/* already connected, just authenticate */	else {		qlog("Global Options: Version='%s', fetch=%d, socket=%d, unknown_sizes=%d, max_varchar_size=%d, max_longvarchar_size=%d\n",			POSTGRESDRIVERVERSION,			globals.fetch_max, 			globals.socket_buffersize, 			globals.unknown_sizes, 			globals.max_varchar_size, 			globals.max_longvarchar_size);		qlog("                disable_optimizer=%d, ksqo=%d, unique_index=%d, use_declarefetch=%d\n",			globals.disable_optimizer,			globals.ksqo,			globals.unique_index,			globals.use_declarefetch);		qlog("                text_as_longvarchar=%d, unknowns_as_longvarchar=%d, bools_as_char=%d\n",			globals.text_as_longvarchar, 			globals.unknowns_as_longvarchar, 			globals.bools_as_char);		qlog("                extra_systable_prefixes='%s', conn_settings='%s'\n",			globals.extra_systable_prefixes, 			globals.conn_settings);		if (self->status != CONN_NOT_CONNECTED) {			self->errormsg = "Already connected.";			self->errornumber = CONN_OPENDB_ERROR;			return 0;		}		if ( ci->server[0] == '\0' || ci->port[0] == '\0' || ci->database[0] == '\0') {			self->errornumber = CONN_INIREAD_ERROR;			self->errormsg = "Missing server name, port, or database name in call to CC_connect.";			return 0;		}		mylog("CC_connect(): DSN = '%s', server = '%s', port = '%s', database = '%s', username = '%s', password='%s'\n", ci->dsn, ci->server, ci->port, ci->database, ci->username, ci->password);		/* If the socket was closed for some reason (like a SQLDisconnect, but no SQLFreeConnect			then create a socket now.		*/		if ( ! self->sock) {			self->sock = SOCK_Constructor();			if ( ! self->sock) {				 self->errornumber = CONNECTION_SERVER_NOT_REACHED;				 self->errormsg = "Could not open a socket to the server";				 return 0;			}		}		sock = self->sock;		mylog("connecting to the server socket...\n");		SOCK_connect_to(sock, (short) atoi(ci->port), ci->server);		if (SOCK_get_errcode(sock) != 0) {			mylog("connection to the server socket failed.\n");			self->errornumber = CONNECTION_SERVER_NOT_REACHED;			self->errormsg = "Could not connect to the server";			return 0;		}		mylog("connection to the server socket succeeded.\n");		if ( PROTOCOL_62(ci)) {			sock->reverse = TRUE;		/* make put_int and get_int work for 6.2 */			memset(&sp62, 0, sizeof(StartupPacket6_2));			SOCK_put_int(sock, htonl(4+sizeof(StartupPacket6_2)), 4);			sp62.authtype = htonl(NO_AUTHENTICATION);			strncpy(sp62.database, ci->database, PATH_SIZE);			strncpy(sp62.user, ci->username, NAMEDATALEN);			SOCK_put_n_char(sock, (char *) &sp62, sizeof(StartupPacket6_2));			SOCK_flush_output(sock);		}		else {			memset(&sp, 0, sizeof(StartupPacket));			mylog("sizeof startup packet = %d\n", sizeof(StartupPacket));			// Send length of Authentication Block			SOCK_put_int(sock, 4+sizeof(StartupPacket), 4); 			if ( PROTOCOL_63(ci))				sp.protoVersion = (ProtocolVersion) htonl(PG_PROTOCOL_63);			else				sp.protoVersion = (ProtocolVersion) htonl(PG_PROTOCOL_LATEST);			strncpy(sp.database, ci->database, SM_DATABASE);			strncpy(sp.user, ci->username, SM_USER);			SOCK_put_n_char(sock, (char *) &sp, sizeof(StartupPacket));			SOCK_flush_output(sock);		}		mylog("sent the authentication block.\n");		if (sock->errornumber != 0) {			mylog("couldn't send the authentication block properly.\n");			self->errornumber = CONN_INVALID_AUTHENTICATION;			self->errormsg = "Sending the authentication packet failed";			return 0;		}		mylog("sent the authentication block successfully.\n");	}	mylog("gonna do authentication\n");	// ***************************************************	//	Now get the authentication request from backend	// ***************************************************	if ( ! PROTOCOL_62(ci))	do {		if (do_password)			beresp = 'R';		else			beresp = SOCK_get_char(sock);		switch(beresp) {		case 'E':			mylog("auth got 'E'\n");			SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);			self->errornumber = CONN_INVALID_AUTHENTICATION;			self->errormsg = msgbuffer;			qlog("ERROR from backend during authentication: '%s'\n", self->errormsg);			return 0;		case 'R':			if (do_password) {				mylog("in 'R' do_password\n");				areq = AUTH_REQ_PASSWORD;				do_password = FALSE;			}			else {				mylog("auth got 'R'\n");				areq = SOCK_get_int(sock, 4);				if (areq == AUTH_REQ_CRYPT)					SOCK_get_n_char(sock, salt, 2);				mylog("areq = %d\n", areq);			}			switch(areq) {			case AUTH_REQ_OK:				break;			case AUTH_REQ_KRB4:				self->errormsg = "Kerberos 4 authentication not supported";				self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED;				return 0;			case AUTH_REQ_KRB5:				self->errormsg = "Kerberos 5 authentication not supported";				self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED;				return 0;			case AUTH_REQ_PASSWORD:				mylog("in AUTH_REQ_PASSWORD\n");				if (ci->password[0] == '\0') {					self->errornumber = CONNECTION_NEED_PASSWORD;					self->errormsg = "A password is required for this connection.";					return -1;	/* need password */				}				mylog("past need password\n");				SOCK_put_int(sock, 4+strlen(ci->password)+1, 4);				SOCK_put_n_char(sock, ci->password, strlen(ci->password) + 1);				SOCK_flush_output(sock);				mylog("past flush\n");				break;			case AUTH_REQ_CRYPT:				self->errormsg = "Password crypt authentication not supported";				self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED;				return 0;			default:				self->errormsg = "Unknown authentication type";				self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED;				return 0;			}			break;		default:			self->errormsg = "Unexpected protocol character during authentication";			self->errornumber = CONN_INVALID_AUTHENTICATION;			return 0;		}	} while (areq != AUTH_REQ_OK);			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 */	mylog("sending an empty query...\n");	res = CC_send_query(self, " ", NULL);	if ( res == NULL || QR_get_status(res) != PGRES_EMPTY_QUERY) {		mylog("got no result from the empty query.  (probably database does not exist)\n");		self->errornumber = CONNECTION_NO_SUCH_DATABASE;		self->errormsg = "The database does not exist on the server\nor user authentication failed.";		if (res != NULL)			QR_Destructor(res);		return 0;	}	if (res)		QR_Destructor(res);	mylog("empty query seems to be OK.\n");	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.	*/	CC_send_settings(self);	CC_lookup_lo(self);		/* a hack to get the oid of our large object oid type */	CC_clear_error(self);	/* clear any initial command errors */	self->status = CONN_CONNECTED;	mylog("%s: returning...\n", func);	return 1;}charCC_add_statement(ConnectionClass *self, StatementClass *stmt){int i;	mylog("CC_add_statement: self=%u, stmt=%u\n", self, stmt);	for (i = 0; i < self->num_stmts; i++) {		if ( ! self->stmts[i]) {			stmt->hdbc = self;			self->stmts[i] = stmt;			return TRUE;		}	}	/* no more room -- allocate more memory */	self->stmts = (StatementClass **) realloc( self->stmts, sizeof(StatementClass *) * (STMT_INCREMENT + self->num_stmts));	if ( ! self->stmts)		return FALSE;	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;	return TRUE;}char CC_remove_statement(ConnectionClass *self, StatementClass *stmt){int i;	for (i = 0; i < self->num_stmts; i++) {		if (self->stmts[i] == stmt && stmt->status != STMT_EXECUTING) {			self->stmts[i] = NULL;			return TRUE;		}	}	return FALSE;}/*	Create a more informative error message by concatenating the connection	error message with its socket error message.*/char *CC_create_errormsg(ConnectionClass *self){SocketClass *sock = self->sock;int pos;static char msg[4096];	mylog("enter CC_create_errormsg\n");	msg[0] = '\0';	if (self->errormsg)		strcpy(msg, self->errormsg);	mylog("msg = '%s'\n", msg);	if (sock && sock->errormsg && sock->errormsg[0] != '\0') {		pos = strlen(msg);		sprintf(&msg[pos], ";\n%s", sock->errormsg);	}	mylog("exit CC_create_errormsg\n");	return msg;}char CC_get_error(ConnectionClass *self, int *number, char **message){int rv;	mylog("enter CC_get_error\n");	//	Create a very informative errormsg if it hasn't been done yet.	if ( ! self->errormsg_created) {		self->errormsg = CC_create_errormsg(self);		self->errormsg_created = TRUE;	}	if (self->errornumber) {		*number = self->errornumber;		*message = self->errormsg;	}	rv = (self->errornumber != 0);	self->errornumber = 0;		// clear the error	mylog("exit CC_get_error\n");	return rv;}/*	The "result_in" is only used by QR_next_tuple() to fetch another group of rows into	the same existing QResultClass (this occurs when the tuple cache is depleted and	needs to be re-filled).	The "cursor" is used by SQLExecute to associate a statement handle as the cursor name	(i.e., C3326857) for SQL select statements.  This cursor is then used in future 	'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements.*/QResultClass *CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi){QResultClass *result_in, *res = NULL;char id, swallow;SocketClass *sock = self->sock;static char msgbuffer[MAX_MESSAGE_LEN+1];char cmdbuffer[MAX_MESSAGE_LEN+1];	// QR_set_command() dups this string so dont need static	mylog("send_query(): conn=%u, query='%s'\n", self, query);	qlog("conn=%u, query='%s'\n", self, query);	// Indicate that we are sending a query to the backend	if(strlen(query) > MAX_MESSAGE_LEN-2) {		self->errornumber = CONNECTION_MSG_TOO_LONG;		self->errormsg = "Query string is too long";		return NULL;	}	if ((NULL == query) || (query[0] == '\0'))		return NULL;	if (SOCK_get_errcode(sock) != 0) {		self->errornumber = CONNECTION_COULD_NOT_SEND;		self->errormsg = "Could not send Query to backend";		CC_set_no_trans(self);		return NULL;	}	SOCK_put_char(sock, 'Q');	if (SOCK_get_errcode(sock) != 0) {		self->errornumber = CONNECTION_COULD_NOT_SEND;		self->errormsg = "Could not send Query to backend";		CC_set_no_trans(self);		return NULL;	}	SOCK_put_string(sock, query);	SOCK_flush_output(sock);	if (SOCK_get_errcode(sock) != 0) {		self->errornumber = CONNECTION_COULD_NOT_SEND;		self->errormsg = "Could not send Query to backend";		CC_set_no_trans(self);		return NULL;	}	mylog("send_query: done sending query\n");	while(1) {		/* what type of message is coming now ? */		id = SOCK_get_char(sock);		if ((SOCK_get_errcode(sock) != 0) || (id == EOF)) {			self->errornumber = CONNECTION_NO_RESPONSE;			self->errormsg = "No response from the backend";			if (res)				QR_Destructor(res);			mylog("send_query: 'id' - %s\n", self->errormsg);			CC_set_no_trans(self);			return NULL;		}		mylog("send_query: got id = '%c'\n", id);		switch (id) {		case 'A' : /* Asynchronous Messages are ignored */			(void)SOCK_get_int(sock, 4); /* id of notification */			SOCK_get_string(sock, msgbuffer, MAX_MESSAGE_LEN);			/* name of the relation the message comes from */			break;		case 'C' : /* portal query command, no tuples returned */			/* read in the return message from the backend */			SOCK_get_string(sock, cmdbuffer, MAX_MESSAGE_LEN);			if (SOCK_get_errcode(sock) != 0) {				self->errornumber = CONNECTION_NO_RESPONSE;				self->errormsg = "No response from backend while receiving a portal query command";				mylog("send_query: 'C' - %s\n", self->errormsg);				CC_set_no_trans(self);				return NULL;			} else {				char clear = 0;				mylog("send_query: ok - 'C' - %s\n", cmdbuffer);				if (res == NULL)	/* allow for "show" style notices */					res = QR_Constructor();				mylog("send_query: setting cmdbuffer = '%s'\n", cmdbuffer);				/*	Only save the first command */

⌨️ 快捷键说明

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