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

📄 mysqlconnection.c

📁 适合于Unix/Linux下的一个持久数据库连接池
💻 C
📖 第 1 页 / 共 2 页
字号:
// Copyright (c) 1999-2001  David Muse// See the file COPYING for more information#include <rudiments/charstring.h>#include <rudiments/rawbuffer.h>#include <mysqlconnection.h>#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID>=32200	#include <errmsg.h>#endif#include <datatypes.h>#include <config.h>#include <stdlib.h>#include <unistd.h>#ifdef MYSQL_OPT_RECONNECTconst my_bool	mysqlconnection::mytrue=TRUE;#endifmysqlconnection::mysqlconnection() : sqlrconnection_svr() {	connected=false;#ifdef HAVE_MYSQL_STMT_PREPARE	fakebinds=false;#endif	dbversion=NULL;	// start this at false because we don't need to do a commit before	// the first query when we very first start up	firstquery=false;}mysqlconnection::~mysqlconnection() {	delete[] dbversion;}uint16_t mysqlconnection::getNumberOfConnectStringVars() {	return NUM_CONNECT_STRING_VARS;}void mysqlconnection::handleConnectString() {	setUser(connectStringValue("user"));	setPassword(connectStringValue("password"));	db=connectStringValue("db");	host=connectStringValue("host");	port=connectStringValue("port");	socket=connectStringValue("socket");#ifdef HAVE_MYSQL_STMT_PREPARE	fakebinds=!charstring::compare(connectStringValue("fakebinds"),"yes");#endif}bool mysqlconnection::logIn(bool printerrors) {	// Handle host.	// For really old versions of mysql, a NULL host indicates that the	// unix socket should be used.  There's no way to specify what unix	// socket or inet port to connect to, those values are hardcoded	// into the client library.	// For some newer versions, a NULL host causes problems, but an empty	// string is safe.#ifdef HAVE_MYSQL_REAL_CONNECT_FOR_SURE	const char	*hostval=(host && host[0])?host:"";#else	const char	*hostval=(host && host[0])?host:NULL;#endif	// Handle db.	const char	*dbval=(db && db[0])?db:"";		// log in	const char	*user=getUser();	const char	*password=getPassword();#ifdef HAVE_MYSQL_REAL_CONNECT_FOR_SURE	// Handle port and socket.	int		portval=(port && port[0])?charstring::toInteger(port):0;	const char	*socketval=(socket && socket[0])?socket:NULL;	unsigned long	clientflag=0;	#ifdef CLIENT_MULTI_STATEMENTS	clientflag=CLIENT_MULTI_STATEMENTS;	#endif	#if MYSQL_VERSION_ID>=32200	// initialize database connection structure	if (!mysql_init(&mysql)) {		if (printerrors) {			fprintf(stderr,"mysql_init failed\n");		}		return false;	}	if (!mysql_real_connect(&mysql,hostval,user,password,dbval,					portval,socketval,clientflag)) {	#else	if (!mysql_real_connect(&mysql,hostval,user,password,					portval,socketval,clientflag)) {	#endif		if (printerrors) {			fprintf(stderr,"mysql_real_connect failed: %s\n",							mysql_error(&mysql));		}#else	if (!mysql_connect(&mysql,hostval,user,password)) {		if (printerrors) {			fprintf(stderr,"mysql_connect failed: %s\n",						mysql_error(&mysql));		}#endif		logOut();		return false;	}#ifdef MYSQL_OPT_RECONNECT	// Enable autoreconnect in the C api	// (ordinarily mysql_options should be called before mysql_connect,	// but not for this option)	mysql_options(&mysql,MYSQL_OPT_RECONNECT,&mytrue);#endif#ifdef MYSQL_SELECT_DB	if (mysql_select_db(&mysql,dbval)) {		if (printerrors) {			fprintf(stderr,"mysql_select_db failed: %s\n",						mysql_error(&mysql));		}		logOut();		return false;	}#endif	connected=true;#ifdef HAVE_MYSQL_STMT_PREPARE	// fake binds when connected to older servers#ifdef HAVE_MYSQL_GET_SERVER_VERSION	if (mysql_get_server_version(&mysql)<40102) {		fakebinds=true;	}#else	char		**list;	uint64_t	listlen;	charstring::split(mysql_get_server_info(&mysql),				".",true,&list,&listlen);	if (listlen==3) {		uint64_t	major=charstring::toUnsignedInteger(list[0]);		uint64_t	minor=charstring::toUnsignedInteger(list[1]);		uint64_t	patch=charstring::toUnsignedInteger(list[2]);		if (major>4 || (major==4 && minor>1) ||				(major==4 && minor==1 && patch>=2)) {			fakebinds=true;		} 		for (uint64_t index=0; index<listlen; index++) {			delete[] list[index];		}		delete[] list;	}#endif#endif	return true;}#ifdef HAVE_MYSQL_CHANGE_USERbool mysqlconnection::changeUser(const char *newuser,					const char *newpassword) {	return !mysql_change_user(&mysql,newuser,newpassword,					(char *)((db && db[0])?db:""));}#endifsqlrcursor_svr *mysqlconnection::initCursor() {	return (sqlrcursor_svr *)new mysqlcursor((sqlrconnection_svr *)this);}void mysqlconnection::deleteCursor(sqlrcursor_svr *curs) {	delete (mysqlcursor *)curs;}void mysqlconnection::logOut() {	connected=false;	mysql_close(&mysql);}#ifdef HAVE_MYSQL_PINGbool mysqlconnection::ping() {	return (!mysql_ping(&mysql))?true:false;}#endifconst char *mysqlconnection::identify() {	return "mysql";}const char *mysqlconnection::dbVersion() {	delete[] dbversion;	dbversion=charstring::duplicate(mysql_get_server_info(&mysql));	return dbversion;}const char *mysqlconnection::bindFormat() {#ifdef HAVE_MYSQL_STMT_PREPARE	if (fakebinds) {		return sqlrconnection_svr::bindFormat();	} else {		return "?";	}#else	return sqlrconnection_svr::bindFormat();#endif}bool mysqlconnection::isTransactional() {	return true;}bool mysqlconnection::autoCommitOn() {#ifdef HAVE_MYSQL_AUTOCOMMIT	return !mysql_autocommit(&mysql,true);#else	// do nothing	return true;#endif}bool mysqlconnection::autoCommitOff() {#ifdef HAVE_MYSQL_AUTOCOMMIT	return !mysql_autocommit(&mysql,false);#else	// do nothing	return true;#endif}bool mysqlconnection::commit() {#ifdef HAVE_MYSQL_COMMIT	return !mysql_commit(&mysql);#else	// do nothing	return true;#endif}bool mysqlconnection::rollback() {#ifdef HAVE_MYSQL_ROLLBACK	return !mysql_rollback(&mysql);#else	// do nothing	return true;#endif}#ifdef HAVE_MYSQL_STMT_PREPAREshort mysqlconnection::nonNullBindValue() {	return 0;}short mysqlconnection::nullBindValue() {	return 1;}#endifvoid mysqlconnection::endSession() {	firstquery=true;}mysqlcursor::mysqlcursor(sqlrconnection_svr *conn) : sqlrcursor_svr(conn) {	mysqlconn=(mysqlconnection *)conn;	mysqlresult=NULL;	columnnames=NULL;#ifdef HAVE_MYSQL_STMT_PREPARE	usestmtprepare=true;	unsupportedbystmt.compile("^\\s*(((create|CREATE|drop|DROP)\\s+"			"(procedure|PROCEDURE|function|FUNCTION))|"			"(CALL|call)|(START|start)|(BEGIN|begin))\\s+");	unsupportedbystmt.study();	stmt=mysql_stmt_init(&mysqlconn->mysql);	for (unsigned short index=0; index<MAX_SELECT_LIST_SIZE; index++) {		fieldbind[index].buffer_type=MYSQL_TYPE_STRING;		fieldbind[index].buffer=(char *)&field[index];		fieldbind[index].buffer_length=MAX_ITEM_BUFFER_SIZE;		fieldbind[index].is_null=&isnull[index];		fieldbind[index].length=&fieldlength[index];	}#endif}mysqlcursor::~mysqlcursor() {	delete[] columnnames;#ifdef HAVE_MYSQL_STMT_PREPARE	mysql_stmt_free_result(stmt);	mysql_stmt_close(stmt);	if (mysqlresult) {		mysql_free_result(mysqlresult);	}#endif}#ifdef HAVE_MYSQL_STMT_PREPAREbool mysqlcursor::prepareQuery(const char *query, uint32_t length) {	// if this if the first query of the session, do a commit first,	// doing this will refresh this connection with any data committed	// by other connections, which is what would happen if a new client	// connected directly to mysql	if (mysqlconn->firstquery) {		mysqlconn->commit();		mysqlconn->firstquery=false;	}	if (mysqlconn->fakebinds) {		return true;	}	// can't use stmt API to run a couple of types of queries as of 5.0	usestmtprepare=true;	if (unsupportedbystmt.match(query)) {		usestmtprepare=false;		return true;	}	// store inbindcount here, otherwise if rebinding/reexecution occurs and	// the client tries to bind more variables than were defined when the	// query was prepared, it would cause the inputBind methods to attempt	// to address beyond the end of the various arrays	bindcount=inbindcount;	// reset bind counter	bindcounter=0;	// re-init bind buffers	rawbuffer::zero(&bind,sizeof(bind));	return !mysql_stmt_prepare(stmt,query,length);}#endifbool mysqlcursor::supportsNativeBinds() {#ifdef HAVE_MYSQL_STMT_PREPARE	return (!mysqlconn->fakebinds && usestmtprepare);#else	return false;#endif}#ifdef HAVE_MYSQL_STMT_PREPAREbool mysqlcursor::inputBindString(const char *variable, 						uint16_t variablesize,						const char *value, 						uint16_t valuesize,						int16_t *isnull) {	if (mysqlconn->fakebinds || !usestmtprepare) {		return true;	}	// don't attempt to bind beyond the number of	// variables defined when the query was prepared	if (bindcounter>bindcount) {		return false;	}	bindvaluesize[bindcounter]=valuesize;	if (*isnull) {		bind[bindcounter].buffer_type=MYSQL_TYPE_NULL;		bind[bindcounter].buffer=(void *)NULL;		bind[bindcounter].buffer_length=0;		bind[bindcounter].length=0;	} else {		bind[bindcounter].buffer_type=MYSQL_TYPE_STRING;		bind[bindcounter].buffer=(void *)value;		bind[bindcounter].buffer_length=valuesize;		bind[bindcounter].length=&bindvaluesize[bindcounter];	}	bind[bindcounter].is_null=(my_bool *)isnull;	bindcounter++;	return true;}bool mysqlcursor::inputBindInteger(const char *variable, 						uint16_t variablesize,						int64_t *value) {	if (mysqlconn->fakebinds || !usestmtprepare) {		return true;	}	// don't attempt to bind beyond the number of	// variables defined when the query was prepared	if (bindcounter>bindcount) {		return false;	}	bindvaluesize[bindcounter]=sizeof(int64_t);	if (*isnull) {		bind[bindcounter].buffer_type=MYSQL_TYPE_NULL;		bind[bindcounter].buffer=(void *)NULL;		bind[bindcounter].buffer_length=0;		bind[bindcounter].length=0;	} else {		bind[bindcounter].buffer_type=MYSQL_TYPE_LONGLONG;		bind[bindcounter].buffer=(void *)value;		bind[bindcounter].buffer_length=sizeof(int64_t);		bind[bindcounter].length=&bindvaluesize[bindcounter];	}	bind[bindcounter].is_null=(my_bool *)isnull;	bindcounter++;	return true;}bool mysqlcursor::inputBindDouble(const char *variable, 						uint16_t variablesize,						double *value,						uint32_t precision,						uint32_t scale) {	if (mysqlconn->fakebinds || !usestmtprepare) {		return true;	}	// don't attempt to bind beyond the number of	// variables defined when the query was prepared	if (bindcounter>bindcount) {		return false;	}	bindvaluesize[bindcounter]=sizeof(double);	if (*isnull) {		bind[bindcounter].buffer_type=MYSQL_TYPE_NULL;		bind[bindcounter].buffer=(void *)NULL;		bind[bindcounter].buffer_length=0;		bind[bindcounter].length=0;	} else {		bind[bindcounter].buffer_type=MYSQL_TYPE_DOUBLE;		bind[bindcounter].buffer=(void *)value;		bind[bindcounter].buffer_length=sizeof(double);		bind[bindcounter].length=&bindvaluesize[bindcounter];	}	bind[bindcounter].is_null=(my_bool *)isnull;	bindcounter++;	return true;}bool mysqlcursor::inputBindBlob(const char *variable, 						uint16_t variablesize,						const char *value, 						uint32_t valuesize,						int16_t *isnull) {	if (mysqlconn->fakebinds || !usestmtprepare) {		return true;	}

⌨️ 快捷键说明

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