postgresql/src/interfaces/python/pgmodule.c

3258 lines
72 KiB
C
Raw Normal View History

1999-05-17 02:15:31 -04:00
/*
* 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).
1999-05-25 12:15:34 -04:00
*
1999-05-17 02:15:31 -04:00
* 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.
1999-05-25 12:15:34 -04:00
*
1999-05-17 02:15:31 -04:00
* 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.
1999-05-25 12:15:34 -04:00
*
1999-05-17 02:15:31 -04:00
* 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.
1999-05-25 12:15:34 -04:00
*
* Further modifications copyright 1997, 1998, 1999 by D'Arcy J.M. Cain
* (darcy@druid.net) subject to the same terms and conditions as above.
1999-05-25 12:15:34 -04:00
*
1999-05-17 02:15:31 -04:00
*/
#include <Python.h>
#include "postgres.h"
#include "libpq-fe.h"
#include "libpq/libpq-fs.h"
#include "catalog/pg_type.h"
1999-05-17 02:15:31 -04:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* PyObject_Del does not exist in older versions of Python. */
#if PY_VERSION_HEX < 0x01060000
#define PyObject_Del(op) PyMem_DEL((op))
#endif
2001-03-21 23:01:46 -05:00
static PyObject *PGError;
static const char *PyPgVersion = "3.4 (beta)";
1999-05-17 02:15:31 -04:00
/* taken from fileobject.c */
#define BUF(v) PyString_AS_STRING((PyStringObject *)(v))
/* default values */
2001-03-21 23:01:46 -05:00
#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
1999-05-17 02:15:31 -04:00
/* query result types */
#define RESULT_EMPTY 1
#define RESULT_DML 2
#define RESULT_DDL 3
#define RESULT_DQL 4
/* flags for move methods */
#define QUERY_MOVEFIRST 1
#define QUERY_MOVELAST 2
#define QUERY_MOVENEXT 3
#define QUERY_MOVEPREV 4
/* moves names for errors */
const char *__movename[5] =
2001-03-21 23:01:46 -05:00
{"", "movefirst", "movelast", "movenext", "moveprev"};
2001-03-21 23:01:46 -05:00
#define MAX_BUFFER_SIZE 8192 /* maximum transaction size */
1999-05-17 02:15:31 -04:00
#ifndef NO_DIRECT
#define DIRECT_ACCESS 1 /* enables direct access functions */
#endif /* NO_DIRECT */
1999-05-17 02:15:31 -04:00
#ifndef NO_LARGE
#define LARGE_OBJECTS 1 /* enables large objects support */
#endif /* NO_LARGE */
1999-05-17 02:15:31 -04:00
#ifndef NO_DEF_VAR
#define DEFAULT_VARS 1 /* enables default variables use */
#endif /* NO_DEF_VAR */
1999-05-17 02:15:31 -04:00
2001-03-15 06:26:22 -05:00
#ifdef MS_WIN32
#define NO_SNPRINTF 1
#endif
1999-05-17 02:15:31 -04:00
/* --------------------------------------------------------------------- */
/* MODULE GLOBAL VARIABLES */
#ifdef DEFAULT_VARS
2001-03-21 23:01:46 -05:00
static 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 */
2001-03-21 23:01:46 -05:00
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 */
1999-05-17 02:15:31 -04:00
2001-07-11 18:00:57 -04:00
DL_EXPORT(void) init_pg(void);
int *get_type_array(PGresult *result, int nfields);
2001-07-11 18:00:57 -04:00
1999-05-17 02:15:31 -04:00
/* --------------------------------------------------------------------- */
/* OBJECTS DECLARATION */
/* pg connection object */
typedef struct
{
PyObject_HEAD
1999-05-25 12:15:34 -04:00
int valid; /* validity flag */
2001-03-21 23:01:46 -05:00
PGconn *cnx; /* PostGres connection handle */
PGresult *last_result; /* last result content */
} pgobject;
1999-05-17 02:15:31 -04:00
staticforward PyTypeObject PgType;
#define is_pgobject(v) ((v)->ob_type == &PgType)
static PyObject *
pgobject_New(void)
{
2001-03-21 23:01:46 -05:00
pgobject *pgobj;
if ((pgobj = PyObject_NEW(pgobject, &PgType)) == NULL)
return NULL;
pgobj->valid = 1;
pgobj->last_result = NULL;
pgobj->cnx = NULL;
2001-03-21 23:01:46 -05:00
return (PyObject *) pgobj;
}
1999-05-17 02:15:31 -04:00
/* pg query object */
typedef struct
{
PyObject_HEAD
2001-03-21 23:01:46 -05:00
PGresult *last_result; /* last result content */
int result_type; /* type of previous result */
long current_pos; /* current position in last result */
long num_rows; /* number of (affected) rows */
} pgqueryobject;
1999-05-17 02:15:31 -04:00
staticforward PyTypeObject PgQueryType;
#define is_pgqueryobject(v) ((v)->ob_type == &PgQueryType)
/* pg source object */
typedef struct
{
PyObject_HEAD
2001-03-21 23:01:46 -05:00
int valid; /* validity flag */
pgobject *pgcnx; /* parent connection object */
PGresult *last_result; /* last result content */
int result_type; /* result type (DDL/DML/DQL) */
long arraysize; /* array size for fetch method */
int current_row; /* current selected row */
int max_row; /* number of rows in the result */
int num_fields; /* number of fields in each row */
} pgsourceobject;
staticforward PyTypeObject PgSourceType;
#define is_pgsourceobject(v) ((v)->ob_type == &PgSourceType)
1999-05-17 02:15:31 -04:00
#ifdef LARGE_OBJECTS
/* pg large object */
typedef struct
{
PyObject_HEAD
pgobject * pgcnx; /* parent connection object */
2001-03-21 23:01:46 -05:00
Oid lo_oid; /* large object oid */
int lo_fd; /* large object fd */
} pglargeobject;
1999-05-17 02:15:31 -04:00
staticforward PyTypeObject PglargeType;
#define is_pglargeobject(v) ((v)->ob_type == &PglargeType)
#endif /* LARGE_OBJECTS */
1999-05-17 02:15:31 -04:00
/* --------------------------------------------------------------------- */
/* INTERNAL FUNCTIONS */
/* checks connection validity */
static int
check_cnx_obj(pgobject * self)
{
2001-03-21 23:01:46 -05:00
if (!self->valid)
{
PyErr_SetString(PGError, "connection has been closed");
return 0;
}
return 1;
}
1999-05-17 02:15:31 -04:00
#ifdef LARGE_OBJECTS
/* checks large object validity */
1999-05-17 02:15:31 -04:00
static int
check_lo_obj(pglargeobject * self, int level)
1999-05-17 02:15:31 -04:00
{
if (!check_cnx_obj(self->pgcnx))
return 0;
1999-05-17 02:15:31 -04:00
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 */
/* checks source object validity */
static int
check_source_obj(pgsourceobject * self, int level)
{
if (!self->valid)
{
PyErr_SetString(PGError, "object has been closed");
return 0;
}
if ((level & CHECK_RESULT) && self->last_result == NULL)
{
PyErr_SetString(PGError, "no result.");
return 0;
}
if ((level & CHECK_DQL) && self->result_type != RESULT_DQL)
{
PyErr_SetString(PGError, "last query did not return tuples.");
return 0;
}
if ((level & CHECK_CNX) && !check_cnx_obj(self->pgcnx))
return 0;
return 1;
}
/* shared functions for converting PG types to Python types */
int *
get_type_array(PGresult *result, int nfields)
{
2001-03-21 23:01:46 -05:00
int *typ;
int j;
if ((typ = malloc(sizeof(int) * nfields)) == NULL)
{
PyErr_SetString(PyExc_SyntaxError, "memory error in getresult().");
return NULL;
}
for (j = 0; j < nfields; j++)
{
switch (PQftype(result, j))
{
case INT2OID:
case INT4OID:
case OIDOID:
typ[j] = 1;
break;
case INT8OID:
typ[j] = 2;
break;
case FLOAT4OID:
case FLOAT8OID:
case NUMERICOID:
typ[j] = 3;
break;
case CASHOID:
typ[j] = 4;
break;
default:
typ[j] = 5;
break;
}
}
return typ;
}
/* prototypes for constructors */
2001-03-21 23:01:46 -05:00
static pgsourceobject *pgsource_new(pgobject * pgcnx);
/* --------------------------------------------------------------------- */
/* PG SOURCE OBJECT IMPLEMENTATION */
/* constructor (internal use only) */
static pgsourceobject *
pgsource_new(pgobject * pgcnx)
{
2001-03-21 23:01:46 -05:00
pgsourceobject *npgobj;
/* allocates new query object */
if ((npgobj = PyObject_NEW(pgsourceobject, &PgSourceType)) == NULL)
return NULL;
/* initializes internal parameters */
Py_XINCREF(pgcnx);
npgobj->pgcnx = pgcnx;
npgobj->last_result = NULL;
npgobj->valid = 1;
npgobj->arraysize = ARRAYSIZE;
return npgobj;
}
/* destructor */
static void
pgsource_dealloc(pgsourceobject * self)
{
if (self->last_result)
PQclear(self->last_result);
Py_XDECREF(self->pgcnx);
PyObject_Del(self);
}
/* closes object */
static char pgsource_close__doc__[] =
"close() -- close query object without deleting it. "
"All instances of the query object can no longer be used after this call.";
static PyObject *
pgsource_close(pgsourceobject * self, PyObject * args)
{
/* checks args */
if (!PyArg_ParseTuple(args, ""))
{
PyErr_SetString(PyExc_TypeError, "method close() takes no parameter.");
return NULL;
}
/* frees result if necessary and invalidates object */
if (self->last_result)
{
PQclear(self->last_result);
self->result_type = RESULT_EMPTY;
self->last_result = NULL;
}
self->valid = 0;
/* return None */
Py_INCREF(Py_None);
return Py_None;
}
/* database query */
static char pgsource_execute__doc__[] =
"execute(sql) -- execute a SQL statement (string).\n "
"On success, this call returns the number of affected rows, "
"or None for DQL (SELECT, ...) statements.\n"
"The fetch (fetch(), fetchone() and fetchall()) methods can be used "
"to get result rows.";
static PyObject *
pgsource_execute(pgsourceobject * self, PyObject * args)
{
2001-03-21 23:01:46 -05:00
char *query;
const char *temp;
long num_rows;
/* checks validity */
if (!check_source_obj(self, CHECK_CNX))
return NULL;
/* get query args */
if (!PyArg_ParseTuple(args, "s", &query))
{
PyErr_SetString(PyExc_TypeError, "execute(sql), with sql (string).");
return NULL;
}
/* frees previous result */
if (self->last_result)
{
PQclear(self->last_result);
self->last_result = NULL;
}
self->max_row = 0;
self->current_row = 0;
self->num_fields = 0;
/* gets result */
Py_BEGIN_ALLOW_THREADS
2001-03-21 23:01:46 -05:00
self->last_result = PQexec(self->pgcnx->cnx, query);
Py_END_ALLOW_THREADS
/* checks result validity */
2001-03-21 23:01:46 -05:00
if (!self->last_result)
{
PyErr_SetString(PyExc_ValueError, PQerrorMessage(self->pgcnx->cnx));
return NULL;
}
/* checks result status */
switch (PQresultStatus(self->last_result))
{
2001-03-21 23:01:46 -05:00
/* query succeeded */
case PGRES_TUPLES_OK: /* DQL: returns None (DB-SIG compliant) */
self->result_type = RESULT_DQL;
self->max_row = PQntuples(self->last_result);
self->num_fields = PQnfields(self->last_result);
Py_INCREF(Py_None);
return Py_None;
case PGRES_COMMAND_OK: /* other requests */
case PGRES_COPY_OUT:
case PGRES_COPY_IN:
self->result_type = RESULT_DDL;
temp = PQcmdTuples(self->last_result);
num_rows = 1;
if (temp[0] != 0)
{
self->result_type = RESULT_DML;
num_rows = atol(temp);
}
return PyInt_FromLong(num_rows);
/* query failed */
case PGRES_EMPTY_QUERY:
PyErr_SetString(PyExc_ValueError, "empty query.");
break;
case PGRES_BAD_RESPONSE:
case PGRES_FATAL_ERROR:
case PGRES_NONFATAL_ERROR:
PyErr_SetString(PGError, PQerrorMessage(self->pgcnx->cnx));
break;
default:
PyErr_SetString(PGError, "internal error: "
"unknown result status.");
break;
}
/* frees result and returns error */
PQclear(self->last_result);
self->last_result = NULL;
self->result_type = RESULT_EMPTY;
return NULL;
}
/* gets oid status for last query (valid for INSERTs, 0 for other) */
static char pgsource_oidstatus__doc__[] =
"oidstatus() -- return oid of last inserted row (if available).";
static PyObject *
pgsource_oidstatus(pgsourceobject * self, PyObject * args)
{
long oid;
/* checks validity */
if (!check_source_obj(self, CHECK_RESULT))
return NULL;
/* checks args */
if ((args != NULL) && (!PyArg_ParseTuple(args, "")))
{
PyErr_SetString(PyExc_SyntaxError,
2001-03-21 23:01:46 -05:00
"method oidstatus() takes no parameters.");
return NULL;
}
/* retrieves oid status */
if ((oid = PQoidValue(self->last_result)) == InvalidOid)
oid = 0;
return PyInt_FromLong(oid);
}
/* fetches rows from last result */
static char pgsource_fetch__doc__[] =
"fetch(num) -- return the next num rows from the last result in a list. "
"If num parameter is omitted arraysize attribute value is used. "
"If size equals -1, all rows are fetched.";
static PyObject *
pgsource_fetch(pgsourceobject * self, PyObject * args)
{
2001-03-21 23:01:46 -05:00
PyObject *rowtuple,
*reslist,
*str;
int i,
j;
long size;
/* checks validity */
if (!check_source_obj(self, CHECK_RESULT | CHECK_DQL))
return NULL;
/* checks args */
size = self->arraysize;
if (!PyArg_ParseTuple(args, "|l", &size))
{
PyErr_SetString(PyExc_SyntaxError,
2001-03-21 23:01:46 -05:00
"fetch(num), with num (integer, optional).");
return NULL;
}
/* seeks last line */
/* limit size to be within the amount of data we actually have */
if (size == -1 || (self->max_row - self->current_row) < size)
size = self->max_row - self->current_row;
/* allocate list for result */
if ((reslist = PyList_New(0)) == NULL)
return NULL;
/* builds result */
for (i = 0; i < size; ++i)
{
if ((rowtuple = PyTuple_New(self->num_fields)) == NULL)
{
Py_DECREF(reslist);
return NULL;
}
for (j = 0; j < self->num_fields; j++)
{
if (PQgetisnull(self->last_result, self->current_row, j))
{
Py_INCREF(Py_None);
str = Py_None;
}
else
str = PyString_FromString(PQgetvalue(self->last_result, self->current_row, j));
PyTuple_SET_ITEM(rowtuple, j, str);
}
PyList_Append(reslist, rowtuple);
Py_DECREF(rowtuple);
self->current_row++;
}
return reslist;
}
/* changes current row (internal wrapper for all "move" methods) */
static PyObject *
pgsource_move(pgsourceobject * self, PyObject * args, int move)
{
/* checks validity */
if (!check_source_obj(self, CHECK_RESULT | CHECK_DQL))
return NULL;
/* checks args */
if (!PyArg_ParseTuple(args, ""))
{
2001-03-21 23:01:46 -05:00
char errbuf[256];
#ifdef NO_SNPRINTF
sprintf(errbuf, "method %s() takes no parameter.", __movename[move]);
#else
snprintf(errbuf, sizeof(errbuf),
2001-03-21 23:01:46 -05:00
"method %s() takes no parameter.", __movename[move]);
#endif
PyErr_SetString(PyExc_SyntaxError, errbuf);
return NULL;
}
/* changes the current row */
2001-03-21 23:01:46 -05:00
switch (move)
{
case QUERY_MOVEFIRST:
self->current_row = 0;
break;
case QUERY_MOVELAST:
self->current_row = self->max_row - 1;
break;
case QUERY_MOVENEXT:
if (self->current_row != self->max_row)
self->current_row++;
break;
case QUERY_MOVEPREV:
if (self->current_row > 0)
self->current_row--;
break;
}
Py_INCREF(Py_None);
return Py_None;
}
/* move to first result row */
static char pgsource_movefirst__doc__[] =
"movefirst() -- move to first result row.";
static PyObject *
pgsource_movefirst(pgsourceobject * self, PyObject * args)
{
return pgsource_move(self, args, QUERY_MOVEFIRST);
}
/* move to last result row */
static char pgsource_movelast__doc__[] =
"movelast() -- move to last valid result row.";
static PyObject *
pgsource_movelast(pgsourceobject * self, PyObject * args)
{
return pgsource_move(self, args, QUERY_MOVELAST);
}
/* move to next result row */
static char pgsource_movenext__doc__[] =
"movenext() -- move to next result row.";
static PyObject *
pgsource_movenext(pgsourceobject * self, PyObject * args)
{
return pgsource_move(self, args, QUERY_MOVENEXT);
}
/* move to previous result row */
static char pgsource_moveprev__doc__[] =
"moveprev() -- move to previous result row.";
static PyObject *
pgsource_moveprev(pgsourceobject * self, PyObject * args)
{
return pgsource_move(self, args, QUERY_MOVEPREV);
}
/* finds field number from string/integer (internal use only) */
static int
2001-03-21 23:01:46 -05:00
pgsource_fieldindex(pgsourceobject * self, PyObject * param, const char *usage)
{
2001-03-21 23:01:46 -05:00
int num;
/* checks validity */
if (!check_source_obj(self, CHECK_RESULT | CHECK_DQL))
return -1;
/* gets field number */
if (PyString_Check(param))
num = PQfnumber(self->last_result, PyString_AsString(param));
else if (PyInt_Check(param))
num = PyInt_AsLong(param);
else
{
PyErr_SetString(PyExc_TypeError, usage);
return -1;
}
/* checks field validity */
2001-03-21 23:01:46 -05:00
if (num < 0 || num >= self->num_fields)
{
PyErr_SetString(PyExc_ValueError, "Unknown field.");
return -1;
}
return num;
}
/* builds field information from position (internal use only) */
static PyObject *
pgsource_buildinfo(pgsourceobject * self, int num)
{
2001-03-21 23:01:46 -05:00
PyObject *result;
/* allocates tuple */
result = PyTuple_New(3);
if (!result)
return NULL;
/* affects field information */
PyTuple_SET_ITEM(result, 0, PyInt_FromLong(num));
PyTuple_SET_ITEM(result, 1,
2001-03-21 23:01:46 -05:00
PyString_FromString(PQfname(self->last_result, num)));
PyTuple_SET_ITEM(result, 2,
2001-03-21 23:01:46 -05:00
PyInt_FromLong(PQftype(self->last_result, num)));
return result;
}
/* lists fields info */
static char pgsource_listinfo__doc__[] =
"listinfo() -- return information for all fields "
"(position, name, type oid).";
static PyObject *
pgsource_listinfo(pgsourceobject * self, PyObject * args)
{
2001-03-21 23:01:46 -05:00
int i;
PyObject *result,
*info;
/* checks validity */
if (!check_source_obj(self, CHECK_RESULT | CHECK_DQL))
return NULL;
/* gets args */
if (!PyArg_ParseTuple(args, ""))
{
PyErr_SetString(PyExc_TypeError,
2001-03-21 23:01:46 -05:00
"method listinfo() takes no parameter.");
return NULL;
}
/* builds result */
if ((result = PyTuple_New(self->num_fields)) == NULL)
return NULL;
2001-03-21 23:01:46 -05:00
for (i = 0; i < self->num_fields; i++)
{
info = pgsource_buildinfo(self, i);
if (!info)
{
Py_DECREF(result);
return NULL;
}
PyTuple_SET_ITEM(result, i, info);
}
/* returns result */
return result;
};
/* list fields information for last result */
static char pgsource_fieldinfo__doc__[] =
"fieldinfo(string|integer) -- return specified field information "
"(position, name, type oid).";
static PyObject *
pgsource_fieldinfo(pgsourceobject * self, PyObject * args)
{
static const char short_usage[] =
2001-03-21 23:01:46 -05:00
"fieldinfo(desc), with desc (string|integer).";
int num;
PyObject *param;
/* gets args */
if (!PyArg_ParseTuple(args, "O", &param))
{
PyErr_SetString(PyExc_TypeError, short_usage);
return NULL;
}
/* checks args and validity */
if ((num = pgsource_fieldindex(self, param, short_usage)) == -1)
return NULL;
/* returns result */
return pgsource_buildinfo(self, num);
};
/* retrieve field value */
static char pgsource_field__doc__[] =
"field(string|integer) -- return specified field value.";
static PyObject *
pgsource_field(pgsourceobject * self, PyObject * args)
{
static const char short_usage[] =
2001-03-21 23:01:46 -05:00
"field(desc), with desc (string|integer).";
int num;
PyObject *param;
/* gets args */
if (!PyArg_ParseTuple(args, "O", &param))
{
PyErr_SetString(PyExc_TypeError, short_usage);
return NULL;
}
/* checks args and validity */
if ((num = pgsource_fieldindex(self, param, short_usage)) == -1)
return NULL;
return PyString_FromString(PQgetvalue(self->last_result,
2001-03-21 23:01:46 -05:00
self->current_row, num));
}
/* query object methods */
static PyMethodDef pgsource_methods[] = {
2001-03-21 23:01:46 -05:00
{"close", (PyCFunction) pgsource_close, 1,
pgsource_close__doc__},
{"execute", (PyCFunction) pgsource_execute, 1,
pgsource_execute__doc__},
{"oidstatus", (PyCFunction) pgsource_oidstatus, 1,
pgsource_oidstatus__doc__},
{"fetch", (PyCFunction) pgsource_fetch, 1,
pgsource_fetch__doc__},
{"movefirst", (PyCFunction) pgsource_movefirst, 1,
pgsource_movefirst__doc__},
{"movelast", (PyCFunction) pgsource_movelast, 1,
pgsource_movelast__doc__},
{"movenext", (PyCFunction) pgsource_movenext, 1,
pgsource_movenext__doc__},
{"moveprev", (PyCFunction) pgsource_moveprev, 1,
pgsource_moveprev__doc__},
{"field", (PyCFunction) pgsource_field, 1,
pgsource_field__doc__},
{"fieldinfo", (PyCFunction) pgsource_fieldinfo, 1,
pgsource_fieldinfo__doc__},
{"listinfo", (PyCFunction) pgsource_listinfo, 1,
pgsource_listinfo__doc__},
{NULL, NULL}
};
/* gets query object attributes */
static PyObject *
pgsource_getattr(pgsourceobject * self, char *name)
{
/* pg connection object */
if (!strcmp(name, "pgcnx"))
{
if (check_source_obj(self, 0))
{
Py_INCREF(self->pgcnx);
return (PyObject *) (self->pgcnx);
}
Py_INCREF(Py_None);
return Py_None;
}
/* arraysize */
if (!strcmp(name, "arraysize"))
return PyInt_FromLong(self->arraysize);
/* resulttype */
if (!strcmp(name, "resulttype"))
return PyInt_FromLong(self->result_type);
/* ntuples */
if (!strcmp(name, "ntuples"))
return PyInt_FromLong(self->max_row);
/* nfields */
if (!strcmp(name, "nfields"))
return PyInt_FromLong(self->num_fields);
/* attributes list */
2001-03-21 23:01:46 -05:00
if (!strcmp(name, "__members__"))
{
PyObject *list = PyList_New(5);
PyList_SET_ITEM(list, 0, PyString_FromString("pgcnx"));
PyList_SET_ITEM(list, 1, PyString_FromString("arraysize"));
PyList_SET_ITEM(list, 2, PyString_FromString("resulttype"));
PyList_SET_ITEM(list, 3, PyString_FromString("ntuples"));
PyList_SET_ITEM(list, 4, PyString_FromString("nfields"));
return list;
}
/* module name */
if (!strcmp(name, "__module__"))
return PyString_FromString(MODULE_NAME);
/* class name */
if (!strcmp(name, "__class__"))
return PyString_FromString("pgsource");
/* seeks name in methods (fallback) */
return Py_FindMethod(pgsource_methods, (PyObject *) self, name);
}
/* sets query object attributes */
static int
2001-03-21 23:01:46 -05:00
pgsource_setattr(pgsourceobject * self, char *name, PyObject * v)
{
/* arraysize */
if (!strcmp(name, "arraysize"))
{
if (!PyInt_Check(v))
{
PyErr_SetString(PyExc_TypeError, "arraysize must be integer.");
return -1;
}
self->arraysize = PyInt_AsLong(v);
return 0;
}
/* unknown attribute */
PyErr_SetString(PyExc_TypeError, "not a writable attribute.");
return -1;
}
/* prints query object in human readable format */
static int
pgsource_print(pgsourceobject * self, FILE *fp, int flags)
{
2001-03-21 23:01:46 -05:00
PQprintOpt op;
switch (self->result_type)
{
2001-03-21 23:01:46 -05:00
case RESULT_DQL:
memset(&op, 0, sizeof(op));
op.align = 1;
op.header = 1;
op.fieldSep = "|";
op.pager = 1;
PQprint(fp, self->last_result, &op);
break;
case RESULT_DDL:
case RESULT_DML:
fputs(PQcmdStatus(self->last_result), fp);
break;
case RESULT_EMPTY:
default:
fputs("Empty PostgreSQL source object.", fp);
break;
}
return 0;
}
/* query type definition */
staticforward PyTypeObject PgSourceType = {
2001-03-15 06:26:22 -05:00
PyObject_HEAD_INIT(NULL)
2001-03-21 23:01:46 -05:00
0, /* ob_size */
"pgsourceobject", /* tp_name */
sizeof(pgsourceobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
2001-03-21 23:01:46 -05:00
(destructor) pgsource_dealloc, /* tp_dealloc */
(printfunc) pgsource_print, /* tp_print */
(getattrfunc) pgsource_getattr, /* tp_getattr */
(setattrfunc) pgsource_setattr, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
};
1999-05-17 02:15:31 -04:00
/* --------------------------------------------------------------------- */
/* PG "LARGE" OBJECT IMPLEMENTATION */
1999-05-17 02:15:31 -04:00
#ifdef LARGE_OBJECTS
1999-05-17 02:15:31 -04:00
/* constructor (internal use only) */
static pglargeobject *
pglarge_new(pgobject * pgcnx, Oid oid)
1999-05-17 02:15:31 -04:00
{
2001-03-21 23:01:46 -05:00
pglargeobject *npglo;
1999-05-17 02:15:31 -04:00
if ((npglo = PyObject_NEW(pglargeobject, &PglargeType)) == NULL)
1999-05-25 12:15:34 -04:00
return NULL;
Py_XINCREF(pgcnx);
npglo->pgcnx = pgcnx;
1999-05-17 02:15:31 -04:00
npglo->lo_fd = -1;
npglo->lo_oid = oid;
1999-05-17 02:15:31 -04:00
1999-05-25 12:15:34 -04:00
return npglo;
1999-05-17 02:15:31 -04:00
}
/* destructor */
static void
pglarge_dealloc(pglargeobject * self)
{
if (self->lo_fd >= 0 && check_cnx_obj(self->pgcnx))
1999-05-17 02:15:31 -04:00
lo_close(self->pgcnx->cnx, self->lo_fd);
Py_XDECREF(self->pgcnx);
PyObject_Del(self);
1999-05-17 02:15:31 -04:00
}
/* opens large object */
static char pglarge_open__doc__[] =
2001-03-21 23:01:46 -05:00
"open(mode) -- open access to large object with specified mode "
"(INV_READ, INV_WRITE constants defined by module).";
1999-05-17 02:15:31 -04:00
static PyObject *
pglarge_open(pglargeobject * self, PyObject * args)
{
2001-03-21 23:01:46 -05:00
int mode,
fd;
1999-05-17 02:15:31 -04:00
/* check validity */
if (!check_lo_obj(self, CHECK_CLOSE))
1999-05-17 02:15:31 -04:00
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__[] =
2001-03-21 23:01:46 -05:00
"close() -- close access to large object data.";
1999-05-25 12:15:34 -04:00
1999-05-17 02:15:31 -04:00
static PyObject *
pglarge_close(pglargeobject * self, PyObject * args)
{
/* checks args */
if (!PyArg_ParseTuple(args, ""))
{
PyErr_SetString(PyExc_SyntaxError,
2001-03-21 23:01:46 -05:00
"method close() takes no parameters.");
1999-05-17 02:15:31 -04:00
return NULL;
}
/* checks validity */
if (!check_lo_obj(self, CHECK_OPEN))
1999-05-17 02:15:31 -04:00
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__[] =
2001-03-21 23:01:46 -05:00
"read(integer) -- read from large object to sized string. "
"Object must be opened in read mode before calling this method.";
1999-05-17 02:15:31 -04:00
static PyObject *
pglarge_read(pglargeobject * self, PyObject * args)
{
1999-05-25 12:15:34 -04:00
int size;
2001-03-21 23:01:46 -05:00
PyObject *buffer;
1999-05-17 02:15:31 -04:00
/* checks validity */
if (!check_lo_obj(self, CHECK_OPEN))
1999-05-17 02:15:31 -04:00
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__[] =
2001-03-21 23:01:46 -05:00
"write(string) -- write sized string to large object. "
"Object must be opened in read mode before calling this method.";
1999-05-25 12:15:34 -04:00
1999-05-17 02:15:31 -04:00
static PyObject *
pglarge_write(pglargeobject * self, PyObject * args)
{
2001-03-21 23:01:46 -05:00
char *buffer;
int size,
bufsize;
1999-05-17 02:15:31 -04:00
/* checks validity */
if (!check_lo_obj(self, CHECK_OPEN))
1999-05-17 02:15:31 -04:00
return NULL;
/* gets arguments */
if (!PyArg_ParseTuple(args, "s#", &buffer, &bufsize))
1999-05-17 02:15:31 -04:00
{
PyErr_SetString(PyExc_TypeError,
2001-03-21 23:01:46 -05:00
"write(buffer), with buffer (sized string).");
1999-05-17 02:15:31 -04:00
return NULL;
}
/* sends query */
if ((size = lo_write(self->pgcnx->cnx, self->lo_fd, buffer,
2001-03-21 23:01:46 -05:00
bufsize)) < bufsize)
1999-05-17 02:15:31 -04:00
{
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__[] =
2001-03-21 23:01:46 -05:00
"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.";
1999-05-17 02:15:31 -04:00
static PyObject *
pglarge_lseek(pglargeobject * self, PyObject * args)
{
/* offset and whence are initialized to keep compiler happy */
2001-03-21 23:01:46 -05:00
int ret,
offset = 0,
whence = 0;
1999-05-17 02:15:31 -04:00
/* checks validity */
if (!check_lo_obj(self, CHECK_OPEN))
1999-05-17 02:15:31 -04:00
return NULL;
/* gets arguments */
if (!PyArg_ParseTuple(args, "ii", &offset, &whence))
{
PyErr_SetString(PyExc_TypeError,
2001-03-21 23:01:46 -05:00
"lseek(offset, whence), with offset and whence (integers).");
1999-05-17 02:15:31 -04:00
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__[] =
2001-03-21 23:01:46 -05:00
"size() -- return large object size. "
"Object must be opened before calling this method.";
1999-05-17 02:15:31 -04:00
static PyObject *
pglarge_size(pglargeobject * self, PyObject * args)
{
2001-03-21 23:01:46 -05:00
int start,
end;
1999-05-17 02:15:31 -04:00
/* checks args */
if (!PyArg_ParseTuple(args, ""))
{
PyErr_SetString(PyExc_SyntaxError,
2001-03-21 23:01:46 -05:00
"method size() takes no parameters.");
1999-05-17 02:15:31 -04:00
return NULL;
}
/* checks validity */
if (!check_lo_obj(self, CHECK_OPEN))
1999-05-17 02:15:31 -04:00
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 */
2001-03-21 23:01:46 -05:00
if ((start = lo_lseek(self->pgcnx->cnx, self->lo_fd, start, SEEK_SET)) == -1)
1999-05-17 02:15:31 -04:00
{
PyErr_SetString(PyExc_IOError,
2001-03-21 23:01:46 -05:00
"error while moving back to first position.");
1999-05-17 02:15:31 -04:00
return NULL;
}
/* returns size */
return PyInt_FromLong(end);
}
/* gets large object cursor position */
static char pglarge_tell__doc__[] =
2001-03-21 23:01:46 -05:00
"tell() -- give current position in large object. "
"Object must be opened before calling this method.";
1999-05-17 02:15:31 -04:00
static PyObject *
pglarge_tell(pglargeobject * self, PyObject * args)
{
2001-03-21 23:01:46 -05:00
int start;
1999-05-17 02:15:31 -04:00
/* checks args */
if (!PyArg_ParseTuple(args, ""))
{
PyErr_SetString(PyExc_SyntaxError,
2001-03-21 23:01:46 -05:00
"method tell() takes no parameters.");
1999-05-17 02:15:31 -04:00
return NULL;
}
/* checks validity */
if (!check_lo_obj(self, CHECK_OPEN))
1999-05-17 02:15:31 -04:00
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__[] =
2001-03-21 23:01:46 -05:00
"export(string) -- export large object data to specified file. "
"Object must be closed when calling this method.";
1999-05-17 02:15:31 -04:00
static PyObject *
pglarge_export(pglargeobject * self, PyObject * args)
{
2001-03-21 23:01:46 -05:00
char *name;
1999-05-17 02:15:31 -04:00
/* checks validity */
if (!check_lo_obj(self, CHECK_CLOSE))
1999-05-17 02:15:31 -04:00
return NULL;
/* gets arguments */
if (!PyArg_ParseTuple(args, "s", &name))
{
PyErr_SetString(PyExc_TypeError,
2001-03-21 23:01:46 -05:00
"export(filename), with filename (string).");
1999-05-17 02:15:31 -04:00
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__[] =
2001-03-21 23:01:46 -05:00
"unlink() -- destroy large object. "
"Object must be closed when calling this method.";
1999-05-17 02:15:31 -04:00
static PyObject *
pglarge_unlink(pglargeobject * self, PyObject * args)
{
/* checks args */
if (!PyArg_ParseTuple(args, ""))
{
PyErr_SetString(PyExc_SyntaxError,
2001-03-21 23:01:46 -05:00
"method unlink() takes no parameters.");
1999-05-17 02:15:31 -04:00
return NULL;
}
/* checks validity */
if (!check_lo_obj(self, CHECK_CLOSE))
1999-05-17 02:15:31 -04:00
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[] = {
2001-03-21 23:01:46 -05:00
{"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}
1999-05-17 02:15:31 -04:00
};
/* 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))
1999-05-17 02:15:31 -04:00
{
Py_INCREF(self->pgcnx);
return (PyObject *) (self->pgcnx);
}
Py_INCREF(Py_None);
return Py_None;
}
/* large object oid */
if (!strcmp(name, "oid"))
{
if (check_lo_obj(self, 0))
1999-05-17 02:15:31 -04:00
return PyInt_FromLong(self->lo_oid);
Py_INCREF(Py_None);
return Py_None;
}
/* error (status) message */
if (!strcmp(name, "error"))
return PyString_FromString(PQerrorMessage(self->pgcnx->cnx));
/* attributes list */
if (!strcmp(name, "__members__"))
{
2001-03-21 23:01:46 -05:00
PyObject *list = PyList_New(3);
1999-05-17 02:15:31 -04:00
if (list)
{
PyList_SET_ITEM(list, 0, PyString_FromString("oid"));
PyList_SET_ITEM(list, 1, PyString_FromString("pgcnx"));
PyList_SET_ITEM(list, 2, PyString_FromString("error"));
1999-05-17 02:15:31 -04:00
}
return list;
}
/* module name */
if (!strcmp(name, "__module__"))
1999-05-25 12:15:34 -04:00
return PyString_FromString(MODULE_NAME);
/* class name */
if (!strcmp(name, "__class__"))
1999-05-25 12:15:34 -04:00
return PyString_FromString("pglarge");
/* seeks name in methods (fallback) */
1999-05-17 02:15:31 -04:00
return Py_FindMethod(pglarge_methods, (PyObject *) self, name);
}
/* prints query object in human readable format */
static int
pglarge_print(pglargeobject * self, FILE *fp, int flags)
{
2001-03-21 23:01:46 -05:00
char print_buffer[128];
1999-05-25 12:15:34 -04:00
if (self->lo_fd >= 0)
{
#ifdef NO_SNPRINTF
sprintf(print_buffer,
2001-03-21 23:01:46 -05:00
"Opened large object, oid %ld", (long) self->lo_oid);
#else
1999-05-25 12:15:34 -04:00
snprintf(print_buffer, sizeof(print_buffer),
2001-03-21 23:01:46 -05:00
"Opened large object, oid %ld", (long) self->lo_oid);
#endif
fputs(print_buffer, fp);
1999-05-25 12:15:34 -04:00
}
else
{
#ifdef NO_SNPRINTF
sprintf(print_buffer,
2001-03-21 23:01:46 -05:00
"Closed large object, oid %ld", (long) self->lo_oid);
#else
1999-05-25 12:15:34 -04:00
snprintf(print_buffer, sizeof(print_buffer),
2001-03-21 23:01:46 -05:00
"Closed large object, oid %ld", (long) self->lo_oid);
#endif
fputs(print_buffer, fp);
}
return 0;
}
1999-05-17 02:15:31 -04:00
/* object type definition */
staticforward PyTypeObject PglargeType = {
PyObject_HEAD_INIT(NULL)
2001-03-21 23:01:46 -05:00
0, /* ob_size */
"pglarge", /* tp_name */
sizeof(pglargeobject), /* tp_basicsize */
0, /* tp_itemsize */
1999-05-17 02:15:31 -04:00
/* methods */
2001-03-21 23:01:46 -05:00
(destructor) pglarge_dealloc, /* tp_dealloc */
(printfunc) pglarge_print, /* tp_print */
(getattrfunc) pglarge_getattr, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
1999-05-17 02:15:31 -04:00
};
#endif /* LARGE_OBJECTS */
1999-05-17 02:15:31 -04:00
/* --------------------------------------------------------------------- */
/* PG QUERY OBJECT IMPLEMENTATION */
1999-05-17 02:15:31 -04:00
/* connects to a database */
static char connect__doc__[] =
2001-03-21 23:01:46 -05:00
"connect(dbname, host, port, opt, tty) -- connect to a PostgreSQL database "
"using specified parameters (optionals, keywords aware).";
1999-05-17 02:15:31 -04:00
static PyObject *
2001-03-21 23:01:46 -05:00
pgconnect(pgobject * self, PyObject * args, PyObject * dict)
{
static const char *kwlist[] = {"dbname", "host", "port", "opt",
"tty", "user", "passwd", NULL};
char *pghost,
*pgopt,
*pgtty,
*pgdbname,
*pguser,
*pgpasswd;
int pgport;
char port_buffer[20];
pgobject *npgobj;
1999-05-17 02:15:31 -04:00
pghost = pgopt = pgtty = pgdbname = pguser = pgpasswd = NULL;
pgport = -1;
2001-03-21 23:01:46 -05:00
/*
* parses standard arguments With the right compiler warnings, this
* will issue a diagnostic. There is really no way around it. If I
* don't declare kwlist as const char *kwlist[] then it complains when
* I try to assign all those constant strings to it.
*/
if (!PyArg_ParseTupleAndKeywords(args, dict, "|zzizzzz", (char **) kwlist,
2001-03-21 23:01:46 -05:00
&pgdbname, &pghost, &pgport, &pgopt, &pgtty, &pguser, &pgpasswd))
1999-05-17 02:15:31 -04:00
return NULL;
#ifdef DEFAULT_VARS
/* handles defaults variables (for unintialised vars) */
if ((!pghost) && (pg_default_host != Py_None))
pghost = PyString_AsString(pg_default_host);
if ((pgport == -1) && (pg_default_port != Py_None))
pgport = PyInt_AsLong(pg_default_port);
if ((!pgopt) && (pg_default_opt != Py_None))
pgopt = PyString_AsString(pg_default_opt);
if ((!pgtty) && (pg_default_tty != Py_None))
pgtty = PyString_AsString(pg_default_tty);
if ((!pgdbname) && (pg_default_base != Py_None))
pgdbname = PyString_AsString(pg_default_base);
if ((!pguser) && (pg_default_user != Py_None))
pguser = PyString_AsString(pg_default_user);
if ((!pgpasswd) && (pg_default_passwd != Py_None))
pgpasswd = PyString_AsString(pg_default_passwd);
#endif /* DEFAULT_VARS */
1999-05-17 02:15:31 -04:00
2001-03-21 23:01:46 -05:00
if ((npgobj = (pgobject *) pgobject_New()) == NULL)
1999-05-17 02:15:31 -04:00
return NULL;
if (pgport != -1)
{
memset(port_buffer, 0, sizeof(port_buffer));
1999-05-17 02:15:31 -04:00
sprintf(port_buffer, "%d", pgport);
npgobj->cnx = PQsetdbLogin(pghost, port_buffer, pgopt, pgtty, pgdbname,
2001-03-21 23:01:46 -05:00
pguser, pgpasswd);
1999-05-17 02:15:31 -04:00
}
else
npgobj->cnx = PQsetdbLogin(pghost, NULL, pgopt, pgtty, pgdbname,
2001-03-21 23:01:46 -05:00
pguser, pgpasswd);
1999-05-17 02:15:31 -04:00
if (PQstatus(npgobj->cnx) == CONNECTION_BAD)
{
PyErr_SetString(PGError, PQerrorMessage(npgobj->cnx));
Py_XDECREF(npgobj);
return NULL;
}
return (PyObject *) npgobj;
}
/* pgobject methods */
/* destructor */
static void
pg_dealloc(pgobject * self)
{
if (self->cnx)
PQfinish(self->cnx);
PyObject_Del(self);
1999-05-17 02:15:31 -04:00
}
/* close without deleting */
1999-05-25 12:15:34 -04:00
static char pg_close__doc__[] =
2001-03-21 23:01:46 -05:00
"close() -- close connection. All instances of the connection object and "
"derived objects (queries and large objects) can no longer be used after "
"this call.";
1999-05-17 02:15:31 -04:00
static PyObject *
2001-03-21 23:01:46 -05:00
pg_close(pgobject * self, PyObject * args)
1999-05-17 02:15:31 -04:00
{
/* gets args */
if (!PyArg_ParseTuple(args, ""))
{
PyErr_SetString(PyExc_TypeError, "close().");
return NULL;
}
if (self->cnx)
PQfinish(self->cnx);
self->cnx = NULL;
Py_INCREF(Py_None);
return Py_None;
1999-05-25 12:15:34 -04:00
}
1999-05-17 02:15:31 -04:00
static void
pgquery_dealloc(pgqueryobject * self)
1999-05-17 02:15:31 -04:00
{
if (self->last_result)
PQclear(self->last_result);
PyObject_Del(self);
1999-05-17 02:15:31 -04:00
}
/* resets connection */
1999-05-25 12:15:34 -04:00
static char pg_reset__doc__[] =
2001-03-21 23:01:46 -05:00
"reset() -- reset connection with current parameters. All derived queries "
"and large objects derived from this connection will not be usable after "
"this call.";
1999-05-17 02:15:31 -04:00
static PyObject *
pg_reset(pgobject * self, PyObject * args)
{
if (!self->cnx)
{
PyErr_SetString(PyExc_TypeError, "Connection is not valid");
return NULL;
}
/* checks args */
if (!PyArg_ParseTuple(args, ""))
{
PyErr_SetString(PyExc_SyntaxError,
2001-03-21 23:01:46 -05:00
"method reset() takes no parameters.");
1999-05-17 02:15:31 -04:00
return NULL;
}
/* resets the connection */
PQreset(self->cnx);
Py_INCREF(Py_None);
return Py_None;
}
/* get connection socket */
1999-05-25 12:15:34 -04:00
static char pg_fileno__doc__[] =
2001-03-21 23:01:46 -05:00
"fileno() -- return database connection socket file handle.";
1999-05-17 02:15:31 -04:00
static PyObject *
pg_fileno(pgobject * self, PyObject * args)
{
if (!self->cnx)
{
PyErr_SetString(PyExc_TypeError, "Connection is not valid");
return NULL;
}
/* checks args */
if (!PyArg_ParseTuple(args, ""))
{
PyErr_SetString(PyExc_SyntaxError,
2001-03-21 23:01:46 -05:00
"method fileno() takes no parameters.");
1999-05-17 02:15:31 -04:00
return NULL;
}
#ifdef NO_PQSOCKET
return PyInt_FromLong((long) self->cnx->sock);
#else
return PyInt_FromLong((long) PQsocket(self->cnx));
#endif
}
/* get number of rows */
static char pgquery_ntuples__doc__[] =
2001-03-21 23:01:46 -05:00
"ntuples() -- returns number of tuples returned by query.";
static PyObject *
pgquery_ntuples(pgqueryobject * self, PyObject * args)
{
/* checks args */
if (!PyArg_ParseTuple(args, ""))
{
PyErr_SetString(PyExc_SyntaxError,
2001-03-21 23:01:46 -05:00
"method ntuples() takes no parameters.");
return NULL;
}
return PyInt_FromLong((long) PQntuples(self->last_result));
1999-05-25 12:15:34 -04:00
}
1999-05-17 02:15:31 -04:00
/* list fields names from query result */
static char pgquery_listfields__doc__[] =
2001-03-21 23:01:46 -05:00
"listfields() -- Lists field names from result.";
1999-05-17 02:15:31 -04:00
static PyObject *
pgquery_listfields(pgqueryobject * self, PyObject * args)
1999-05-17 02:15:31 -04:00
{
2001-03-21 23:01:46 -05:00
int i,
n;
char *name;
PyObject *fieldstuple,
*str;
1999-05-17 02:15:31 -04:00
/* checks args */
if (!PyArg_ParseTuple(args, ""))
{
PyErr_SetString(PyExc_SyntaxError,
2001-03-21 23:01:46 -05:00
"method listfields() takes no parameters.");
1999-05-17 02:15:31 -04:00
return NULL;
}
/* builds tuple */
n = PQnfields(self->last_result);
fieldstuple = PyTuple_New(n);
for (i = 0; i < n; i++)
{
name = PQfname(self->last_result, i);
str = PyString_FromString(name);
PyTuple_SET_ITEM(fieldstuple, i, str);
1999-05-17 02:15:31 -04:00
}
return fieldstuple;
}
/* get field name from last result */
static char pgquery_fieldname__doc__[] =
2001-03-21 23:01:46 -05:00
"fieldname() -- returns name of field from result from its position.";
1999-05-17 02:15:31 -04:00
static PyObject *
pgquery_fieldname(pgqueryobject * self, PyObject * args)
1999-05-17 02:15:31 -04:00
{
2001-03-21 23:01:46 -05:00
int i;
char *name;
1999-05-17 02:15:31 -04:00
/* gets args */
if (!PyArg_ParseTuple(args, "i", &i))
{
PyErr_SetString(PyExc_TypeError,
2001-03-21 23:01:46 -05:00
"fieldname(number), with number(integer).");
1999-05-17 02:15:31 -04:00
return NULL;
}
/* checks number validity */
if (i >= PQnfields(self->last_result))
{
PyErr_SetString(PyExc_ValueError, "invalid field number.");
return NULL;
}
/* gets fields name and builds object */
name = PQfname(self->last_result, i);
return PyString_FromString(name);
}
/* gets fields number from name in last result */
static char pgquery_fieldnum__doc__[] =
2001-03-21 23:01:46 -05:00
"fieldnum() -- returns position in query for field from its name.";
1999-05-17 02:15:31 -04:00
static PyObject *
pgquery_fieldnum(pgqueryobject * self, PyObject * args)
1999-05-17 02:15:31 -04:00
{
2001-03-21 23:01:46 -05:00
char *name;
int num;
1999-05-17 02:15:31 -04:00
/* gets args */
if (!PyArg_ParseTuple(args, "s", &name))
{
PyErr_SetString(PyExc_TypeError, "fieldnum(name), with name (string).");
return NULL;
}
/* gets field number */
if ((num = PQfnumber(self->last_result, name)) == -1)
{
PyErr_SetString(PyExc_ValueError, "Unknown field.");
return NULL;
}
return PyInt_FromLong(num);
}
/* retrieves last result */
static char pgquery_getresult__doc__[] =
2001-03-21 23:01:46 -05:00
"getresult() -- Gets the result of a query. The result is returned "
"as a list of rows, each one a list of fields in the order returned "
"by the server.";
1999-05-17 02:15:31 -04:00
static PyObject *
pgquery_getresult(pgqueryobject * self, PyObject * args)
1999-05-17 02:15:31 -04:00
{
2001-03-21 23:01:46 -05:00
PyObject *rowtuple,
*reslist,
*val;
int i,
j,
m,
n,
*typ;
1999-05-17 02:15:31 -04:00
/* checks args (args == NULL for an internal call) */
if ((args != NULL) && (!PyArg_ParseTuple(args, "")))
{
PyErr_SetString(PyExc_SyntaxError,
2001-03-21 23:01:46 -05:00
"method getresult() takes no parameters.");
1999-05-17 02:15:31 -04:00
return NULL;
}
/* stores result in tuple */
m = PQntuples(self->last_result);
n = PQnfields(self->last_result);
reslist = PyList_New(m);
1999-05-17 02:15:31 -04:00
typ = get_type_array(self->last_result, n);
1999-05-17 02:15:31 -04:00
for (i = 0; i < m; i++)
{
if ((rowtuple = PyTuple_New(n)) == NULL)
{
Py_DECREF(reslist);
reslist = NULL;
goto exit;
}
1999-05-17 02:15:31 -04:00
for (j = 0; j < n; j++)
{
2001-03-21 23:01:46 -05:00
int k;
char *s = PQgetvalue(self->last_result, i, j);
char cashbuf[64];
1999-05-17 02:15:31 -04:00
if (PQgetisnull(self->last_result, i, j))
{
Py_INCREF(Py_None);
val = Py_None;
}
2001-03-21 23:01:46 -05:00
else
switch (typ[j])
{
case 1:
val = PyInt_FromLong(strtol(s, NULL, 10));
break;
1999-05-17 02:15:31 -04:00
2001-03-21 23:01:46 -05:00
case 2:
val = PyLong_FromLong(strtol(s, NULL, 10));
2001-03-21 23:01:46 -05:00
break;
1999-05-17 02:15:31 -04:00
case 3:
val = PyFloat_FromDouble(strtod(s, NULL));
break;
case 4:
{
int mult = 1;
if (*s == '$') /* there's talk of getting
* rid of it */
s++;
if (*s == '-' || *s == '(')
{
s++;
mult = -1;
}
/* get rid of the '$' and commas */
if (*s == '$') /* Just in case we exposed
* one */
s++;
for (k = 0; *s; s++)
if (*s != ',')
cashbuf[k++] = *s;
cashbuf[k] = 0;
val = PyFloat_FromDouble(strtod(cashbuf, NULL) * mult);
break;
}
2001-03-21 23:01:46 -05:00
default:
val = PyString_FromString(s);
break;
}
1999-05-17 02:15:31 -04:00
if (val == NULL)
{
Py_DECREF(reslist);
Py_DECREF(rowtuple);
reslist = NULL;
goto exit;
}
PyTuple_SET_ITEM(rowtuple, j, val);
1999-05-17 02:15:31 -04:00
}
PyList_SET_ITEM(reslist, i, rowtuple);
1999-05-17 02:15:31 -04:00
}
exit:
1999-05-17 02:15:31 -04:00
free(typ);
/* returns list */
return reslist;
}
/* retrieves last result as a list of dictionaries*/
static char pgquery_dictresult__doc__[] =
2001-03-21 23:01:46 -05:00
"dictresult() -- Gets the result of a query. The result is returned "
"as a list of rows, each one a dictionary with the field names used "
"as the labels.";
1999-05-17 02:15:31 -04:00
static PyObject *
pgquery_dictresult(pgqueryobject * self, PyObject * args)
1999-05-17 02:15:31 -04:00
{
2001-03-21 23:01:46 -05:00
PyObject *dict,
*reslist,
*val;
int i,
j,
m,
n,
*typ;
1999-05-17 02:15:31 -04:00
/* checks args (args == NULL for an internal call) */
if ((args != NULL) && (!PyArg_ParseTuple(args, "")))
{
PyErr_SetString(PyExc_SyntaxError,
2001-03-21 23:01:46 -05:00
"method getresult() takes no parameters.");
1999-05-17 02:15:31 -04:00
return NULL;
}
/* stores result in list */
m = PQntuples(self->last_result);
n = PQnfields(self->last_result);
reslist = PyList_New(m);
1999-05-17 02:15:31 -04:00
typ = get_type_array(self->last_result, n);
1999-05-17 02:15:31 -04:00
for (i = 0; i < m; i++)
{
if ((dict = PyDict_New()) == NULL)
{
Py_DECREF(reslist);
reslist = NULL;
goto exit;
}
1999-05-17 02:15:31 -04:00
for (j = 0; j < n; j++)
{
2001-03-21 23:01:46 -05:00
int k;
char *s = PQgetvalue(self->last_result, i, j);
char cashbuf[64];
1999-05-17 02:15:31 -04:00
if (PQgetisnull(self->last_result, i, j))
{
Py_INCREF(Py_None);
val = Py_None;
}
2001-03-21 23:01:46 -05:00
else
switch (typ[j])
{
case 1:
val = PyInt_FromLong(strtol(s, NULL, 10));
break;
1999-05-17 02:15:31 -04:00
2001-03-21 23:01:46 -05:00
case 2:
val = PyLong_FromLong(strtol(s, NULL, 10));
2001-03-21 23:01:46 -05:00
break;
1999-05-17 02:15:31 -04:00
case 3:
val = PyFloat_FromDouble(strtod(s, NULL));
break;
case 4:
{
int mult = 1;
if (*s == '$') /* there's talk of getting
* rid of it */
s++;
if (*s == '-' || *s == '(')
{
s++;
mult = -1;
}
/* get rid of the '$' and commas */
if (*s == '$') /* Just in case we exposed
* one */
s++;
2002-09-04 16:31:48 -04:00
for (k = 0;
*s && k < sizeof(cashbuf) / sizeof(cashbuf[0]) - 1;
s++)
{
if (*s != ',')
cashbuf[k++] = *s;
}
cashbuf[k] = 0;
val = PyFloat_FromDouble(strtod(cashbuf, NULL) * mult);
break;
}
2001-03-21 23:01:46 -05:00
default:
val = PyString_FromString(s);
break;
}
1999-05-17 02:15:31 -04:00
if (val == NULL)
{
Py_DECREF(dict);
Py_DECREF(reslist);
reslist = NULL;
goto exit;
}
1999-05-17 02:15:31 -04:00
PyDict_SetItemString(dict, PQfname(self->last_result, j), val);
Py_DECREF(val);
1999-05-17 02:15:31 -04:00
}
PyList_SET_ITEM(reslist, i, dict);
1999-05-17 02:15:31 -04:00
}
exit:
1999-05-17 02:15:31 -04:00
free(typ);
/* returns list */
return reslist;
}
/* gets asynchronous notify */
1999-05-25 12:15:34 -04:00
static char pg_getnotify__doc__[] =
2001-03-21 23:01:46 -05:00
"getnotify() -- get database notify for this connection.";
1999-05-17 02:15:31 -04:00
static PyObject *
pg_getnotify(pgobject * self, PyObject * args)
{
2001-03-21 23:01:46 -05:00
PGnotify *notify;
PGresult *result;
PyObject *notify_result,
*temp;
1999-05-17 02:15:31 -04:00
if (!self->cnx)
{
PyErr_SetString(PyExc_TypeError, "Connection is not valid");
return NULL;
}
/* checks args */
if (!PyArg_ParseTuple(args, ""))
{
PyErr_SetString(PyExc_SyntaxError,
2001-03-21 23:01:46 -05:00
"method getnotify() takes no parameters.");
1999-05-17 02:15:31 -04:00
return NULL;
}
/* gets notify and builds result */
2001-03-21 23:01:46 -05:00
/*
* notifies only come back as result of a query, so I send an empty
* query
*/
Py_BEGIN_ALLOW_THREADS
2001-03-21 23:01:46 -05:00
result = PQexec(self->cnx, " ");
Py_END_ALLOW_THREADS
1999-05-17 02:15:31 -04:00
2001-03-21 23:01:46 -05:00
if ((notify = PQnotifies(self->cnx)) != NULL)
1999-05-17 02:15:31 -04:00
{
if ((notify_result = PyTuple_New(2)) == NULL)
{
PQclear(result);
return NULL;
}
if ((temp = PyString_FromString(notify->relname)) == NULL)
{
PQclear(result);
return NULL;
}
PyTuple_SET_ITEM(notify_result, 0, temp);
if ((temp = PyInt_FromLong(notify->be_pid)) == NULL)
{
PQclear(result);
Py_DECREF(notify_result);
return NULL;
}
PyTuple_SET_ITEM(notify_result, 1, temp);
1999-05-17 02:15:31 -04:00
free(notify);
}
else
{
Py_INCREF(Py_None);
notify_result = Py_None;
}
PQclear(result);
/* returns result */
return notify_result;
}
/* source creation */
static char pg_source__doc__[] =
2001-03-21 23:01:46 -05:00
"source() -- creates a new source object for this connection";
static PyObject *
pg_source(pgobject * self, PyObject * args)
{
/* checks validity */
if (!check_cnx_obj(self))
return NULL;
/* checks args */
if (!PyArg_ParseTuple(args, ""))
{
PyErr_SetString(PyExc_TypeError, "method source() takes no parameter.");
return NULL;
}
/* allocate new pg query object */
2001-03-21 23:01:46 -05:00
return (PyObject *) pgsource_new(self);
}
1999-05-17 02:15:31 -04:00
/* database query */
static char pg_query__doc__[] =
2001-03-21 23:01:46 -05:00
"query(sql) -- creates a new query object for this connection,"
" using sql (string) request.";
1999-05-17 02:15:31 -04:00
static PyObject *
pg_query(pgobject * self, PyObject * args)
{
2001-03-21 23:01:46 -05:00
char *query;
PGresult *result;
pgqueryobject *npgobj;
int status;
1999-05-17 02:15:31 -04:00
if (!self->cnx)
{
PyErr_SetString(PyExc_TypeError, "Connection is not valid");
return NULL;
}
/* get query args */
if (!PyArg_ParseTuple(args, "s", &query))
{
PyErr_SetString(PyExc_TypeError, "query(sql), with sql (string).");
return NULL;
}
/* frees previous result */
if (self->last_result)
{
PQclear(self->last_result);
self->last_result = NULL;
}
1999-05-17 02:15:31 -04:00
/* gets result */
Py_BEGIN_ALLOW_THREADS
2001-03-21 23:01:46 -05:00
result = PQexec(self->cnx, query);
Py_END_ALLOW_THREADS
1999-05-17 02:15:31 -04:00
/* checks result validity */
2001-03-21 23:01:46 -05:00
if (!result)
1999-05-17 02:15:31 -04:00
{
PyErr_SetString(PyExc_ValueError, PQerrorMessage(self->cnx));
return NULL;
}
/* checks result status */
if ((status = PQresultStatus(result)) != PGRES_TUPLES_OK)
{
2001-03-21 23:01:46 -05:00
Oid oid;
1999-05-17 02:15:31 -04:00
PQclear(result);
switch (status)
{
case PGRES_EMPTY_QUERY:
PyErr_SetString(PyExc_ValueError, "empty query.");
break;
case PGRES_BAD_RESPONSE:
case PGRES_FATAL_ERROR:
case PGRES_NONFATAL_ERROR:
PyErr_SetString(PGError, PQerrorMessage(self->cnx));
break;
2001-03-21 23:01:46 -05:00
case PGRES_COMMAND_OK: /* could be an INSERT */
if ((oid = PQoidValue(result)) == InvalidOid) /* nope */
1999-05-17 02:15:31 -04:00
{
Py_INCREF(Py_None);
return Py_None;
}
/* otherwise, return the oid */
return PyInt_FromLong(oid);
1999-05-17 02:15:31 -04:00
2001-03-21 23:01:46 -05:00
case PGRES_COPY_OUT: /* no data will be received */
1999-05-17 02:15:31 -04:00
case PGRES_COPY_IN:
Py_INCREF(Py_None);
return Py_None;
default:
PyErr_SetString(PGError, "internal error: "
2001-03-21 23:01:46 -05:00
"unknown result status.");
1999-05-17 02:15:31 -04:00
break;
}
return NULL; /* error detected on query */
}
if ((npgobj = PyObject_NEW(pgqueryobject, &PgQueryType)) == NULL)
return NULL;
/* stores result and returns object */
npgobj->last_result = result;
return (PyObject *) npgobj;
}
#ifdef DIRECT_ACCESS
static char pg_putline__doc__[] =
2001-03-21 23:01:46 -05:00
"putline() -- sends a line directly to the backend";
1999-05-17 02:15:31 -04:00
/* direct acces function : putline */
static PyObject *
pg_putline(pgobject * self, PyObject * args)
{
2001-03-21 23:01:46 -05:00
char *line;
1999-05-17 02:15:31 -04:00
if (!self->cnx)
{
PyErr_SetString(PyExc_TypeError, "Connection is not valid");
return NULL;
}
/* reads args */
if (!PyArg_ParseTuple(args, "s", &line))
{
PyErr_SetString(PyExc_TypeError, "putline(line), with line (string).");
return NULL;
}
/* sends line to backend */
PQputline(self->cnx, line);
Py_INCREF(Py_None);
return Py_None;
}
/* direct access function : getline */
static char pg_getline__doc__[] =
2001-03-21 23:01:46 -05:00
"getline() -- gets a line directly from the backend.";
1999-05-17 02:15:31 -04:00
static PyObject *
pg_getline(pgobject * self, PyObject * args)
{
1999-05-25 12:15:34 -04:00
char line[MAX_BUFFER_SIZE];
2001-03-21 23:01:46 -05:00
PyObject *str = NULL; /* GCC */
1999-05-17 02:15:31 -04:00
if (!self->cnx)
{
PyErr_SetString(PyExc_TypeError, "Connection is not valid");
return NULL;
}
/* checks args */
if (!PyArg_ParseTuple(args, ""))
{
PyErr_SetString(PyExc_SyntaxError,
2001-03-21 23:01:46 -05:00
"method getline() takes no parameters.");
1999-05-17 02:15:31 -04:00
return NULL;
}
/* gets line */
switch (PQgetline(self->cnx, line, MAX_BUFFER_SIZE))
{
case 0:
str = PyString_FromString(line);
break;
case 1:
PyErr_SetString(PyExc_MemoryError, "buffer overflow");
str = NULL;
break;
case EOF:
Py_INCREF(Py_None);
str = Py_None;
break;
}
return str;
}
/* direct access function : end copy */
static char pg_endcopy__doc__[] =
2001-03-21 23:01:46 -05:00
"endcopy() -- synchronizes client and server";
1999-05-17 02:15:31 -04:00
static PyObject *
pg_endcopy(pgobject * self, PyObject * args)
{
if (!self->cnx)
{
PyErr_SetString(PyExc_TypeError, "Connection is not valid");
return NULL;
}
/* checks args */
if (!PyArg_ParseTuple(args, ""))
{
PyErr_SetString(PyExc_SyntaxError,
2001-03-21 23:01:46 -05:00
"method endcopy() takes no parameters.");
1999-05-17 02:15:31 -04:00
return NULL;
}
/* ends direct copy */
PQendcopy(self->cnx);
Py_INCREF(Py_None);
return Py_None;
}
#endif /* DIRECT_ACCESS */
1999-05-17 02:15:31 -04:00
static PyObject *
2001-03-21 23:01:46 -05:00
pgquery_print(pgqueryobject * self, FILE *fp, int flags)
1999-05-17 02:15:31 -04:00
{
2001-03-21 23:01:46 -05:00
PQprintOpt op;
1999-05-17 02:15:31 -04:00
memset(&op, 0, sizeof(op));
1999-05-25 12:15:34 -04:00
op.align = 1;
1999-05-17 02:15:31 -04:00
op.header = 1;
op.fieldSep = "|";
op.pager = 1;
PQprint(fp, self->last_result, &op);
return 0;
}
static PyObject *
2001-03-21 23:01:46 -05:00
pgquery_repr(pgqueryobject * self)
{
return PyString_FromString("<pg query result>");
}
1999-05-17 02:15:31 -04:00
/* insert table */
1999-05-25 12:15:34 -04:00
static char pg_inserttable__doc__[] =
2001-03-21 23:01:46 -05:00
"inserttable(string, list) -- insert list in table. The fields in the "
"list must be in the same order as in the table.";
1999-05-17 02:15:31 -04:00
static PyObject *
pg_inserttable(pgobject * self, PyObject * args)
{
PyGreSQL inserttable patch ===================== I suggested an improvement of the inserttable in the PyGreSQL interface already in January, but seemingly it was never implemented. I was told this is the right place to get patches in for PyGreSQL, so I'm reposting my patch here. I consider the inserttable methode essential in populating the database because of its benefits in performance compared to insert, so I think this patch is quite essential. The attachment is an improved version of the corresponding pg_inserttable function in pgmodule.c, which fixes the following problems: * The function raised exceptions because PyList_GetItem was used beyond the size of the list. This was checked by comparing the result with NULL, but the exception was not cleaned up, which could result in mysterious errors in the following Python code. Instead of clearing the exception using PyErr_Clear or something like that, I avoided throwing the exception at all by at first requesting the size of the list. Using this opportunity, I also checked the uniformity of the size of the rows passed in the lists/tuples. The function also accepts (and silently ignores) empty lists and sublists. * Python "None" values are now accepted and properly converted to PostgreSQL NULL values * The function now generates an error message in case of a line buffer overflow * It copes with tabulators, newlines and backslashes in strings now * Rewrote the buffer filling code which should now run faster by avoiding unnecessary string copy operations forth and back Christoph Zwerschke
2002-12-05 22:19:28 -05:00
PGresult *result;
char *table,
*buffer,
*bufpt,
*temp;
size_t bufsiz;
PyObject *list,
*sublist,
*item;
PyObject *(*getitem) (PyObject *, int);
PyObject *(*getsubitem) (PyObject *, int);
2001-03-21 23:01:46 -05:00
int i,
PyGreSQL inserttable patch ===================== I suggested an improvement of the inserttable in the PyGreSQL interface already in January, but seemingly it was never implemented. I was told this is the right place to get patches in for PyGreSQL, so I'm reposting my patch here. I consider the inserttable methode essential in populating the database because of its benefits in performance compared to insert, so I think this patch is quite essential. The attachment is an improved version of the corresponding pg_inserttable function in pgmodule.c, which fixes the following problems: * The function raised exceptions because PyList_GetItem was used beyond the size of the list. This was checked by comparing the result with NULL, but the exception was not cleaned up, which could result in mysterious errors in the following Python code. Instead of clearing the exception using PyErr_Clear or something like that, I avoided throwing the exception at all by at first requesting the size of the list. Using this opportunity, I also checked the uniformity of the size of the rows passed in the lists/tuples. The function also accepts (and silently ignores) empty lists and sublists. * Python "None" values are now accepted and properly converted to PostgreSQL NULL values * The function now generates an error message in case of a line buffer overflow * It copes with tabulators, newlines and backslashes in strings now * Rewrote the buffer filling code which should now run faster by avoiding unnecessary string copy operations forth and back Christoph Zwerschke
2002-12-05 22:19:28 -05:00
j,
m,
n;
1999-05-17 02:15:31 -04:00
if (!self->cnx)
{
PyErr_SetString(PyExc_TypeError, "Connection is not valid");
return NULL;
}
/* gets arguments */
if (!PyArg_ParseTuple(args, "sO:filter", &table, &list))
{
PyErr_SetString(PyExc_TypeError,
PyGreSQL inserttable patch ===================== I suggested an improvement of the inserttable in the PyGreSQL interface already in January, but seemingly it was never implemented. I was told this is the right place to get patches in for PyGreSQL, so I'm reposting my patch here. I consider the inserttable methode essential in populating the database because of its benefits in performance compared to insert, so I think this patch is quite essential. The attachment is an improved version of the corresponding pg_inserttable function in pgmodule.c, which fixes the following problems: * The function raised exceptions because PyList_GetItem was used beyond the size of the list. This was checked by comparing the result with NULL, but the exception was not cleaned up, which could result in mysterious errors in the following Python code. Instead of clearing the exception using PyErr_Clear or something like that, I avoided throwing the exception at all by at first requesting the size of the list. Using this opportunity, I also checked the uniformity of the size of the rows passed in the lists/tuples. The function also accepts (and silently ignores) empty lists and sublists. * Python "None" values are now accepted and properly converted to PostgreSQL NULL values * The function now generates an error message in case of a line buffer overflow * It copes with tabulators, newlines and backslashes in strings now * Rewrote the buffer filling code which should now run faster by avoiding unnecessary string copy operations forth and back Christoph Zwerschke
2002-12-05 22:19:28 -05:00
"tableinsert(table, content), with table (string) "
"and content (list).");
1999-05-17 02:15:31 -04:00
return NULL;
}
/* checks list type */
if (PyTuple_Check(list))
PyGreSQL inserttable patch ===================== I suggested an improvement of the inserttable in the PyGreSQL interface already in January, but seemingly it was never implemented. I was told this is the right place to get patches in for PyGreSQL, so I'm reposting my patch here. I consider the inserttable methode essential in populating the database because of its benefits in performance compared to insert, so I think this patch is quite essential. The attachment is an improved version of the corresponding pg_inserttable function in pgmodule.c, which fixes the following problems: * The function raised exceptions because PyList_GetItem was used beyond the size of the list. This was checked by comparing the result with NULL, but the exception was not cleaned up, which could result in mysterious errors in the following Python code. Instead of clearing the exception using PyErr_Clear or something like that, I avoided throwing the exception at all by at first requesting the size of the list. Using this opportunity, I also checked the uniformity of the size of the rows passed in the lists/tuples. The function also accepts (and silently ignores) empty lists and sublists. * Python "None" values are now accepted and properly converted to PostgreSQL NULL values * The function now generates an error message in case of a line buffer overflow * It copes with tabulators, newlines and backslashes in strings now * Rewrote the buffer filling code which should now run faster by avoiding unnecessary string copy operations forth and back Christoph Zwerschke
2002-12-05 22:19:28 -05:00
{
m = PyTuple_Size(list);
1999-05-17 02:15:31 -04:00
getitem = PyTuple_GetItem;
PyGreSQL inserttable patch ===================== I suggested an improvement of the inserttable in the PyGreSQL interface already in January, but seemingly it was never implemented. I was told this is the right place to get patches in for PyGreSQL, so I'm reposting my patch here. I consider the inserttable methode essential in populating the database because of its benefits in performance compared to insert, so I think this patch is quite essential. The attachment is an improved version of the corresponding pg_inserttable function in pgmodule.c, which fixes the following problems: * The function raised exceptions because PyList_GetItem was used beyond the size of the list. This was checked by comparing the result with NULL, but the exception was not cleaned up, which could result in mysterious errors in the following Python code. Instead of clearing the exception using PyErr_Clear or something like that, I avoided throwing the exception at all by at first requesting the size of the list. Using this opportunity, I also checked the uniformity of the size of the rows passed in the lists/tuples. The function also accepts (and silently ignores) empty lists and sublists. * Python "None" values are now accepted and properly converted to PostgreSQL NULL values * The function now generates an error message in case of a line buffer overflow * It copes with tabulators, newlines and backslashes in strings now * Rewrote the buffer filling code which should now run faster by avoiding unnecessary string copy operations forth and back Christoph Zwerschke
2002-12-05 22:19:28 -05:00
}
1999-05-17 02:15:31 -04:00
else if (PyList_Check(list))
PyGreSQL inserttable patch ===================== I suggested an improvement of the inserttable in the PyGreSQL interface already in January, but seemingly it was never implemented. I was told this is the right place to get patches in for PyGreSQL, so I'm reposting my patch here. I consider the inserttable methode essential in populating the database because of its benefits in performance compared to insert, so I think this patch is quite essential. The attachment is an improved version of the corresponding pg_inserttable function in pgmodule.c, which fixes the following problems: * The function raised exceptions because PyList_GetItem was used beyond the size of the list. This was checked by comparing the result with NULL, but the exception was not cleaned up, which could result in mysterious errors in the following Python code. Instead of clearing the exception using PyErr_Clear or something like that, I avoided throwing the exception at all by at first requesting the size of the list. Using this opportunity, I also checked the uniformity of the size of the rows passed in the lists/tuples. The function also accepts (and silently ignores) empty lists and sublists. * Python "None" values are now accepted and properly converted to PostgreSQL NULL values * The function now generates an error message in case of a line buffer overflow * It copes with tabulators, newlines and backslashes in strings now * Rewrote the buffer filling code which should now run faster by avoiding unnecessary string copy operations forth and back Christoph Zwerschke
2002-12-05 22:19:28 -05:00
{
m = PyList_Size(list);
1999-05-17 02:15:31 -04:00
getitem = PyList_GetItem;
PyGreSQL inserttable patch ===================== I suggested an improvement of the inserttable in the PyGreSQL interface already in January, but seemingly it was never implemented. I was told this is the right place to get patches in for PyGreSQL, so I'm reposting my patch here. I consider the inserttable methode essential in populating the database because of its benefits in performance compared to insert, so I think this patch is quite essential. The attachment is an improved version of the corresponding pg_inserttable function in pgmodule.c, which fixes the following problems: * The function raised exceptions because PyList_GetItem was used beyond the size of the list. This was checked by comparing the result with NULL, but the exception was not cleaned up, which could result in mysterious errors in the following Python code. Instead of clearing the exception using PyErr_Clear or something like that, I avoided throwing the exception at all by at first requesting the size of the list. Using this opportunity, I also checked the uniformity of the size of the rows passed in the lists/tuples. The function also accepts (and silently ignores) empty lists and sublists. * Python "None" values are now accepted and properly converted to PostgreSQL NULL values * The function now generates an error message in case of a line buffer overflow * It copes with tabulators, newlines and backslashes in strings now * Rewrote the buffer filling code which should now run faster by avoiding unnecessary string copy operations forth and back Christoph Zwerschke
2002-12-05 22:19:28 -05:00
}
1999-05-17 02:15:31 -04:00
else
{
PyErr_SetString(PyExc_TypeError,
PyGreSQL inserttable patch ===================== I suggested an improvement of the inserttable in the PyGreSQL interface already in January, but seemingly it was never implemented. I was told this is the right place to get patches in for PyGreSQL, so I'm reposting my patch here. I consider the inserttable methode essential in populating the database because of its benefits in performance compared to insert, so I think this patch is quite essential. The attachment is an improved version of the corresponding pg_inserttable function in pgmodule.c, which fixes the following problems: * The function raised exceptions because PyList_GetItem was used beyond the size of the list. This was checked by comparing the result with NULL, but the exception was not cleaned up, which could result in mysterious errors in the following Python code. Instead of clearing the exception using PyErr_Clear or something like that, I avoided throwing the exception at all by at first requesting the size of the list. Using this opportunity, I also checked the uniformity of the size of the rows passed in the lists/tuples. The function also accepts (and silently ignores) empty lists and sublists. * Python "None" values are now accepted and properly converted to PostgreSQL NULL values * The function now generates an error message in case of a line buffer overflow * It copes with tabulators, newlines and backslashes in strings now * Rewrote the buffer filling code which should now run faster by avoiding unnecessary string copy operations forth and back Christoph Zwerschke
2002-12-05 22:19:28 -05:00
"second arg must be some kind of array.");
1999-05-17 02:15:31 -04:00
return NULL;
}
PyGreSQL inserttable patch ===================== I suggested an improvement of the inserttable in the PyGreSQL interface already in January, but seemingly it was never implemented. I was told this is the right place to get patches in for PyGreSQL, so I'm reposting my patch here. I consider the inserttable methode essential in populating the database because of its benefits in performance compared to insert, so I think this patch is quite essential. The attachment is an improved version of the corresponding pg_inserttable function in pgmodule.c, which fixes the following problems: * The function raised exceptions because PyList_GetItem was used beyond the size of the list. This was checked by comparing the result with NULL, but the exception was not cleaned up, which could result in mysterious errors in the following Python code. Instead of clearing the exception using PyErr_Clear or something like that, I avoided throwing the exception at all by at first requesting the size of the list. Using this opportunity, I also checked the uniformity of the size of the rows passed in the lists/tuples. The function also accepts (and silently ignores) empty lists and sublists. * Python "None" values are now accepted and properly converted to PostgreSQL NULL values * The function now generates an error message in case of a line buffer overflow * It copes with tabulators, newlines and backslashes in strings now * Rewrote the buffer filling code which should now run faster by avoiding unnecessary string copy operations forth and back Christoph Zwerschke
2002-12-05 22:19:28 -05:00
if (m)
1999-05-17 02:15:31 -04:00
{
/* not strictly necessary but removes a bogus warning */
n = 0;
PyGreSQL inserttable patch ===================== I suggested an improvement of the inserttable in the PyGreSQL interface already in January, but seemingly it was never implemented. I was told this is the right place to get patches in for PyGreSQL, so I'm reposting my patch here. I consider the inserttable methode essential in populating the database because of its benefits in performance compared to insert, so I think this patch is quite essential. The attachment is an improved version of the corresponding pg_inserttable function in pgmodule.c, which fixes the following problems: * The function raised exceptions because PyList_GetItem was used beyond the size of the list. This was checked by comparing the result with NULL, but the exception was not cleaned up, which could result in mysterious errors in the following Python code. Instead of clearing the exception using PyErr_Clear or something like that, I avoided throwing the exception at all by at first requesting the size of the list. Using this opportunity, I also checked the uniformity of the size of the rows passed in the lists/tuples. The function also accepts (and silently ignores) empty lists and sublists. * Python "None" values are now accepted and properly converted to PostgreSQL NULL values * The function now generates an error message in case of a line buffer overflow * It copes with tabulators, newlines and backslashes in strings now * Rewrote the buffer filling code which should now run faster by avoiding unnecessary string copy operations forth and back Christoph Zwerschke
2002-12-05 22:19:28 -05:00
/* checks sublists type and size */
for (i = 0; i < m; i++)
1999-05-17 02:15:31 -04:00
{
PyGreSQL inserttable patch ===================== I suggested an improvement of the inserttable in the PyGreSQL interface already in January, but seemingly it was never implemented. I was told this is the right place to get patches in for PyGreSQL, so I'm reposting my patch here. I consider the inserttable methode essential in populating the database because of its benefits in performance compared to insert, so I think this patch is quite essential. The attachment is an improved version of the corresponding pg_inserttable function in pgmodule.c, which fixes the following problems: * The function raised exceptions because PyList_GetItem was used beyond the size of the list. This was checked by comparing the result with NULL, but the exception was not cleaned up, which could result in mysterious errors in the following Python code. Instead of clearing the exception using PyErr_Clear or something like that, I avoided throwing the exception at all by at first requesting the size of the list. Using this opportunity, I also checked the uniformity of the size of the rows passed in the lists/tuples. The function also accepts (and silently ignores) empty lists and sublists. * Python "None" values are now accepted and properly converted to PostgreSQL NULL values * The function now generates an error message in case of a line buffer overflow * It copes with tabulators, newlines and backslashes in strings now * Rewrote the buffer filling code which should now run faster by avoiding unnecessary string copy operations forth and back Christoph Zwerschke
2002-12-05 22:19:28 -05:00
sublist = getitem(list, i);
if (PyTuple_Check(sublist))
j = PyTuple_Size(sublist);
else if (PyList_Check(sublist))
j = PyList_Size(sublist);
else
1999-05-17 02:15:31 -04:00
{
PyGreSQL inserttable patch ===================== I suggested an improvement of the inserttable in the PyGreSQL interface already in January, but seemingly it was never implemented. I was told this is the right place to get patches in for PyGreSQL, so I'm reposting my patch here. I consider the inserttable methode essential in populating the database because of its benefits in performance compared to insert, so I think this patch is quite essential. The attachment is an improved version of the corresponding pg_inserttable function in pgmodule.c, which fixes the following problems: * The function raised exceptions because PyList_GetItem was used beyond the size of the list. This was checked by comparing the result with NULL, but the exception was not cleaned up, which could result in mysterious errors in the following Python code. Instead of clearing the exception using PyErr_Clear or something like that, I avoided throwing the exception at all by at first requesting the size of the list. Using this opportunity, I also checked the uniformity of the size of the rows passed in the lists/tuples. The function also accepts (and silently ignores) empty lists and sublists. * Python "None" values are now accepted and properly converted to PostgreSQL NULL values * The function now generates an error message in case of a line buffer overflow * It copes with tabulators, newlines and backslashes in strings now * Rewrote the buffer filling code which should now run faster by avoiding unnecessary string copy operations forth and back Christoph Zwerschke
2002-12-05 22:19:28 -05:00
PyErr_SetString(PyExc_TypeError,
"second arg must contain some kind of arrays.");
return NULL;
1999-05-17 02:15:31 -04:00
}
PyGreSQL inserttable patch ===================== I suggested an improvement of the inserttable in the PyGreSQL interface already in January, but seemingly it was never implemented. I was told this is the right place to get patches in for PyGreSQL, so I'm reposting my patch here. I consider the inserttable methode essential in populating the database because of its benefits in performance compared to insert, so I think this patch is quite essential. The attachment is an improved version of the corresponding pg_inserttable function in pgmodule.c, which fixes the following problems: * The function raised exceptions because PyList_GetItem was used beyond the size of the list. This was checked by comparing the result with NULL, but the exception was not cleaned up, which could result in mysterious errors in the following Python code. Instead of clearing the exception using PyErr_Clear or something like that, I avoided throwing the exception at all by at first requesting the size of the list. Using this opportunity, I also checked the uniformity of the size of the rows passed in the lists/tuples. The function also accepts (and silently ignores) empty lists and sublists. * Python "None" values are now accepted and properly converted to PostgreSQL NULL values * The function now generates an error message in case of a line buffer overflow * It copes with tabulators, newlines and backslashes in strings now * Rewrote the buffer filling code which should now run faster by avoiding unnecessary string copy operations forth and back Christoph Zwerschke
2002-12-05 22:19:28 -05:00
if (i)
1999-05-17 02:15:31 -04:00
{
PyGreSQL inserttable patch ===================== I suggested an improvement of the inserttable in the PyGreSQL interface already in January, but seemingly it was never implemented. I was told this is the right place to get patches in for PyGreSQL, so I'm reposting my patch here. I consider the inserttable methode essential in populating the database because of its benefits in performance compared to insert, so I think this patch is quite essential. The attachment is an improved version of the corresponding pg_inserttable function in pgmodule.c, which fixes the following problems: * The function raised exceptions because PyList_GetItem was used beyond the size of the list. This was checked by comparing the result with NULL, but the exception was not cleaned up, which could result in mysterious errors in the following Python code. Instead of clearing the exception using PyErr_Clear or something like that, I avoided throwing the exception at all by at first requesting the size of the list. Using this opportunity, I also checked the uniformity of the size of the rows passed in the lists/tuples. The function also accepts (and silently ignores) empty lists and sublists. * Python "None" values are now accepted and properly converted to PostgreSQL NULL values * The function now generates an error message in case of a line buffer overflow * It copes with tabulators, newlines and backslashes in strings now * Rewrote the buffer filling code which should now run faster by avoiding unnecessary string copy operations forth and back Christoph Zwerschke
2002-12-05 22:19:28 -05:00
if (j != n)
{
PyErr_SetString(PyExc_TypeError,
"arrays contained in second arg must have same size.");
return NULL;
}
1999-05-17 02:15:31 -04:00
}
else
n = j; /* never used before this assignment */
PyGreSQL inserttable patch ===================== I suggested an improvement of the inserttable in the PyGreSQL interface already in January, but seemingly it was never implemented. I was told this is the right place to get patches in for PyGreSQL, so I'm reposting my patch here. I consider the inserttable methode essential in populating the database because of its benefits in performance compared to insert, so I think this patch is quite essential. The attachment is an improved version of the corresponding pg_inserttable function in pgmodule.c, which fixes the following problems: * The function raised exceptions because PyList_GetItem was used beyond the size of the list. This was checked by comparing the result with NULL, but the exception was not cleaned up, which could result in mysterious errors in the following Python code. Instead of clearing the exception using PyErr_Clear or something like that, I avoided throwing the exception at all by at first requesting the size of the list. Using this opportunity, I also checked the uniformity of the size of the rows passed in the lists/tuples. The function also accepts (and silently ignores) empty lists and sublists. * Python "None" values are now accepted and properly converted to PostgreSQL NULL values * The function now generates an error message in case of a line buffer overflow * It copes with tabulators, newlines and backslashes in strings now * Rewrote the buffer filling code which should now run faster by avoiding unnecessary string copy operations forth and back Christoph Zwerschke
2002-12-05 22:19:28 -05:00
}
if (n)
{
/* allocate buffer */
if (!(buffer = malloc(MAX_BUFFER_SIZE)))
{
PyErr_SetString(PyExc_MemoryError,
"can't allocate insert buffer.");
return NULL;
}
/* starts query */
sprintf(buffer, "copy %s from stdin", table);
Py_BEGIN_ALLOW_THREADS
result = PQexec(self->cnx, buffer);
Py_END_ALLOW_THREADS
if (!result)
1999-05-17 02:15:31 -04:00
{
free(buffer);
PyGreSQL inserttable patch ===================== I suggested an improvement of the inserttable in the PyGreSQL interface already in January, but seemingly it was never implemented. I was told this is the right place to get patches in for PyGreSQL, so I'm reposting my patch here. I consider the inserttable methode essential in populating the database because of its benefits in performance compared to insert, so I think this patch is quite essential. The attachment is an improved version of the corresponding pg_inserttable function in pgmodule.c, which fixes the following problems: * The function raised exceptions because PyList_GetItem was used beyond the size of the list. This was checked by comparing the result with NULL, but the exception was not cleaned up, which could result in mysterious errors in the following Python code. Instead of clearing the exception using PyErr_Clear or something like that, I avoided throwing the exception at all by at first requesting the size of the list. Using this opportunity, I also checked the uniformity of the size of the rows passed in the lists/tuples. The function also accepts (and silently ignores) empty lists and sublists. * Python "None" values are now accepted and properly converted to PostgreSQL NULL values * The function now generates an error message in case of a line buffer overflow * It copes with tabulators, newlines and backslashes in strings now * Rewrote the buffer filling code which should now run faster by avoiding unnecessary string copy operations forth and back Christoph Zwerschke
2002-12-05 22:19:28 -05:00
PyErr_SetString(PyExc_ValueError, PQerrorMessage(self->cnx));
1999-05-17 02:15:31 -04:00
return NULL;
}
PyGreSQL inserttable patch ===================== I suggested an improvement of the inserttable in the PyGreSQL interface already in January, but seemingly it was never implemented. I was told this is the right place to get patches in for PyGreSQL, so I'm reposting my patch here. I consider the inserttable methode essential in populating the database because of its benefits in performance compared to insert, so I think this patch is quite essential. The attachment is an improved version of the corresponding pg_inserttable function in pgmodule.c, which fixes the following problems: * The function raised exceptions because PyList_GetItem was used beyond the size of the list. This was checked by comparing the result with NULL, but the exception was not cleaned up, which could result in mysterious errors in the following Python code. Instead of clearing the exception using PyErr_Clear or something like that, I avoided throwing the exception at all by at first requesting the size of the list. Using this opportunity, I also checked the uniformity of the size of the rows passed in the lists/tuples. The function also accepts (and silently ignores) empty lists and sublists. * Python "None" values are now accepted and properly converted to PostgreSQL NULL values * The function now generates an error message in case of a line buffer overflow * It copes with tabulators, newlines and backslashes in strings now * Rewrote the buffer filling code which should now run faster by avoiding unnecessary string copy operations forth and back Christoph Zwerschke
2002-12-05 22:19:28 -05:00
PQclear(result);
1999-05-17 02:15:31 -04:00
PyGreSQL inserttable patch ===================== I suggested an improvement of the inserttable in the PyGreSQL interface already in January, but seemingly it was never implemented. I was told this is the right place to get patches in for PyGreSQL, so I'm reposting my patch here. I consider the inserttable methode essential in populating the database because of its benefits in performance compared to insert, so I think this patch is quite essential. The attachment is an improved version of the corresponding pg_inserttable function in pgmodule.c, which fixes the following problems: * The function raised exceptions because PyList_GetItem was used beyond the size of the list. This was checked by comparing the result with NULL, but the exception was not cleaned up, which could result in mysterious errors in the following Python code. Instead of clearing the exception using PyErr_Clear or something like that, I avoided throwing the exception at all by at first requesting the size of the list. Using this opportunity, I also checked the uniformity of the size of the rows passed in the lists/tuples. The function also accepts (and silently ignores) empty lists and sublists. * Python "None" values are now accepted and properly converted to PostgreSQL NULL values * The function now generates an error message in case of a line buffer overflow * It copes with tabulators, newlines and backslashes in strings now * Rewrote the buffer filling code which should now run faster by avoiding unnecessary string copy operations forth and back Christoph Zwerschke
2002-12-05 22:19:28 -05:00
/* feeds table */
for (i = 0; i < m; i++)
{
sublist = getitem(list, i);
if (PyTuple_Check(sublist))
getsubitem = PyTuple_GetItem;
else
getsubitem = PyList_GetItem;
/* builds insert line */
bufpt=buffer;
bufsiz = MAX_BUFFER_SIZE - 1;
for (j = 0; j < n; j++)
{
item = getsubitem(sublist, j);
/* converts item to string */
if (item == Py_None)
{
if (bufsiz > 2)
{
*bufpt++ = '\\'; *bufpt++ = 'N';
bufsiz -= 2;
}
else
bufsiz = 0;
}
else if (PyString_Check(item))
{
temp = PyString_AS_STRING(item);
while (*temp && bufsiz)
{
if (*temp == '\\'
|| *temp == '\t'
|| *temp == '\n')
{
*bufpt++='\\'; --bufsiz;
if (!bufsiz) break;
}
*bufpt++=*temp++; --bufsiz;
}
}
else if (PyInt_Check(item))
{
long k;
int h;
k = PyInt_AsLong(item);
h = snprintf(bufpt, bufsiz, "%ld", k);
if (h > 0)
{
bufpt += h; bufsiz -= h;
}
else
bufsiz = 0;
}
else if (PyLong_Check(item))
{
long k;
int h;
k = PyLong_AsLong(item);
h = snprintf(bufpt, bufsiz, "%ld", k);
if (h > 0)
{
bufpt += h; bufsiz -= h;
}
else
bufsiz = 0;
}
else if (PyFloat_Check(item))
{
double k;
int h;
k = PyFloat_AS_DOUBLE(item);
h = snprintf(bufpt, bufsiz, "%g", k);
if (h > 0)
{
bufpt += h; bufsiz -= h;
}
else
bufsiz = 0;
}
else
{
free(buffer);
PyErr_SetString(PyExc_ValueError,
"items must be strings, integers, "
"longs or double (real).");
return NULL;
}
if (j < n-1)
{
*bufpt++ = '\t'; --bufsiz;
}
if (bufsiz <= 0)
{
free(buffer);
PyErr_SetString(PyExc_MemoryError,
"insert buffer overflow.");
return NULL;
}
1999-05-17 02:15:31 -04:00
PyGreSQL inserttable patch ===================== I suggested an improvement of the inserttable in the PyGreSQL interface already in January, but seemingly it was never implemented. I was told this is the right place to get patches in for PyGreSQL, so I'm reposting my patch here. I consider the inserttable methode essential in populating the database because of its benefits in performance compared to insert, so I think this patch is quite essential. The attachment is an improved version of the corresponding pg_inserttable function in pgmodule.c, which fixes the following problems: * The function raised exceptions because PyList_GetItem was used beyond the size of the list. This was checked by comparing the result with NULL, but the exception was not cleaned up, which could result in mysterious errors in the following Python code. Instead of clearing the exception using PyErr_Clear or something like that, I avoided throwing the exception at all by at first requesting the size of the list. Using this opportunity, I also checked the uniformity of the size of the rows passed in the lists/tuples. The function also accepts (and silently ignores) empty lists and sublists. * Python "None" values are now accepted and properly converted to PostgreSQL NULL values * The function now generates an error message in case of a line buffer overflow * It copes with tabulators, newlines and backslashes in strings now * Rewrote the buffer filling code which should now run faster by avoiding unnecessary string copy operations forth and back Christoph Zwerschke
2002-12-05 22:19:28 -05:00
}
1999-05-17 02:15:31 -04:00
PyGreSQL inserttable patch ===================== I suggested an improvement of the inserttable in the PyGreSQL interface already in January, but seemingly it was never implemented. I was told this is the right place to get patches in for PyGreSQL, so I'm reposting my patch here. I consider the inserttable methode essential in populating the database because of its benefits in performance compared to insert, so I think this patch is quite essential. The attachment is an improved version of the corresponding pg_inserttable function in pgmodule.c, which fixes the following problems: * The function raised exceptions because PyList_GetItem was used beyond the size of the list. This was checked by comparing the result with NULL, but the exception was not cleaned up, which could result in mysterious errors in the following Python code. Instead of clearing the exception using PyErr_Clear or something like that, I avoided throwing the exception at all by at first requesting the size of the list. Using this opportunity, I also checked the uniformity of the size of the rows passed in the lists/tuples. The function also accepts (and silently ignores) empty lists and sublists. * Python "None" values are now accepted and properly converted to PostgreSQL NULL values * The function now generates an error message in case of a line buffer overflow * It copes with tabulators, newlines and backslashes in strings now * Rewrote the buffer filling code which should now run faster by avoiding unnecessary string copy operations forth and back Christoph Zwerschke
2002-12-05 22:19:28 -05:00
*bufpt++ = '\n'; *bufpt = '\0';
1999-05-17 02:15:31 -04:00
PyGreSQL inserttable patch ===================== I suggested an improvement of the inserttable in the PyGreSQL interface already in January, but seemingly it was never implemented. I was told this is the right place to get patches in for PyGreSQL, so I'm reposting my patch here. I consider the inserttable methode essential in populating the database because of its benefits in performance compared to insert, so I think this patch is quite essential. The attachment is an improved version of the corresponding pg_inserttable function in pgmodule.c, which fixes the following problems: * The function raised exceptions because PyList_GetItem was used beyond the size of the list. This was checked by comparing the result with NULL, but the exception was not cleaned up, which could result in mysterious errors in the following Python code. Instead of clearing the exception using PyErr_Clear or something like that, I avoided throwing the exception at all by at first requesting the size of the list. Using this opportunity, I also checked the uniformity of the size of the rows passed in the lists/tuples. The function also accepts (and silently ignores) empty lists and sublists. * Python "None" values are now accepted and properly converted to PostgreSQL NULL values * The function now generates an error message in case of a line buffer overflow * It copes with tabulators, newlines and backslashes in strings now * Rewrote the buffer filling code which should now run faster by avoiding unnecessary string copy operations forth and back Christoph Zwerschke
2002-12-05 22:19:28 -05:00
/* sends data */
PQputline(self->cnx, buffer);
}
/* ends query */
PQputline(self->cnx, "\\.\n");
PQendcopy(self->cnx);
free(buffer);
}
}
1999-05-17 02:15:31 -04:00
/* no error : returns nothing */
Py_INCREF(Py_None);
return Py_None;
}
/* creates large object */
1999-05-25 12:15:34 -04:00
static char pg_locreate__doc__[] =
2001-03-21 23:01:46 -05:00
"locreate() -- creates a new large object in the database.";
1999-05-25 12:15:34 -04:00
static PyObject *
pg_locreate(pgobject * self, PyObject * args)
{
2001-03-21 23:01:46 -05:00
int mode;
Oid lo_oid;
/* checks validity */
if (!check_cnx_obj(self))
1999-05-25 12:15:34 -04:00
return NULL;
/* gets arguments */
if (!PyArg_ParseTuple(args, "i", &mode))
{
PyErr_SetString(PyExc_TypeError,
2001-03-21 23:01:46 -05:00
"locreate(mode), with mode (integer).");
return NULL;
}
/* creates large object */
lo_oid = lo_creat(self->cnx, mode);
1999-05-25 12:15:34 -04:00
if (lo_oid == 0)
{
PyErr_SetString(PGError, "can't create large object.");
return NULL;
1999-05-25 12:15:34 -04:00
}
return (PyObject *) pglarge_new(self, lo_oid);
}
/* init from already known oid */
1999-05-25 12:15:34 -04:00
static char pg_getlo__doc__[] =
2001-03-21 23:01:46 -05:00
"getlo(long) -- create a large object instance for the specified oid.";
static PyObject *
pg_getlo(pgobject * self, PyObject * args)
{
2001-03-21 23:01:46 -05:00
int lo_oid;
/* checks validity */
if (!check_cnx_obj(self))
1999-05-25 12:15:34 -04:00
return NULL;
/* gets arguments */
if (!PyArg_ParseTuple(args, "i", &lo_oid))
{
PyErr_SetString(PyExc_TypeError, "getlo(oid), with oid (integer).");
return NULL;
}
if (!lo_oid)
{
PyErr_SetString(PyExc_ValueError, "the object oid can't be null.");
return NULL;
}
/* creates object */
return (PyObject *) pglarge_new(self, lo_oid);
}
/* import unix file */
1999-05-25 12:15:34 -04:00
static char pg_loimport__doc__[] =
2001-03-21 23:01:46 -05:00
"loimport(string) -- create a new large object from specified file.";
static PyObject *
pg_loimport(pgobject * self, PyObject * args)
{
2001-03-21 23:01:46 -05:00
char *name;
Oid lo_oid;
/* checks validity */
if (!check_cnx_obj(self))
1999-05-25 12:15:34 -04:00
return NULL;
/* gets arguments */
if (!PyArg_ParseTuple(args, "s", &name))
{
PyErr_SetString(PyExc_TypeError, "loimport(name), with name (string).");
return NULL;
}
/* imports file and checks result */
lo_oid = lo_import(self->cnx, name);
if (lo_oid == 0)
{
PyErr_SetString(PGError, "can't create large object.");
return NULL;
}
return (PyObject *) pglarge_new(self, lo_oid);
}
1999-05-17 02:15:31 -04:00
/* connection object methods */
static struct PyMethodDef pgobj_methods[] = {
2001-03-21 23:01:46 -05:00
{"source", (PyCFunction) pg_source, 1, pg_source__doc__},
{"query", (PyCFunction) pg_query, 1, pg_query__doc__},
{"reset", (PyCFunction) pg_reset, 1, pg_reset__doc__},
{"close", (PyCFunction) pg_close, 1, pg_close__doc__},
{"fileno", (PyCFunction) pg_fileno, 1, pg_fileno__doc__},
{"getnotify", (PyCFunction) pg_getnotify, 1, pg_getnotify__doc__},
{"inserttable", (PyCFunction) pg_inserttable, 1, pg_inserttable__doc__},
1999-05-17 02:15:31 -04:00
#ifdef DIRECT_ACCESS
2001-03-21 23:01:46 -05:00
{"putline", (PyCFunction) pg_putline, 1, pg_putline__doc__},
{"getline", (PyCFunction) pg_getline, 1, pg_getline__doc__},
{"endcopy", (PyCFunction) pg_endcopy, 1, pg_endcopy__doc__},
#endif /* DIRECT_ACCESS */
1999-05-17 02:15:31 -04:00
#ifdef LARGE_OBJECTS
2001-03-21 23:01:46 -05:00
{"locreate", (PyCFunction) pg_locreate, 1, pg_locreate__doc__},
{"getlo", (PyCFunction) pg_getlo, 1, pg_getlo__doc__},
{"loimport", (PyCFunction) pg_loimport, 1, pg_loimport__doc__},
#endif /* LARGE_OBJECTS */
1999-05-17 02:15:31 -04:00
{NULL, NULL} /* sentinel */
};
/* get attribute */
static PyObject *
pg_getattr(pgobject * self, char *name)
{
2001-03-21 23:01:46 -05:00
/*
* Although we could check individually, there are only a few
* attributes that don't require a live connection and unless someone
* has an urgent need, this will have to do
1999-05-25 12:15:34 -04:00
*/
1999-05-17 02:15:31 -04:00
if (!self->cnx)
{
PyErr_SetString(PyExc_TypeError, "Connection is not valid");
return NULL;
}
/* list postgreSQL connection fields */
/* postmaster host */
if (!strcmp(name, "host"))
{
2001-03-21 23:01:46 -05:00
char *r = PQhost(self->cnx);
1999-05-17 02:15:31 -04:00
return r ? PyString_FromString(r) : PyString_FromString("localhost");
}
/* postmaster port */
if (!strcmp(name, "port"))
return PyInt_FromLong(atol(PQport(self->cnx)));
/* selected database */
if (!strcmp(name, "db"))
return PyString_FromString(PQdb(self->cnx));
/* selected options */
if (!strcmp(name, "options"))
return PyString_FromString(PQoptions(self->cnx));
/* selected postgres tty */
if (!strcmp(name, "tty"))
return PyString_FromString(PQtty(self->cnx));
/* error (status) message */
if (!strcmp(name, "error"))
return PyString_FromString(PQerrorMessage(self->cnx));
/* connection status : 1 - OK, 0 - BAD */
if (!strcmp(name, "status"))
return PyInt_FromLong(PQstatus(self->cnx) == CONNECTION_OK ? 1 : 0);
/* provided user name */
if (!strcmp(name, "user"))
return PyString_FromString("Deprecated facility");
2001-03-21 23:01:46 -05:00
/* return PyString_FromString(fe_getauthname("<unknown user>")); */
1999-05-17 02:15:31 -04:00
/* attributes list */
if (!strcmp(name, "__members__"))
{
2001-03-21 23:01:46 -05:00
PyObject *list = PyList_New(8);
1999-05-17 02:15:31 -04:00
if (list)
{
PyList_SET_ITEM(list, 0, PyString_FromString("host"));
PyList_SET_ITEM(list, 1, PyString_FromString("port"));
PyList_SET_ITEM(list, 2, PyString_FromString("db"));
PyList_SET_ITEM(list, 3, PyString_FromString("options"));
PyList_SET_ITEM(list, 4, PyString_FromString("tty"));
PyList_SET_ITEM(list, 5, PyString_FromString("error"));
PyList_SET_ITEM(list, 6, PyString_FromString("status"));
PyList_SET_ITEM(list, 7, PyString_FromString("user"));
1999-05-17 02:15:31 -04:00
}
return list;
}
return Py_FindMethod(pgobj_methods, (PyObject *) self, name);
}
/* object type definition */
staticforward PyTypeObject PgType = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"pgobject", /* tp_name */
sizeof(pgobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor) pg_dealloc, /* tp_dealloc */
0, /* tp_print */
(getattrfunc) pg_getattr, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
};
/* query object methods */
static struct PyMethodDef pgquery_methods[] = {
2001-03-21 23:01:46 -05:00
{"getresult", (PyCFunction) pgquery_getresult, 1, pgquery_getresult__doc__},
{"dictresult", (PyCFunction) pgquery_dictresult, 1, pgquery_dictresult__doc__},
{"fieldname", (PyCFunction) pgquery_fieldname, 1, pgquery_fieldname__doc__},
{"fieldnum", (PyCFunction) pgquery_fieldnum, 1, pgquery_fieldnum__doc__},
{"listfields", (PyCFunction) pgquery_listfields, 1, pgquery_listfields__doc__},
{"ntuples", (PyCFunction) pgquery_ntuples, 1, pgquery_ntuples__doc__},
{NULL, NULL}
1999-05-17 02:15:31 -04:00
};
1999-05-25 12:15:34 -04:00
/* gets query object attributes */
1999-05-17 02:15:31 -04:00
static PyObject *
pgquery_getattr(pgqueryobject * self, char *name)
1999-05-17 02:15:31 -04:00
{
/* list postgreSQL connection fields */
return Py_FindMethod(pgquery_methods, (PyObject *) self, name);
}
/* query type definition */
staticforward PyTypeObject PgQueryType = {
PyObject_HEAD_INIT(NULL)
2001-03-21 23:01:46 -05:00
0, /* ob_size */
"pgqueryobject", /* tp_name */
sizeof(pgqueryobject), /* tp_basicsize */
0, /* tp_itemsize */
1999-05-17 02:15:31 -04:00
/* methods */
2001-03-21 23:01:46 -05:00
(destructor) pgquery_dealloc, /* tp_dealloc */
(printfunc) pgquery_print, /* tp_print */
(getattrfunc) pgquery_getattr, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc) pgquery_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
1999-05-17 02:15:31 -04:00
};
/* --------------------------------------------------------------------- */
/* MODULE FUNCTIONS */
#ifdef DEFAULT_VARS
/* gets default host */
static char getdefhost__doc__[] =
2001-03-21 23:01:46 -05:00
"get_defhost() -- return default database host.";
1999-05-25 12:15:34 -04:00
static PyObject *
2001-03-21 23:01:46 -05:00
pggetdefhost(PyObject * self, PyObject * args)
1999-05-17 02:15:31 -04:00
{
/* checks args */
if (!PyArg_ParseTuple(args, ""))
{
PyErr_SetString(PyExc_SyntaxError,
2001-03-21 23:01:46 -05:00
"method get_defhost() takes no parameter.");
1999-05-17 02:15:31 -04:00
return NULL;
}
Py_XINCREF(pg_default_host);
return pg_default_host;
}
/* sets default host */
static char setdefhost__doc__[] =
2001-03-21 23:01:46 -05:00
"set_defhost(string) -- set default database host. Return previous value.";
1999-05-25 12:15:34 -04:00
static PyObject *
2001-03-21 23:01:46 -05:00
pgsetdefhost(PyObject * self, PyObject * args)
1999-05-17 02:15:31 -04:00
{
2001-03-21 23:01:46 -05:00
char *temp = NULL;
PyObject *old;
1999-05-17 02:15:31 -04:00
/* gets arguments */
if (!PyArg_ParseTuple(args, "z", &temp))
{
PyErr_SetString(PyExc_TypeError,
2001-03-21 23:01:46 -05:00
"set_defhost(name), with name (string/None).");
1999-05-17 02:15:31 -04:00
return NULL;
}
/* adjusts value */
old = pg_default_host;
if (temp)
pg_default_host = PyString_FromString(temp);
else
{
Py_INCREF(Py_None);
pg_default_host = Py_None;
}
return old;
}
/* gets default base */
static char getdefbase__doc__[] =
2001-03-21 23:01:46 -05:00
"get_defbase() -- return default database name.";
1999-05-25 12:15:34 -04:00
static PyObject *
2001-03-21 23:01:46 -05:00
pggetdefbase(PyObject * self, PyObject * args)
1999-05-17 02:15:31 -04:00
{
/* checks args */
if (!PyArg_ParseTuple(args, ""))
{
PyErr_SetString(PyExc_SyntaxError,
2001-03-21 23:01:46 -05:00
"method get_defbase() takes no parameter.");
1999-05-17 02:15:31 -04:00
return NULL;
}
Py_XINCREF(pg_default_base);
return pg_default_base;
}
/* sets default base */
static char setdefbase__doc__[] =
2001-03-21 23:01:46 -05:00
"set_defbase(string) -- set default database name. Return previous value";
1999-05-25 12:15:34 -04:00
static PyObject *
2001-03-21 23:01:46 -05:00
pgsetdefbase(PyObject * self, PyObject * args)
1999-05-17 02:15:31 -04:00
{
2001-03-21 23:01:46 -05:00
char *temp = NULL;
PyObject *old;
1999-05-17 02:15:31 -04:00
/* gets arguments */
if (!PyArg_ParseTuple(args, "z", &temp))
{
PyErr_SetString(PyExc_TypeError,
2001-03-21 23:01:46 -05:00
"set_defbase(name), with name (string/None).");
1999-05-17 02:15:31 -04:00
return NULL;
}
/* adjusts value */
old = pg_default_base;
if (temp)
pg_default_base = PyString_FromString(temp);
else
{
Py_INCREF(Py_None);
pg_default_base = Py_None;
}
return old;
}
/* gets default options */
static char getdefopt__doc__[] =
2001-03-21 23:01:46 -05:00
"get_defopt() -- return default database options.";
1999-05-25 12:15:34 -04:00
static PyObject *
2001-03-21 23:01:46 -05:00
pggetdefopt(PyObject * self, PyObject * args)
1999-05-17 02:15:31 -04:00
{
/* checks args */
if (!PyArg_ParseTuple(args, ""))
{
PyErr_SetString(PyExc_SyntaxError,
2001-03-21 23:01:46 -05:00
"method get_defopt() takes no parameter.");
1999-05-17 02:15:31 -04:00
return NULL;
}
Py_XINCREF(pg_default_opt);
return pg_default_opt;
}
/* sets default opt */
static char setdefopt__doc__[] =
2001-03-21 23:01:46 -05:00
"set_defopt(string) -- set default database options. Return previous value.";
1999-05-25 12:15:34 -04:00
static PyObject *
2001-03-21 23:01:46 -05:00
pgsetdefopt(PyObject * self, PyObject * args)
1999-05-17 02:15:31 -04:00
{
2001-03-21 23:01:46 -05:00
char *temp = NULL;
PyObject *old;
1999-05-17 02:15:31 -04:00
/* gets arguments */
if (!PyArg_ParseTuple(args, "z", &temp))
{
PyErr_SetString(PyExc_TypeError,
2001-03-21 23:01:46 -05:00
"set_defopt(name), with name (string/None).");
1999-05-17 02:15:31 -04:00
return NULL;
}
/* adjusts value */
old = pg_default_opt;
if (temp)
pg_default_opt = PyString_FromString(temp);
else
{
Py_INCREF(Py_None);
pg_default_opt = Py_None;
}
return old;
}
/* gets default tty */
static char getdeftty__doc__[] =
2001-03-21 23:01:46 -05:00
"get_deftty() -- return default database debug terminal.";
1999-05-25 12:15:34 -04:00
static PyObject *
2001-03-21 23:01:46 -05:00
pggetdeftty(PyObject * self, PyObject * args)
1999-05-17 02:15:31 -04:00
{
/* checks args */
if (!PyArg_ParseTuple(args, ""))
{
PyErr_SetString(PyExc_SyntaxError,
2001-03-21 23:01:46 -05:00
"method get_deftty() takes no parameter.");
1999-05-17 02:15:31 -04:00
return NULL;
}
Py_XINCREF(pg_default_tty);
return pg_default_tty;
}
/* sets default tty */
static char setdeftty__doc__[] =
2001-03-21 23:01:46 -05:00
"set_deftty(string) -- set default database debug terminal. "
"Return previous value.";
1999-05-25 12:15:34 -04:00
static PyObject *
2001-03-21 23:01:46 -05:00
pgsetdeftty(PyObject * self, PyObject * args)
1999-05-17 02:15:31 -04:00
{
2001-03-21 23:01:46 -05:00
char *temp = NULL;
PyObject *old;
1999-05-17 02:15:31 -04:00
/* gets arguments */
if (!PyArg_ParseTuple(args, "z", &temp))
{
PyErr_SetString(PyExc_TypeError,
2001-03-21 23:01:46 -05:00
"set_deftty(name), with name (string/None).");
1999-05-17 02:15:31 -04:00
return NULL;
}
/* adjusts value */
old = pg_default_tty;
if (temp)
pg_default_tty = PyString_FromString(temp);
else
{
Py_INCREF(Py_None);
pg_default_tty = Py_None;
}
return old;
}
/* gets default username */
static char getdefuser__doc__[] =
2001-03-21 23:01:46 -05:00
"get_defuser() -- return default database username.";
1999-05-25 12:15:34 -04:00
static PyObject *
2001-03-21 23:01:46 -05:00
pggetdefuser(PyObject * self, PyObject * args)
1999-05-17 02:15:31 -04:00
{
/* checks args */
if (!PyArg_ParseTuple(args, ""))
{
PyErr_SetString(PyExc_SyntaxError,
2001-03-21 23:01:46 -05:00
"method get_defuser() takes no parameter.");
1999-05-17 02:15:31 -04:00
return NULL;
}
Py_XINCREF(pg_default_user);
return pg_default_user;
}
/* sets default username */
static char setdefuser__doc__[] =
2001-03-21 23:01:46 -05:00
"set_defuser() -- set default database username. Return previous value.";
1999-05-25 12:15:34 -04:00
static PyObject *
2001-03-21 23:01:46 -05:00
pgsetdefuser(PyObject * self, PyObject * args)
1999-05-17 02:15:31 -04:00
{
2001-03-21 23:01:46 -05:00
char *temp = NULL;
PyObject *old;
1999-05-17 02:15:31 -04:00
/* gets arguments */
if (!PyArg_ParseTuple(args, "z", &temp))
{
PyErr_SetString(PyExc_TypeError,
2001-03-21 23:01:46 -05:00
"set_defuser(name), with name (string/None).");
1999-05-17 02:15:31 -04:00
return NULL;
}
/* adjusts value */
old = pg_default_user;
if (temp)
pg_default_user = PyString_FromString(temp);
else
{
Py_INCREF(Py_None);
pg_default_user = Py_None;
}
return old;
}
/* sets default password */
static char setdefpasswd__doc__[] =
2001-03-21 23:01:46 -05:00
"set_defpasswd() -- set default database password.";
1999-05-25 12:15:34 -04:00
static PyObject *
2001-03-21 23:01:46 -05:00
pgsetdefpasswd(PyObject * self, PyObject * args)
1999-05-17 02:15:31 -04:00
{
2001-03-21 23:01:46 -05:00
char *temp = NULL;
PyObject *old;
1999-05-17 02:15:31 -04:00
/* gets arguments */
if (!PyArg_ParseTuple(args, "z", &temp))
{
PyErr_SetString(PyExc_TypeError,
"set_defpasswd(password), with password (string/None).");
1999-05-17 02:15:31 -04:00
return NULL;
}
/* adjusts value */
old = pg_default_passwd;
if (temp)
pg_default_passwd = PyString_FromString(temp);
else
{
Py_INCREF(Py_None);
pg_default_passwd = Py_None;
}
1999-05-25 12:15:34 -04:00
Py_INCREF(Py_None);
return Py_None;
1999-05-17 02:15:31 -04:00
}
/* gets default port */
static char getdefport__doc__[] =
2001-03-21 23:01:46 -05:00
"get_defport() -- return default database port.";
1999-05-25 12:15:34 -04:00
static PyObject *
2001-03-21 23:01:46 -05:00
pggetdefport(PyObject * self, PyObject * args)
1999-05-17 02:15:31 -04:00
{
/* checks args */
if (!PyArg_ParseTuple(args, ""))
{
PyErr_SetString(PyExc_SyntaxError,
2001-03-21 23:01:46 -05:00
"method get_defport() takes no parameter.");
1999-05-17 02:15:31 -04:00
return NULL;
}
Py_XINCREF(pg_default_port);
return pg_default_port;
}
/* sets default port */
static char setdefport__doc__[] =
2001-03-21 23:01:46 -05:00
"set_defport(integer) -- set default database port. Return previous value.";
1999-05-25 12:15:34 -04:00
static PyObject *
2001-03-21 23:01:46 -05:00
pgsetdefport(PyObject * self, PyObject * args)
1999-05-17 02:15:31 -04:00
{
1999-05-25 12:15:34 -04:00
long int port = -2;
2001-03-21 23:01:46 -05:00
PyObject *old;
1999-05-17 02:15:31 -04:00
/* gets arguments */
if ((!PyArg_ParseTuple(args, "l", &port)) || (port < -1))
{
PyErr_SetString(PyExc_TypeError, "set_defport(port), with port "
2001-03-21 23:01:46 -05:00
"(positive integer/-1).");
1999-05-17 02:15:31 -04:00
return NULL;
}
/* adjusts value */
old = pg_default_port;
if (port != -1)
pg_default_port = PyLong_FromLong(port);
else
{
Py_INCREF(Py_None);
pg_default_port = Py_None;
}
return old;
}
#endif /* DEFAULT_VARS */
1999-05-17 02:15:31 -04:00
/* List of functions defined in the module */
static struct PyMethodDef pg_methods[] = {
2001-03-21 23:01:46 -05:00
{"connect", (PyCFunction) pgconnect, 3, connect__doc__},
1999-05-17 02:15:31 -04:00
#ifdef DEFAULT_VARS
2001-03-21 23:01:46 -05:00
{"get_defhost", pggetdefhost, 1, getdefhost__doc__},
{"set_defhost", pgsetdefhost, 1, setdefhost__doc__},
{"get_defbase", pggetdefbase, 1, getdefbase__doc__},
{"set_defbase", pgsetdefbase, 1, setdefbase__doc__},
{"get_defopt", pggetdefopt, 1, getdefopt__doc__},
{"set_defopt", pgsetdefopt, 1, setdefopt__doc__},
{"get_deftty", pggetdeftty, 1, getdeftty__doc__},
{"set_deftty", pgsetdeftty, 1, setdeftty__doc__},
{"get_defport", pggetdefport, 1, getdefport__doc__},
{"set_defport", pgsetdefport, 1, setdefport__doc__},
{"get_defuser", pggetdefuser, 1, getdefuser__doc__},
{"set_defuser", pgsetdefuser, 1, setdefuser__doc__},
{"set_defpasswd", pgsetdefpasswd, 1, setdefpasswd__doc__},
#endif /* DEFAULT_VARS */
1999-05-17 02:15:31 -04:00
{NULL, NULL} /* sentinel */
};
1999-05-25 12:15:34 -04:00
static char pg__doc__[] = "Python interface to PostgreSQL DB";
1999-05-17 02:15:31 -04:00
/* Initialization function for the module */
2001-03-15 06:26:22 -05:00
DL_EXPORT(void)
1999-05-17 02:15:31 -04:00
init_pg(void)
{
2001-03-21 23:01:46 -05:00
PyObject *mod,
*dict,
*v;
1999-05-17 02:15:31 -04:00
/* Initialize here because some WIN platforms get confused otherwise */
PglargeType.ob_type = PgType.ob_type = PgQueryType.ob_type =
PgSourceType.ob_type = &PyType_Type;
1999-05-17 02:15:31 -04:00
/* Create the module and add the functions */
mod = Py_InitModule4("_pg", pg_methods, pg__doc__, NULL, PYTHON_API_VERSION);
dict = PyModule_GetDict(mod);
/* Add some symbolic constants to the module */
PGError = PyString_FromString("_pg.error");
1999-05-17 02:15:31 -04:00
PyDict_SetItemString(dict, "error", PGError);
/* Make the version available */
v = PyString_FromString(PyPgVersion);
PyDict_SetItemString(dict, "version", v);
PyDict_SetItemString(dict, "__version__", v);
Py_DECREF(v);
/* results type for queries */
PyDict_SetItemString(dict, "RESULT_EMPTY", PyInt_FromLong(RESULT_EMPTY));
PyDict_SetItemString(dict, "RESULT_DML", PyInt_FromLong(RESULT_DML));
PyDict_SetItemString(dict, "RESULT_DDL", PyInt_FromLong(RESULT_DDL));
PyDict_SetItemString(dict, "RESULT_DQL", PyInt_FromLong(RESULT_DQL));
1999-05-17 02:15:31 -04:00
#ifdef LARGE_OBJECTS
/* create mode for large objects */
PyDict_SetItemString(dict, "INV_READ", PyInt_FromLong(INV_READ));
PyDict_SetItemString(dict, "INV_WRITE", PyInt_FromLong(INV_WRITE));
/* position flags for lo_lseek */
PyDict_SetItemString(dict, "SEEK_SET", PyInt_FromLong(SEEK_SET));
PyDict_SetItemString(dict, "SEEK_CUR", PyInt_FromLong(SEEK_CUR));
PyDict_SetItemString(dict, "SEEK_END", PyInt_FromLong(SEEK_END));
#endif /* LARGE_OBJECTS */
1999-05-17 02:15:31 -04:00
#ifdef DEFAULT_VARS
/* prepares default values */
2001-03-21 23:01:46 -05:00
Py_INCREF(Py_None);
pg_default_host = Py_None;
Py_INCREF(Py_None);
pg_default_base = Py_None;
Py_INCREF(Py_None);
pg_default_opt = Py_None;
Py_INCREF(Py_None);
pg_default_port = Py_None;
Py_INCREF(Py_None);
pg_default_tty = Py_None;
Py_INCREF(Py_None);
pg_default_user = Py_None;
Py_INCREF(Py_None);
pg_default_passwd = Py_None;
#endif /* DEFAULT_VARS */
1999-05-17 02:15:31 -04:00
/* Check for errors */
if (PyErr_Occurred())
Py_FatalError("can't initialize module _pg");
}