📄 pgmodule.c
字号:
/* * PyGres, version 2.2 A Python interface for PostgreSQL database. Written by * D'Arcy J.M. Cain, (darcy@druid.net). Based heavily on code written by * Pascal Andre, andre@chimay.via.ecp.fr. Copyright (c) 1995, Pascal Andre * (andre@via.ecp.fr). * * Permission 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 or in * any new file that contains a substantial portion of this file. * * IN NO EVENT SHALL THE AUTHOR 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 * AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE AUTHOR 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 * AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, * ENHANCEMENTS, OR MODIFICATIONS. * * Further modifications copyright 1997, 1998, 1999 by D'Arcy J.M. Cain * (darcy@druid.net) subject to the same terms and conditions as above. * */#include <Python.h>#include <libpq-fe.h>#include <libpq/libpq-fs.h>#include <stdio.h>#include <stdlib.h>#include <string.h>/* really bad stuff here - I'm so naughty *//* If you need to you can run mkdefines to get *//* current defines but it should not have changed */#define INT2OID 21#define INT4OID 23#define OIDOID 26#define FLOAT4OID 700#define FLOAT8OID 701#define CASHOID 790static PyObject *PGError;static const char *PyPgVersion = "2.4";/* taken from fileobject.c */#define BUF(v) PyString_AS_STRING((PyStringObject *)(v))/* default values */#define MODULE_NAME "pgsql"#define ARRAYSIZE 1/* flags for object validity checks */#define CHECK_OPEN 1#define CHECK_CLOSE 2#define CHECK_CNX 4#define CHECK_RESULT 8#define CHECK_DQL 16#define MAX_BUFFER_SIZE 8192 /* maximum transaction size */#ifndef NO_DIRECT#define DIRECT_ACCESS 1 /* enables direct access functions */#endif /* NO_DIRECT */#ifndef NO_LARGE#define LARGE_OBJECTS 1 /* enables large objects support */#endif /* NO_LARGE */#ifndef NO_DEF_VAR#define DEFAULT_VARS 1 /* enables default variables use */#endif /* NO_DEF_VAR *//* --------------------------------------------------------------------- *//* MODULE GLOBAL VARIABLES */#ifdef DEFAULT_VARSstatic PyObject *pg_default_host; /* default database host */static PyObject *pg_default_base; /* default database name */static PyObject *pg_default_opt;/* default connection options */static PyObject *pg_default_tty;/* default debug tty */static PyObject *pg_default_port; /* default connection port */static PyObject *pg_default_user; /* default username */static PyObject *pg_default_passwd; /* default password */#endif /* DEFAULT_VARS *//* --------------------------------------------------------------------- *//* OBJECTS DECLARATION *//* pg connection object */typedef struct{ PyObject_HEAD int valid; /* validity flag */ PGconn *cnx; /* PostGres connection handle */} pgobject;staticforward PyTypeObject PgType;#define is_pgobject(v) ((v)->ob_type == &PgType)/* pg query object */typedef struct{ PyObject_HEAD PGresult *last_result; /* last result content */} pgqueryobject;staticforward PyTypeObject PgQueryType;#define is_pgqueryobject(v) ((v)->ob_type == &PgQueryType)#ifdef LARGE_OBJECTS/* pg large object */typedef struct{ PyObject_HEAD pgobject * pgcnx; /* parent connection object */ Oid lo_oid; /* large object oid */ int lo_fd; /* large object fd */} pglargeobject;staticforward PyTypeObject PglargeType;#define is_pglargeobject(v) ((v)->ob_type == &PglargeType)#endif /* LARGE_OBJECTS *//* --------------------------------------------------------------------- *//* INTERNAL FUNCTIONS *//* checks connection validity */static intcheck_cnx_obj(pgobject * self){ if (!self->valid) { PyErr_SetString(PGError, "connection has been closed"); return 0; } return 1;}#ifdef LARGE_OBJECTS/* checks large object validity */static intcheck_lo_obj(pglargeobject * self, int level){ if (!check_cnx_obj(self->pgcnx)) return 0; if (!self->lo_oid) { PyErr_SetString(PGError, "object is not valid (null oid)."); return 0; } if (level & CHECK_OPEN) { if (self->lo_fd < 0) { PyErr_SetString(PyExc_IOError, "object is not opened."); return 0; } } if (level & CHECK_CLOSE) { if (self->lo_fd >= 0) { PyErr_SetString(PyExc_IOError, "object is already opened."); return 0; } } return 1;}#endif /* LARGE_OBJECTS *//* --------------------------------------------------------------------- *//* PG CONNECTION OBJECT IMPLEMENTATION */#ifdef LARGE_OBJECTS/* constructor (internal use only) */static pglargeobject *pglarge_new(pgobject * pgcnx, Oid oid){ pglargeobject *npglo; if ((npglo = PyObject_NEW(pglargeobject, &PglargeType)) == NULL) return NULL; Py_XINCREF(pgcnx); npglo->pgcnx = pgcnx; npglo->lo_fd = -1; npglo->lo_oid = oid; return npglo;}/* destructor */static voidpglarge_dealloc(pglargeobject * self){ if (self->lo_fd >= 0 && check_cnx_obj(self->pgcnx)) lo_close(self->pgcnx->cnx, self->lo_fd); Py_XDECREF(self->pgcnx); PyMem_DEL(self);}/* opens large object */static char pglarge_open__doc__[] ="open(mode) -- open access to large object with specified mode ""(INV_READ, INV_WRITE constants defined by module).";static PyObject *pglarge_open(pglargeobject * self, PyObject * args){ int mode, fd; /* check validity */ if (!check_lo_obj(self, CHECK_CLOSE)) return NULL; /* gets arguments */ if (!PyArg_ParseTuple(args, "i", &mode)) { PyErr_SetString(PyExc_TypeError, "open(mode), with mode(integer)."); return NULL; } /* opens large object */ if ((fd = lo_open(self->pgcnx->cnx, self->lo_oid, mode)) < 0) { PyErr_SetString(PyExc_IOError, "can't open large object."); return NULL; } self->lo_fd = fd; /* no error : returns Py_None */ Py_INCREF(Py_None); return Py_None;}/* close large object */static char pglarge_close__doc__[] ="close() -- close access to large object data.";static PyObject *pglarge_close(pglargeobject * self, PyObject * args){ /* checks args */ if (!PyArg_ParseTuple(args, "")) { PyErr_SetString(PyExc_SyntaxError, "method close() takes no parameters."); return NULL; } /* checks validity */ if (!check_lo_obj(self, CHECK_OPEN)) return NULL; /* closes large object */ if (lo_close(self->pgcnx->cnx, self->lo_fd)) { PyErr_SetString(PyExc_IOError, "error while closing large object fd."); return NULL; } self->lo_fd = -1; /* no error : returns Py_None */ Py_INCREF(Py_None); return Py_None;}/* reads from large object */static char pglarge_read__doc__[] ="read(integer) -- read from large object to sized string. ""Object must be opened in read mode before calling this method.";static PyObject *pglarge_read(pglargeobject * self, PyObject * args){ int size; PyObject *buffer; /* checks validity */ if (!check_lo_obj(self, CHECK_OPEN)) return NULL; /* gets arguments */ if (!PyArg_ParseTuple(args, "i", &size)) { PyErr_SetString(PyExc_TypeError, "read(size), wih size (integer)."); return NULL; } if (size <= 0) { PyErr_SetString(PyExc_ValueError, "size must be positive."); return NULL; } /* allocate buffer and runs read */ buffer = PyString_FromStringAndSize((char *) NULL, size); if ((size = lo_read(self->pgcnx->cnx, self->lo_fd, BUF(buffer), size)) < 0) { PyErr_SetString(PyExc_IOError, "error while reading."); Py_XDECREF(buffer); return NULL; } /* resize buffer and returns it */ _PyString_Resize(&buffer, size); return buffer;}/* write to large object */static char pglarge_write__doc__[] ="write(string) -- write sized string to large object. ""Object must be opened in read mode before calling this method.";static PyObject *pglarge_write(pglargeobject * self, PyObject * args){ char *buffer; int size; /* checks validity */ if (!check_lo_obj(self, CHECK_OPEN)) return NULL; /* gets arguments */ if (!PyArg_ParseTuple(args, "s", &buffer)) { PyErr_SetString(PyExc_TypeError, "write(buffer), with buffer (sized string)."); return NULL; } /* sends query */ if ((size = lo_write(self->pgcnx->cnx, self->lo_fd, buffer, strlen(buffer))) < strlen(buffer)) { PyErr_SetString(PyExc_IOError, "buffer truncated during write."); return NULL; } /* no error : returns Py_None */ Py_INCREF(Py_None); return Py_None;}/* go to position in large object */static char pglarge_seek__doc__[] ="seek(off, whence) -- move to specified position. Object must be opened ""before calling this method. whence can be SEEK_SET, SEEK_CUR or SEEK_END, ""constants defined by module.";static PyObject *pglarge_lseek(pglargeobject * self, PyObject * args){ /* offset and whence are initialized to keep compiler happy */ int ret, offset = 0, whence = 0; /* checks validity */ if (!check_lo_obj(self, CHECK_OPEN)) return NULL; /* gets arguments */ if (!PyArg_ParseTuple(args, "ii", &offset, &whence)) { PyErr_SetString(PyExc_TypeError, "lseek(offset, whence), with offset and whence (integers)."); return NULL; } /* sends query */ if ((ret = lo_lseek(self->pgcnx->cnx, self->lo_fd, offset, whence)) == -1) { PyErr_SetString(PyExc_IOError, "error while moving cursor."); return NULL; } /* returns position */ return PyInt_FromLong(ret);}/* gets large object size */static char pglarge_size__doc__[] ="size() -- return large object size. ""Object must be opened before calling this method.";static PyObject *pglarge_size(pglargeobject * self, PyObject * args){ int start, end; /* checks args */ if (!PyArg_ParseTuple(args, "")) { PyErr_SetString(PyExc_SyntaxError, "method size() takes no parameters."); return NULL; } /* checks validity */ if (!check_lo_obj(self, CHECK_OPEN)) return NULL; /* gets current position */ if ((start = lo_tell(self->pgcnx->cnx, self->lo_fd)) == -1) { PyErr_SetString(PyExc_IOError, "error while getting current position."); return NULL; } /* gets end position */ if ((end = lo_lseek(self->pgcnx->cnx, self->lo_fd, 0, SEEK_END)) == -1) { PyErr_SetString(PyExc_IOError, "error while getting end position."); return NULL; } /* move back to start position */ if ((start = lo_lseek(self->pgcnx->cnx, self->lo_fd, start, SEEK_SET)) == -1) { PyErr_SetString(PyExc_IOError, "error while moving back to first position."); return NULL; } /* returns size */ return PyInt_FromLong(end);}/* gets large object cursor position */static char pglarge_tell__doc__[] ="tell() -- give current position in large object. ""Object must be opened before calling this method.";static PyObject *pglarge_tell(pglargeobject * self, PyObject * args){ int start; /* checks args */ if (!PyArg_ParseTuple(args, "")) { PyErr_SetString(PyExc_SyntaxError, "method tell() takes no parameters."); return NULL; } /* checks validity */ if (!check_lo_obj(self, CHECK_OPEN)) return NULL; /* gets current position */ if ((start = lo_tell(self->pgcnx->cnx, self->lo_fd)) == -1) { PyErr_SetString(PyExc_IOError, "error while getting position."); return NULL; } /* returns size */ return PyInt_FromLong(start);}/* exports large object as unix file */static char pglarge_export__doc__[] ="export(string) -- export large object data to specified file. ""Object must be closed when calling this method.";static PyObject *pglarge_export(pglargeobject * self, PyObject * args){ char *name; /* checks validity */ if (!check_lo_obj(self, CHECK_CLOSE)) return NULL; /* gets arguments */ if (!PyArg_ParseTuple(args, "s", &name)) { PyErr_SetString(PyExc_TypeError, "export(filename), with filename (string)."); return NULL; } /* runs command */ if (!lo_export(self->pgcnx->cnx, self->lo_oid, name)) { PyErr_SetString(PyExc_IOError, "error while exporting large object."); return NULL; } Py_INCREF(Py_None); return Py_None;}/* deletes a large object */static char pglarge_unlink__doc__[] ="unlink() -- destroy large object. ""Object must be closed when calling this method.";static PyObject *pglarge_unlink(pglargeobject * self, PyObject * args){ /* checks args */ if (!PyArg_ParseTuple(args, "")) { PyErr_SetString(PyExc_SyntaxError, "method unlink() takes no parameters."); return NULL; } /* checks validity */ if (!check_lo_obj(self, CHECK_CLOSE)) return NULL; /* deletes the object, invalidate it on success */ if (!lo_unlink(self->pgcnx->cnx, self->lo_oid)) { PyErr_SetString(PyExc_IOError, "error while unlinking large object"); return NULL; } self->lo_oid = 0; Py_INCREF(Py_None); return Py_None;}/* large object methods */static struct PyMethodDef pglarge_methods[] = { {"open", (PyCFunction) pglarge_open, 1, pglarge_open__doc__}, {"close", (PyCFunction) pglarge_close, 1, pglarge_close__doc__}, {"read", (PyCFunction) pglarge_read, 1, pglarge_read__doc__}, {"write", (PyCFunction) pglarge_write, 1, pglarge_write__doc__}, {"seek", (PyCFunction) pglarge_lseek, 1, pglarge_seek__doc__}, {"size", (PyCFunction) pglarge_size, 1, pglarge_size__doc__}, {"tell", (PyCFunction) pglarge_tell, 1, pglarge_tell__doc__}, {"export", (PyCFunction) pglarge_export, 1, pglarge_export__doc__}, {"unlink", (PyCFunction) pglarge_unlink, 1, pglarge_unlink__doc__}, {NULL, NULL}};/* get attribute */static PyObject *pglarge_getattr(pglargeobject * self, char *name){ /* list postgreSQL large object fields */ /* associated pg connection object */ if (!strcmp(name, "pgcnx")) { if (check_lo_obj(self, 0))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -