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

📄 pqresult.c

📁 适合于Unix/Linux下的一个持久数据库连接池
💻 C
字号:
/*Portions Copyright (c) 1996-2002, The PostgreSQL Global Development Group Portions Copyright (c) 1994, The Regents of the University of CaliforniaPortions Copyright (c) 2003-2004, David MusePermission to use, copy, modify, and distribute this software and its documentation for any purpose, without fee, and without a written agreement is hereby granted, provided that the above copyright notice and this paragraph and the following two paragraphs appear in all copies. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.*/#include <pqdefinitions.h>#include <stdlib.h>#include <rudiments/charstring.h>#define NEED_DATATYPESTRING	1#include <datatypes.h>extern "C" {// lame... I stole this code from sqlrcursorchar	*skipWhitespaceAndComments(const char *querybuffer) {	// scan the query, bypassing whitespace and comments.	char	*ptr=(char *)querybuffer;	while (*ptr && 		(*ptr==' ' || *ptr=='\n' || *ptr=='	' || *ptr=='-')) {		// skip any comments		if (*ptr=='-') {			while (*ptr && *ptr!='\n') {				ptr++;			}		}		ptr++;	}	return ptr;}// lame... I stole this code from sqlrcursor tooint	queryIsNotSelect(const char *querybuffer) {	// scan the query, bypassing whitespace and comments.	char	*ptr=skipWhitespaceAndComments(querybuffer);	// if the query is a select but not a select into then return false,	// otherwise return true	if (!charstring::compareIgnoringCase(ptr,"select",6) && 		charstring::compareIgnoringCase(ptr,"select into ",12)) {		return 0;	}	return 1;}void PQclear(PGresult *res) {	if (res) {		res->parent->nonblockingmode=res->previousnonblockingmode;		delete res->sqlrcur;		delete res;	}}PGresult *PQexec(PGconn *conn, const char *query) {	PGresult	*result=new PGresult;	result->parent=conn;	result->previousnonblockingmode=conn->nonblockingmode;	result->queryisnotselect=1;	delete[] conn->error;	conn->error=NULL;	if (query && query[0]) {		result->sqlrcur=new sqlrcursor(conn->sqlrcon);		result->sqlrcur->copyReferences();		if (conn->removetrailingsemicolons==-1) {			const char	*dbtype=conn->sqlrcon->identify();			if (!dbtype) {				size_t	errorlen=					charstring::length(result->sqlrcur->							errorMessage())+2;				conn->error=new char[errorlen];				snprintf(conn->error,errorlen,"%s\n",					result->sqlrcur->errorMessage());				PQclear(result);				return NULL;			}			// FIXME: it's possible that other non-postgresql			// databases allow trailing semicolons			conn->removetrailingsemicolons=				(!charstring::compare(dbtype,"postgresql"))?0:1;		}		int	length=charstring::length(query);		if (conn->removetrailingsemicolons==1) {			while (query[length-1]==' ' ||				query[length-1]=='	' ||				query[length-1]=='\n' ||				query[length-1]=='\r' ||				query[length-1]==';') {				length--;			}		}		if (result->sqlrcur->sendQuery(query,length)) {			if (queryIsNotSelect(query)) {				result->execstatus=PGRES_COMMAND_OK;			} else {				result->execstatus=PGRES_TUPLES_OK;				result->queryisnotselect=0;			}		} else {			size_t	errorlen=				charstring::length(result->						sqlrcur->errorMessage())+2;			conn->error=new char[errorlen];			snprintf(conn->error,errorlen,					"%s\n",result->sqlrcur->errorMessage());			PQclear(result);			result=NULL;		}	} else {		result->sqlrcur=NULL;		result->execstatus=PGRES_EMPTY_QUERY;	}	return result;}ExecStatusType PQresultStatus(const PGresult *res) {	// FIXME: I'm not sure I should return PGRES_FATAL_ERROR if res is NULL	return (res)?res->execstatus:PGRES_FATAL_ERROR;}char *PQresStatus(ExecStatusType status) {	if (status==PGRES_EMPTY_QUERY) {		return "PGRES_EMPTY_QUERY";	} else if (status==PGRES_COMMAND_OK) {		return "PGRES_COMMAND_OK";	} else if (status==PGRES_TUPLES_OK) {		return "PGRES_TUPLES_OK";	} else if (status==PGRES_COPY_OUT) {		return "PGRES_COPY_OUT";	} else if (status==PGRES_COPY_IN) {		return "PGRES_COPY_IN";	} else if (status==PGRES_BAD_RESPONSE) {		return "PGRES_BAD_RESPONSE";	} else if (status==PGRES_NONFATAL_ERROR) {		return "PGRES_NONFATAL_ERROR";	} else if (status==PGRES_FATAL_ERROR) {		return "PGRES_FATAL_ERROR";	}	return NULL;}char *PQresultErrorMessage(const PGresult *res) {	return const_cast<char *>(res->sqlrcur->errorMessage());}int PQntuples(const PGresult *res) {	return res->sqlrcur->rowCount();}int PQnfields(const PGresult *res) {	return res->sqlrcur->colCount();}int PQbinaryTuples(const PGresult *res) {	// return 1 if result set contains binary data, 0 otherwise	for (uint32_t i=0; i<res->sqlrcur->colCount(); i++) {		if (res->sqlrcur->getColumnIsBinary(i)) {			return 1;		}	}	return 0;}char *PQfname(const PGresult *res, int field_num) {	return const_cast<char *>(res->sqlrcur->getColumnName(field_num));}int PQfnumber(const PGresult *res, const char *field_name) {	for (uint32_t i=0; i<res->sqlrcur->colCount(); i++) {		if (!charstring::compare(field_name,					res->sqlrcur->getColumnName(i))) {			return i;		}	}	return -1;}static Oid postgresqltypemap[]={	// "UNKNOWN"	705,	// addded by freetds	// "CHAR"	18,	// "INT"	23,	// "SMALLINT"	21,	// "TINYINT"	21,	// "MONEY"	790,	// "DATETIME"	1082,	// "NUMERIC"	1700,	// "DECIMAL"	701,	// "SMALLDATETIME"	1082,	// "SMALLMONEY"	790,	// "IMAGE"	26,	// "BINARY"	26,	// "BIT"	1560,	// "REAL"	700,	// "FLOAT"	701,	// "TEXT"	25,	// "VARCHAR"	1043,	// "VARBINARY"	26,	// "LONGCHAR"	26,	// "LONGBINARY"	26,	// "LONG"	26,	// "ILLEGAL"	705,	// "SENSITIVITY"	705,	// "BOUNDARY"	705,	// "VOID"	2278,	// "USHORT"	21,	// added by lago	// "UNDEFINED"	705,	// "DOUBLE"	708,	// "DATE"	1082,	// "TIME"	1083,	// "TIMESTAMP"	1114,	// added by msql	// "UINT"	23,	// "LASTREAL"	700,	// added by mysql	// "STRING"	1042,	// "VARSTRING"	1043,	// "LONGLONG"	20,	// "MEDIUMINT"	23,	// "YEAR"	23,	// "NEWDATE"	1082,	// "NULL"	705,	// "ENUM"	32,	// "SET"	32,	// "TINYBLOB"	26,	// "MEDIUMBLOB"	26,	// "LONGBLOB"	26,	// "BLOB"	26,	// added by oracle	// "VARCHAR2"	1043,	// "NUMBER"	1022,	// "ROWID"	20,	// "RAW"	26,	// "LONG_RAW"	26,	// "MLSLABEL"	26,	// "CLOB"	26,	// "BFILE"	26,	// added by odbc	// "BIGINT"	20,	// "INTEGER"	23,	// "LONGVARBINARY"	26,	// "LONGVARCHAR"	26,	// added by db2	// "GRAPHIC"	26,	// "VARGRAPHIC"	26,	// "LONGVARGRAPHIC"	26,	// "DBCLOB"	26,	// "DATALINK"	26,	// "USER_DEFINED_TYPE"	705,	// "SHORT_DATATYPE"	21,	// "TINY_DATATYPE"	21,	// added by firebird	// "D_FLOAT"	708,	// "ARRAY"	2277,	// "QUAD"	2277,	// "INT64"	20,	// "DOUBLE PRECISION"	708,	// added by postgresql	// "BOOL"	16,	// "BYTEA"	17,	// "NAME"	19,	// "INT8"	20,	// "INT2"	21,	// "INT2VECTOR"	22,	// "INT4"	23,	// "REGPROC"	24,	// "OID"	26,	// "TID"	27,	// "XID"	28,	// "CID"	29,	// "OIDVECTOR"	30,	// "SMGR"	210,	// "POINT"	600,	// "LSEG"	601,	// "PATH"	602,	// "BOX"	603,	// "POLYGON"	604,	// "LINE"	628,	// "_LINE"	629,	// "FLOAT4"	700,	// "FLOAT8"	701,	// "ABSTIME"	702,	// "RELTIME"	703,	// "TINTERVAL"	704,	// "CIRCLE"	718,	// "_CIRCLE"	719,	// "_MONEY"	791,	// "MACADDR"	829,	// "INET"	869,	// "CIDR"	650,	// "_BOOL"	1000,	// "_BYTEA"	1001,	// "_CHAR"	1002,	// "_NAME"	1003,	// "_INT2"	1005,	// "_INT2VECTOR"	1006,	// "_INT4"	1007,	// "_REGPROC"	1008,	// "_TEXT"	1009,	// "_oid"	1028,	// "_TID"	1010,	// "_XID"	1011,	// "_CID"	1012,	// "_OIDVECTOR"	1013,	// "_BPCHAR"	1014,	// "_VARCHAR"	1015,	// "_INT8"	1016,	// "_POINT"	1017,	// "_LSEG"	1018,	// "_PATH"	1019,	// "_BOX"	1020,	// "_FLOAT4"	1021,	// "_FLOAT8"	1022,	// "_ABSTIME"	1023,	// "_RELTIME"	1024,	// "_TINTERVAL"	1025,	// "_POLYGON"	1027,	// "ACLITEM"	1033,	// "_ACLITEM"	1034,	// "_MACADDR"	1040,	// "_INET"	1041,	// "_CIDR"	651,	// "BPCHAR"	1042,	// "_TIMESTAMP"	1114,	// "_DATE"	1182,	// "_TIME"	1183,	// "TIMESTAMPTZ"	1184,	// "_TIMESTAMPTZ"	1185,	// "INTERVAL"	1186,	// "_INTERVAL"	1187,	// "_NUMERIC"	1231,	// "TIMETZ"	1266,	// "_TIMETZ"	1270,	// "_BIT"	1561,	// "VARBIT"	1562,	// "_VARBIT"	1563,	// "REFCURSOR"	1790,	// "_REFCURSOR"	2201,	// "REGPROCEDURE"	2202,	// "REGOPER"	2203,	// "REGOPERATOR"	2204,	// "REGCLASS"	2205,	// "REGTYPE"	2206,	// "_REGPROCEDURE"	2207,	// "_REGOPER"	2208,	// "_REGOPERATOR"	2209,	// "_REGCLASS"	2210,	// "_REGTYPE"	2211,	// "RECORD"	2249,	// "CSTRING"	2275,	// "ANY"	2276,	// "ANYARRAY"	2277,	// "TRIGGER"	2279,	// "LANGUAGE_HANDLER"	2280,	// "INTERNAL"	2281,	// "OPAQUE"	2282	// none added by sqlite};Oid PQftype(const PGresult *res, int field_num) {	// if the type is numeric then we're using a postgresql database and	// typemangling is turned off, so we'll just return the type	const char	*columntype=res->sqlrcur->getColumnType(field_num);	Oid	oid=charstring::toInteger(columntype);	if (oid) {		return oid;	}		// if the type is not numeric, then we need to translate to a type	// number	for (int index=0; datatypestring[index]; index++) {		if (!charstring::compareIgnoringCase(datatypestring[index],								columntype)) {			return postgresqltypemap[index];		}	}	// if it wasn't found, return 705 for unknown type	return 705;}int PQfsize(const PGresult *res, int field_num) {	// for char/varchar fields, return -1,	// otherwise, return the column length	Oid	oid=PQftype(res,field_num);	return (oid==1042 || oid==1043)?		-1:(int)res->sqlrcur->getColumnLength(field_num);}int PQfmod(const PGresult *res, int field_num) {	// for char/varchar fields, return the column length,	// otherwise, return -1	Oid	oid=PQftype(res,field_num);	return (oid==1042 || oid==1043)?		(int)res->sqlrcur->getColumnLength(field_num):-1;}char *PQcmdStatus(PGresult *res) {	// should return a string represeting the "command type" like:	//	SELECT, INSERT, UPDATE, DROP, etc.	if (res->queryisnotselect) {		return "";	} else {		return "SELECT";	}}char *PQoidStatus(const PGresult *res) {	// return OID of tuple if query was an insert,	// otherwise return InvalidOid	return "InvalidOid";}Oid PQoidValue(const PGresult *res) {	// return OID of tuple if query was an insert,	// otherwise return InvalidOid	return InvalidOid;}char *PQcmdTuples(PGresult *res) {	return charstring::parseNumber(res->sqlrcur->affectedRows());}char *PQgetvalue(const PGresult *res, int tup_num, int field_num) {	return const_cast<char *>(res->sqlrcur->getField(tup_num,field_num));}int PQgetlength(const PGresult *res, int tup_num, int field_num) {	return res->sqlrcur->getFieldLength(tup_num,field_num);}int PQgetisnull(const PGresult *res, int tup_num, int field_num) {	return (res->sqlrcur->getField(tup_num,field_num)==(char *)NULL);}PGresult *PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status) {	// Make an empty PGresult with given status (some apps find this	// useful). If conn is not NULL and status indicates an error, the	// conn's errorMessage is copied.	PGresult	*result=new PGresult;	result->sqlrcur=NULL;	result->execstatus=status;	result->parent=conn;	result->previousnonblockingmode=conn->nonblockingmode;	return result;}}

⌨️ 快捷键说明

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