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

📄 firebirdconnection.c

📁 适合于Unix/Linux下的一个持久数据库连接池
💻 C
📖 第 1 页 / 共 2 页
字号:
// Copyright (c) 1999-2001  David Muse// See the file COPYING for more information#include <firebirdconnection.h>#include <rudiments/rawbuffer.h>#include <rudiments/snooze.h>#include <config.h>#include <datatypes.h>// for pow()#include <math.h>#include <stdlib.h>static char tpb[] = {	isc_tpb_version3,	isc_tpb_write,	isc_tpb_read_committed,	isc_tpb_rec_version,	// FIXME: vladimir changed this to isc_tpb_nowait.  why?	isc_tpb_wait};firebirdconnection::firebirdconnection() : sqlrconnection_svr() {	dbversion=NULL;}firebirdconnection::~firebirdconnection() {	delete dbversion;}uint16_t firebirdconnection::getNumberOfConnectStringVars() {	return NUM_CONNECT_STRING_VARS;}void firebirdconnection::handleConnectString() {	// override legacy "database" parameter with modern "db" parameter	database=connectStringValue("database");	const char	*tmp=connectStringValue("db");	if (tmp && tmp[0]) {		database=tmp;	}	const char	*dialectstr=connectStringValue("dialect");	if (dialectstr) {		dialect=charstring::toInteger(dialectstr);		if (dialect<1) {			dialect=1;		}		if (dialect>3) {			dialect=3;		}	} else {		dialect=3;	}	setUser(connectStringValue("user"));	setPassword(connectStringValue("password"));	const char	*autocom=connectStringValue("autocommit");	setAutoCommitBehavior((autocom &&		!charstring::compareIgnoringCase(autocom,"yes")));}bool firebirdconnection::logIn(bool printerrors) {	// initialize a dpb	char	*dpbptr=dpb;	*dpbptr++=isc_dpb_version1;	*dpbptr++=isc_dpb_num_buffers;	*dpbptr++=1;	*dpbptr++=90;	dpblength=dpbptr-dpb;	// handle user/password parameters	const char	*user=getUser();	if (user) {		environment::setValue("ISC_USER",user);	}	const char	*password=getPassword();	if (password) {		environment::setValue("ISC_PASSWORD",password);	}	// attach to the database	db=0L;	tr=0L;	if (isc_attach_database(error,charstring::length(database),					const_cast<char *>(database),&db,					//dpblength,dpb)) {					0,NULL)) {		db=0L;		return false;	}	// start a transaction	if (isc_start_transaction(error,&tr,1,&db,(uint16_t)sizeof(tpb),&tpb)) {		// print the error message		char		msg[512];		ISC_STATUS	*err=error;		while (isc_interprete(msg,&err)) {			fprintf(stderr,"%s\n",msg);		}		fprintf(stderr,"\n");		return false;	}	return true;}sqlrcursor_svr *firebirdconnection::initCursor() {	return (sqlrcursor_svr *)new firebirdcursor(					(sqlrconnection_svr *)this);}void firebirdconnection::deleteCursor(sqlrcursor_svr *curs) {	delete (firebirdcursor *)curs;}void firebirdconnection::logOut() {	isc_detach_database(error,&db);}bool firebirdconnection::commit() {	return (!isc_commit_retaining(error,&tr));}bool firebirdconnection::rollback() {	return (!isc_rollback_retaining(error,&tr));}bool firebirdconnection::ping() {	// call isc_database_info to get page_size and num_buffers,	// this should always be available unless the db is down	// if we get an error, then return 0, otherwise return 1	ISC_STATUS	status[20];	char		dbitems[]={isc_info_page_size,					isc_info_num_buffers,					isc_info_end};	char		resbuffer[40];	isc_database_info(status,&db,				sizeof(dbitems),dbitems,				sizeof(resbuffer),resbuffer);	return !(status[0]==1 && status[1]);}const char *firebirdconnection::identify() {	return "firebird";}const char *firebirdconnection::dbVersion() {	ISC_STATUS	status[20];	char		dbitems[]={isc_info_version,					isc_info_end};	char		resbuffer[256];	if (!isc_database_info(status,&db,				sizeof(dbitems),dbitems,				sizeof(resbuffer),resbuffer)) {		char	*ptr=resbuffer;		// first byte is isc_info_version		char		dbitem=*ptr;		ptr++;		// next 2 bytes are length of the isc_info_version data		uint16_t	len=isc_vax_integer(ptr,sizeof(uint16_t));		ptr=ptr+sizeof(uint16_t);		// the next byte is the number of lines of text		stringbuffer	dbvers;		char	linecount=*ptr;		ptr++;		for (char lineindex=0; lineindex<linecount; lineindex++) {			// the first byte of each line is the length of the line			char	linelen=*ptr;			ptr++;			// then comes the line of text itself			if (lineindex) {				dbvers.append('\n');			}			dbvers.append(ptr,linelen);		}		delete[] dbversion;		dbversion=dbvers.detachString();		return dbversion;	} 	return "";}const char *firebirdconnection::bindFormat() {	return "?";}firebirdcursor::firebirdcursor(sqlrconnection_svr *conn) :						sqlrcursor_svr(conn) {	firebirdconn=(firebirdconnection *)conn;	errormsg=NULL;	outsqlda=(XSQLDA ISC_FAR *)malloc(XSQLDA_LENGTH(MAX_SELECT_LIST_SIZE));	outsqlda->version=SQLDA_VERSION1;	outsqlda->sqln=(MAX_SELECT_LIST_SIZE>MAX_BIND_VARS)?				MAX_SELECT_LIST_SIZE:MAX_BIND_VARS;	insqlda=(XSQLDA ISC_FAR *)malloc(XSQLDA_LENGTH(MAX_BIND_VARS));	insqlda->version=SQLDA_VERSION1;	insqlda->sqln=MAX_BIND_VARS;	querytype=0;	stmt=NULL;	queryIsExecSP=false;	outbindcount=0;}firebirdcursor::~firebirdcursor() {	if (errormsg) {		delete errormsg;	}	free(outsqlda);	free(insqlda);}bool firebirdcursor::prepareQuery(const char *query, uint32_t length) {	queryIsExecSP=false;	// free the old statement if it exists	if (stmt) {		isc_dsql_free_statement(firebirdconn->error,						&stmt,DSQL_drop);	}	// allocate a cursor handle	stmt=NULL;	if (isc_dsql_allocate_statement(firebirdconn->error,					&firebirdconn->db,&stmt)) {		return false;	}	// skip whitespace	char	*qptr=(char *)query;	while (*qptr==' ' || *qptr=='\n' || *qptr=='	');	// prepare the cursor	if (isc_dsql_prepare(firebirdconn->error,&firebirdconn->tr,					&stmt,length,(char *)query,					firebirdconn->dialect,outsqlda)) {		return false;	}	// get the cursor type	char	typeitem[]={isc_info_sql_stmt_type};	char	resbuffer[1024];	if (isc_dsql_sql_info(firebirdconn->error,&stmt,				sizeof(typeitem),typeitem,				1024,resbuffer)) {		return false;	}	ISC_LONG	len=isc_vax_integer(resbuffer+1,2);	querytype=isc_vax_integer(resbuffer+3,len);	// find bind parameters, if any	insqlda->sqld=0;	if (isc_dsql_describe_bind(firebirdconn->error,&stmt,1,insqlda)) {		return false;	}	insqlda->sqln=insqlda->sqld;	return true;}bool firebirdcursor::inputBindString(const char *variable,					uint16_t variablesize,					const char *value,					uint16_t valuesize,					int16_t *isnull) {	// make bind vars 1 based like all other db's	long	index=charstring::toInteger(variable+1)-1;	if (index<0) {		return false;	}	insqlda->sqlvar[index].sqltype=SQL_TEXT+1;	insqlda->sqlvar[index].sqlscale=0;	insqlda->sqlvar[index].sqlsubtype=0;	insqlda->sqlvar[index].sqllen=valuesize;	insqlda->sqlvar[index].sqldata=(char *)value;	insqlda->sqlvar[index].sqlind=isnull;	insqlda->sqlvar[index].sqlname_length=0;	insqlda->sqlvar[index].sqlname[0]=(char)NULL;	insqlda->sqlvar[index].relname_length=0;	insqlda->sqlvar[index].relname[0]=(char)NULL;	insqlda->sqlvar[index].ownname_length=0;	insqlda->sqlvar[index].ownname[0]=(char)NULL;	insqlda->sqlvar[index].aliasname_length=0;	insqlda->sqlvar[index].aliasname[0]=(char)NULL;	return true;}bool firebirdcursor::inputBindInteger(const char *variable,					uint16_t variablesize,					int64_t *value) {	// make bind vars 1 based like all other db's	long	index=charstring::toInteger(variable+1)-1;	if (index<0) {		return false;	}	insqlda->sqlvar[index].sqltype=SQL_INT64;	insqlda->sqlvar[index].sqlscale=0;	insqlda->sqlvar[index].sqlsubtype=0;	insqlda->sqlvar[index].sqllen=sizeof(int64_t);	insqlda->sqlvar[index].sqldata=(char *)value;	insqlda->sqlvar[index].sqlind=(short *)NULL;	insqlda->sqlvar[index].sqlname_length=0;	insqlda->sqlvar[index].sqlname[0]=(char)NULL;	insqlda->sqlvar[index].relname_length=0;	insqlda->sqlvar[index].relname[0]=(char)NULL;	insqlda->sqlvar[index].ownname_length=0;	insqlda->sqlvar[index].ownname[0]=(char)NULL;	insqlda->sqlvar[index].aliasname_length=0;	insqlda->sqlvar[index].aliasname[0]=(char)NULL;	return true;}bool firebirdcursor::inputBindDouble(const char *variable,					uint16_t variablesize,					double *value,					uint32_t precision,					uint32_t scale) {	// make bind vars 1 based like all other db's	long	index=charstring::toInteger(variable+1)-1;	if (index<0) {		return false;	}	insqlda->sqlvar[index].sqltype=SQL_DOUBLE;	insqlda->sqlvar[index].sqlscale=scale;	insqlda->sqlvar[index].sqlsubtype=0;	insqlda->sqlvar[index].sqllen=sizeof(double);	insqlda->sqlvar[index].sqldata=(char *)value;	insqlda->sqlvar[index].sqlind=(short *)NULL;	insqlda->sqlvar[index].sqlname_length=0;	insqlda->sqlvar[index].sqlname[0]=(char)NULL;	insqlda->sqlvar[index].relname_length=0;	insqlda->sqlvar[index].relname[0]=(char)NULL;	insqlda->sqlvar[index].ownname_length=0;	insqlda->sqlvar[index].ownname[0]=(char)NULL;	insqlda->sqlvar[index].aliasname_length=0;	insqlda->sqlvar[index].aliasname[0]=(char)NULL;	return true;}bool firebirdcursor::outputBindString(const char *variable, 				uint16_t variablesize,				char *value, 				uint16_t valuesize, 				int16_t *isnull) {	outbindisstring[outbindcount]=true;	outbindcount++;	// if we're doing output binds then the	// query must be a stored procedure	queryIsExecSP=true;	// make bind vars 1 based like all other db's	long	index=charstring::toInteger(variable+1)-1;	if (index<0) {		return false;	}	outsqlda->sqlvar[index].sqltype=SQL_TEXT+1;	outsqlda->sqlvar[index].sqlscale=0;	outsqlda->sqlvar[index].sqlsubtype=0;	outsqlda->sqlvar[index].sqllen=valuesize;	outsqlda->sqlvar[index].sqldata=value;	outsqlda->sqlvar[index].sqlind=isnull;	outsqlda->sqlvar[index].sqlname_length=0;	outsqlda->sqlvar[index].sqlname[0]=(char)NULL;	outsqlda->sqlvar[index].relname_length=0;	outsqlda->sqlvar[index].relname[0]=(char)NULL;	outsqlda->sqlvar[index].ownname_length=0;	outsqlda->sqlvar[index].ownname[0]=(char)NULL;	outsqlda->sqlvar[index].aliasname_length=0;	outsqlda->sqlvar[index].aliasname[0]=(char)NULL;	return true;}bool firebirdcursor::outputBindInteger(const char *variable,						uint16_t variablesize,						int64_t *value,						int16_t *isnull) {	outbindisstring[outbindcount]=false;	outbindcount++;	// if we're doing output binds then the	// query must be a stored procedure	queryIsExecSP=true;	// make bind vars 1 based like all other db's	long	index=charstring::toInteger(variable+1)-1;	if (index<0) {		return false;	}	outsqlda->sqlvar[index].sqltype=SQL_INT64;	outsqlda->sqlvar[index].sqlscale=0;	outsqlda->sqlvar[index].sqlsubtype=0;	outsqlda->sqlvar[index].sqllen=sizeof(int64_t);	outsqlda->sqlvar[index].sqldata=(char *)value;	outsqlda->sqlvar[index].sqlind=isnull;	outsqlda->sqlvar[index].sqlname_length=0;	outsqlda->sqlvar[index].sqlname[0]=(char)NULL;	outsqlda->sqlvar[index].relname_length=0;	outsqlda->sqlvar[index].relname[0]=(char)NULL;	outsqlda->sqlvar[index].ownname_length=0;	outsqlda->sqlvar[index].ownname[0]=(char)NULL;	outsqlda->sqlvar[index].aliasname_length=0;	outsqlda->sqlvar[index].aliasname[0]=(char)NULL;	return true;}bool firebirdcursor::outputBindDouble(const char *variable,						uint16_t variablesize,						double *value,						uint32_t *precision,						uint32_t *scale,						int16_t *isnull) {	outbindisstring[outbindcount]=false;	outbindcount++;	// if we're doing output binds then the	// query must be a stored procedure	queryIsExecSP=true;	// make bind vars 1 based like all other db's	long	index=charstring::toInteger(variable+1)-1;	if (index<0) {		return false;	}	outsqlda->sqlvar[index].sqltype=SQL_DOUBLE;	outsqlda->sqlvar[index].sqlscale=*scale;	outsqlda->sqlvar[index].sqlsubtype=0;	outsqlda->sqlvar[index].sqllen=sizeof(double);	outsqlda->sqlvar[index].sqldata=(char *)value;	outsqlda->sqlvar[index].sqlind=isnull;	outsqlda->sqlvar[index].sqlname_length=0;	outsqlda->sqlvar[index].sqlname[0]=(char)NULL;	outsqlda->sqlvar[index].relname_length=0;	outsqlda->sqlvar[index].relname[0]=(char)NULL;	outsqlda->sqlvar[index].ownname_length=0;	outsqlda->sqlvar[index].ownname[0]=(char)NULL;	outsqlda->sqlvar[index].aliasname_length=0;	outsqlda->sqlvar[index].aliasname[0]=(char)NULL;	return true;}bool firebirdcursor::executeQuery(const char *query, uint32_t length,							bool execute) {	// for commit or rollback, execute the API call and return	if (querytype==isc_info_sql_stmt_commit) {		return !isc_commit_retaining(firebirdconn->error,							&firebirdconn->tr);	} else if (querytype==isc_info_sql_stmt_rollback) {		return !isc_rollback_retaining(firebirdconn->error,							&firebirdconn->tr);	} else if (queryIsExecSP) {		// if the query is a stored procedure then execute it as such		bool	retval=!isc_dsql_execute2(firebirdconn->error,						&firebirdconn->tr,						&stmt,1,insqlda,outsqlda);

⌨️ 快捷键说明

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