/* * Copyright (C) 2001 Michele Comitini * Copyright (C) 2001 Federico Di Gregorio * * This file is part of the psycopg module. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * module.h -- defines constants needed by the module interface DBAPI 2.0 * $Id: module.h 554 2004-10-30 00:19:27Z fog $ */ #ifndef __PSYCOPG_MODULE__ #define __PSYCOPG_MODULE__ #include #include #include #include #include #include #ifndef _WIN32 #include #else #include #define pthread_mutex_t HANDLE #define pthread_condvar_t HANDLE #define pthread_mutex_lock(object) WaitForSingleObject(object, INFINITE) #define pthread_mutex_unlock(object) ReleaseMutex(object) #define pthread_mutex_destroy(ref) (CloseHandle(ref)) static int pthread_mutex_init(pthread_mutex_t *mutex, void* temp) { *mutex=CreateMutex(NULL, FALSE, NULL); return 0; } #define inline #endif #include "typeobj.h" /**** python 1.5 does not have PyObject_Del ****/ #ifndef PyObject_Del #define PyObject_Del PyMem_DEL #endif /**** PyObject_TypeCheck introduced in 2.2 ****/ #ifndef PyObject_TypeCheck #define PyObject_TypeCheck(o, t) ((o)->ob_type == (t)) #endif /**** globals of the module ****/ #define APILEVEL "2.0" #define THREADSAFETY 2 #define PARAMSTYLE "pyformat" /**** constants of the module ****/ #define MAXCONN 64 #define MINCONN 8 #define MACRO_STR(MACRO) "\"MACRO\"" /**** status of the cursor's keeper ****/ #define KEEPER_READY 0 #define KEEPER_BEGIN 1 #define KEEPER_CONN_LOCK 2 #define KEEPER_CONN_READY 3 #define KEEPER_CONN_BEGIN 4 #define KEEPER_LOCKED -1 /**** debug printf-like function ****/ #if defined( __GNUC__) && !defined(__APPLE__) #ifdef PSYCOTIC_DEBUG #include #include #define Dprintf(fmt, args...) fprintf(stderr, "[%d] " fmt, getpid() , ## args) #else #define Dprintf(fmt, args...) #endif #else /* !__GNUC__ or __APPLE__ */ #ifdef PSYCOTIC_DEBUG #include static void Dprintf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); } #else static void Dprintf(const char *fmt, ...) {} #endif #endif /**** global exceptions ****/ PyObject *Error, *Warning, *InterfaceError, *DatabaseError, *InternalError, *OperationalError, *ProgrammingError, *IntegrityError, *DataError, *NotSupportedError; /**** the connection keeper object, used by cursors and connections to access PGconnection objects ****/ typedef struct { PGconn *pgconn; pthread_mutex_t lock; int refcnt; int status; } connkeeper; /**** the connection object ****/ /* forward declaration of the cursor object */ typedef struct _cursobject cursobject; typedef struct { PyObject_HEAD PyObject *cursors; /* a sequence of cursors on this connection */ PyObject *avail_conn; /* a sequence of avaliable db connections */ pthread_mutex_t lock; /* the global connection lock */ cursobject *stdmanager; /* manager cursor */ char *dsn; int closed; /* 1 if the connection is closed */ int maxconn; /* max connections to db */ int minconn; /* minimum number of open connections */ int isolation_level; /* isolation level */ int serialize; /* serialize cursors? */ } connobject; connobject *new_psyco_connobject(char *dsn, int maxconn, int minconn, int serialize); /**** the cursor object ****/ struct _cursobject { PyObject_HEAD int closed; /* 1 if the cursor is closed, -1 need closing */ int notuples; /* 1 if the command was not a query */ connobject *conn; /* connection owning the cursor */ PyObject *description; /* read-only attribute is a sequence of 7-item sequences.*/ /* read-only attribute specifies the number of rows that the last executeXXX() produced (for DQL statements like select) or affected (for DML statements like update or insert).*/ long int rowcount; /* read/write attribute specifies the number of rows to fetch at a time with fetchmany(). It defaults to 1 meaning to fetch a single row at a time.*/ long int arraysize; /* the row counter for fetch*() */ long int row; /* number of columns fetched from the db */ long int columns; /* postgres stuff */ connkeeper *keeper; /* the connection keeper */ PGconn *pgconn; /* this is a copy of the PGconn in the keeper */ PGresult *pgres; /* an array (tuple) of typecast functions */ PyObject *casts; /* last message from the server after an execute */ PyObject *status; /* last oid from an insert or InvalidOid */ Oid last_oid; /* isolation level for this cursor */ int isolation_level; /* a notice from the backend */ char *notice; /* a critical error, remember to cleanup */ char *critical; }; cursobject *new_psyco_cursobject(connobject *conn, connkeeper *keeper); /**** function type used in execute callbacks ****/ typedef PyObject *(*_psyco_curs_execute_callback)(cursobject *s, PyObject *o); /**** mxDateTime API access ****/ extern mxDateTimeModule_APIObject *mxDateTimeP; /**** transaction control functions ****/ extern int dispose_pgconn(cursobject *self); extern int commit_pgconn(cursobject *self); extern int abort_pgconn(cursobject *self); extern int begin_pgconn(cursobject *self); /**** other globally visible functions ****/ extern void curs_switch_isolation_level(cursobject *self, long int level); extern connkeeper *alloc_keeper(connobject *conn); /**** some usefull macros ****/ /* for methods that must return NULL while the object is closed */ #define EXC_IFCLOSED(self) if ((self)->closed) { \ PyErr_SetString(InterfaceError,"already closed"); \ return NULL; } /* for methods that must return NULL when last query has no output */ #define EXC_IFNOTUPLES(self) if ((self)->notuples) { \ PyErr_SetString(Error,"no results to fetch"); \ return NULL; } /* for methods that extend the dbapi and should raise an exception if not the only owners of the connkeeper */ #define EXC_IFNOTONLY(self) if ((self)->keeper->refcnt != 1) { \ PyErr_SetString(Error,"serialized connection: cannot commit on this cursor"); \ return NULL; } /* check for critical errors */ #define EXC_IFCRITICAL(self) if ((self)->critical) \ return pgconn_resolve_critical(self) /* methods that need to parse arguments but don't use them */ #define PARSEARGS(args) if (args && !PyArg_ParseTuple(args, "")) return NULL /* macro to clean the pg result */ #define IFCLEARPGRES(pgres) if (pgres) { PQclear(pgres); pgres = NULL; } #define CLEARPGRES(pgres) PQclear(pgres); pgres = NULL #endif /* __PSYCOPG_MODULE__ */