Fix some quoting functions. In particular handle NULLs better.
Use a method to add primary key information rather than direct
manipulation of the class structures.
Break decimal out in _quote (in pg.py) and treat it as float.
Treat timestamp like date for quoting purposes.
Remove a redundant SELECT from the get method speeding it, and
insert since it calls get, up a little.
Add test for BOOL type in typecast method to pgdbTypeCache class.
(tv@beamnet.de)
Fix pgdb.py to send port as integer to lower level function
(dildog@l0pht.com)
Change pg.py to speed up some operations
Allow updates on tables with no primary keys.
D'Arcy J.M. Cain
-Announce: Release of PyGreSQL version 3.0
+Announce: Release of PyGreSQL version 3.1
===============================================
-PyGreSQL v3.0 has been released.
+PyGreSQL v3.1 has been released.
It is available at: ftp://ftp.druid.net/pub/distrib/PyGreSQL.tgz. If
you are running NetBSD, look in the packages directory under databases.
There is also a package in the FreeBSD ports collection.
embeds the PostgreSQL query library to allow easy use of the powerful
PostgreSQL features from a Python script.
-This release of PyGreSQL is the first DB-SIG API. That's why we have
-a bump in the major number. There is also a potential problem in
-backwards compatibility. Previously when there was a NULL in a returned
-field it was returned as a blank. Now it is more properly returned as
-a Python None. Any scripts that expect NULLs to be blanks will have
-problems with this.
+This release fixes a few bugs, adds a few minor features and makes a
+few speedups in the code.
-Due to the fact that the DB-API is brand new, it is expected that there
-will be a 3.1 release shortly with corrections once many people have
-had a chance to test it.
+The next release (unless serious bugs are found) will be to match PyGreSQL
+to version 2.0 of Python.
See the other changes below or in the Changelog file.
code for Python 1.5 and PostgreSQL 6.2.1. While I was at it I upgraded
the code to use full ANSI style prototypes and changed the order of
arguments to connect. Later versions are fixes and enhancements to that.
-The latest version of PyGreSQL works with Python 1.5.2 and PostgreSQL 6.5.
+The latest version of PyGreSQL works with Python 1.5.2 and PostgreSQL 7.0.x
+
+Important changes from PyGreSQL 3.0 to PyGreSQL 3.1
+ - Fix some quoting functions. In particular handle NULLs better.
+ - Use a method to add primary key information rather than direct
+ manipulation of the class structures.
+ - Break decimal out in _quote (in pg.py) and treat it as float.
+ - Treat timestamp like date for quoting purposes.
+ - Remove a redundant SELECT from the get method speeding it, and insert
+ since it calls get, up a little.
+ - Add test for BOOL type in typecast method to pgdbTypeCache class.
+ (tv@beamnet.de)
+ - Fix pgdb.py to send port as integer to lower level function
+ (dildog@l0pht.com)
+ - Change pg.py to speed up some operations
+ - Allow updates on tables with no primary keys.
Important changes from PyGreSQL 2.4 to PyGreSQL 3.0:
- Remove strlen() call from pglarge_write() and get size from object.
Further copyright 1997, 1998 and 1999 by D'Arcy J.M. Cain (darcy@druid.net)
See file README for copyright information.
+Version 3.1
+ - Fix some quoting functions. In particular handle NULLs better.
+ - Use a method to add primary key information rather than direct
+ manipulation of the class structures.
+ - Break decimal out in _quote (in pg.py) and treat it as float.
+ - Treat timestamp like date for quoting purposes.
+ - Remove a redundant SELECT from the get method speeding it, and insert
+ since it calls get, up a little.
+ - Add test for BOOL type in typecast method to pgdbTypeCache class.
+ (tv@beamnet.de)
+ - Fix pgdb.py to send port as integer to lower level function
+ (dildog@l0pht.com)
+ - Change pg.py to speed up some operations
+ - Allow updates on tables with no primary keys.
+
Version 3.0
- Remove strlen() call from pglarge_write() and get size from object.
(Richard@Bouska.cz)
that uses RPMs, then you can pick up an RPM at
ftp://ftp.druid.net/pub/distrib/pygresql.i386.rpm
+* Note that if you are using the DB-API module you must also install
+ mxDateTime from http://starship.python.net/~lemburg/mxDateTime.html.
+
* Also, check out setup.py for an alternate method of installing the package.
You have two options. You can compile PyGreSQL as a stand-alone module
STAND-ALONE
* In the directory containing pgmodule.c, run the following command
- cc -fpic -shared -o _pg.so -I[pyInc] -I[pgInc] -L[pgLib] -lpq # -lcrypt # needed on some systems
+ cc -fpic -shared -o _pg.so -I[pyInc] -I[pgInc] -L[pgLib] -lpq pgmodule.c
where:
[pyInc] = path of the Python include (usually Python.h)
[pgInc] = path of the PostgreSQL include (usually postgres.h)
-DNO_SNPRINTF - if running a system with no snprintf call
-DNO_PQSOCKET - if running an older PostgreSQL
+ On some systems you may need to include -lcrypt in the list of libraries
+ to make it compile.
+
Define NO_PQSOCKET if you are using a version of PostgreSQL before 6.4
that does not have the PQsocket function. The other options will be
described in the next sections.
The DB-API module needs to be documented.
+The fetch method should use real cursers.
+
6. Future directions
====================
-Thanks to thilo@eevolute.com for this README and the RPM
+Thanks to thilo@eevolute.com and others for this README and the RPM
Note: The precompiled RPM package is not available at www.eevolute.com.
You may use the spec file provided with PyGreSQL to build your
done!
+Oliver White (ojw@muzak.iinet.net.au) sent me the following information
+about installing on Debian.
+
+Hi, I thought you might want to upgrade your documentation for PyGreSQL
+to let people know they can get it by simply typing 'apt-get install
+python-pygresql', on debian (duh). This would have saved me a lot of
+trouble.
+
if d == None:
return "NULL"
- if t in ['int', 'decimal', 'seq']:
- if d == "": return 0
+ if t in ['int', 'seq']:
+ if d == "": return "NULL"
return "%d" % int(d)
+ if t == 'decimal':
+ if d == "": return "NULL"
+ return "%f" % float(d)
+
if t == 'money':
- if d == "": return '0.00'
+ if d == "": return "NULL"
return "'%.2f'" % float(d)
if t == 'bool':
- if string.upper(d) in ['T', 'TRUE', 'Y', 'YES', 1, '1', 'ON']:
+ # Can't run upper() on these
+ if d in (0, 1): return ('f', 't')[d]
+
+ if string.upper(d) in ['T', 'TRUE', 'Y', 'YES', '1', 'ON']:
return "'t'"
else:
return "'f'"
- if d == "": return "null"
+ if t == 'date' and d == '': return "NULL"
+ if t in ('inet', 'cidr') and d == '': return "NULL"
+
return "'%s'" % string.strip(re.sub("'", "''", \
re.sub("\\\\", "\\\\\\\\", "%s" %d)))
print self.debug % qstr
return self.db.query(qstr)
- def pkey(self, cl):
+ # If third arg supplied set primary key to it
+ def pkey(self, cl, newpkey = None):
+ if newpkey:
+ self.__pkeys__[cl] = newpkey
+
# will raise an exception if primary key doesn't exist
return self.__pkeys__[cl]
l[attname] = 'date'
elif re.match("^date", typname):
l[attname] = 'date'
+ elif re.match("^timestamp", typname):
+ l[attname] = 'date'
elif re.match("^bool", typname):
l[attname] = 'bool'
elif re.match("^float", typname):
# return a tuple from a database
def get(self, cl, arg, keyname = None, view = 0):
+ if cl[-1] == '*': # need parent table name
+ xcl = cl[:-1]
+ else:
+ xcl = cl
+
if keyname == None: # use the primary key by default
- keyname = self.__pkeys__[cl]
+ keyname = self.__pkeys__[xcl]
- fnames = self.get_attnames(cl)
+ fnames = self.get_attnames(xcl)
if type(arg) == type({}):
# To allow users to work with multiple tables we munge the
# name when the key is "oid"
- if keyname == 'oid': k = arg['oid_%s' % cl]
+ if keyname == 'oid': k = arg['oid_%s' % xcl]
else: k = arg[keyname]
else:
k = arg
(cl, keyname, _quote(k, fnames[keyname]))
else:
q = "SELECT oid AS oid_%s, %s FROM %s WHERE %s = %s" % \
- (cl, string.join(fnames.keys(), ','),\
+ (xcl, string.join(fnames.keys(), ','),\
cl, keyname, _quote(k, fnames[keyname]))
if self.debug != None: print self.debug % q
n = []
for f in fnames.keys():
if a.has_key(f):
- if a[f] == "": l.append("null")
- else: l.append(_quote(a[f], fnames[f]))
+ l.append(_quote(a[f], fnames[f]))
n.append(f)
try:
# otherwise use the primary key. Fail if neither.
def update(self, cl, a):
foid = 'oid_%s' % cl
- pk = self.__pkeys__[cl]
if a.has_key(foid):
where = "oid = %s" % a[foid]
- elif a.has_key(pk):
- where = "%s = '%s'" % (pk, a[pk])
+ elif self.__pkeys__.has_key(cl) and a.has_key(self.__pkeys__[cl]):
+ where = "%s = '%s'" % (self.__pkeys__[cl], a[self.__pkeys__[cl]])
else:
- raise error, "Update needs key (%s) or oid as %s" % (pk, foid)
-
- q = "SELECT oid FROM %s WHERE %s" % (cl, where)
- if self.debug != None: print self.debug % q
- res = self.db.query(q).getresult()
-
- if len(res) < 1:
- raise error, "No record in %s where %s (%s)" % \
- (cl, where, sys.exc_value)
- else: a[foid] = res[0][0]
+ raise error, "Update needs primary key or oid as %s" % foid
v = []
k = 0
fnames = self.get_attnames(cl)
for ff in fnames.keys():
- if a.has_key(ff) and a[ff] != res[0][k]:
+ if a.has_key(ff):
v.append("%s = %s" % (ff, _quote(a[ff], fnames[ff])))
if v == []:
return None
try:
- q = "UPDATE %s SET %s WHERE oid = %s" % \
- (cl, string.join(v, ','), a[foid])
+ q = "UPDATE %s SET %s WHERE %s" % \
+ (cl, string.join(v, ','), where)
if self.debug != None: print self.debug % q
self.db.query(q)
except:
raise error, "Can't update %s: %s" % (cl, sys.exc_value)
# reload the dictionary to catch things modified by engine
- return self.get(cl, a, 'oid')
+ if a.has_key(foid):
+ return self.get(cl, a, 'oid')
+ else:
+ return self.get(cl, a)
# At some point we will need a way to get defaults from a table
def clear(self, cl, a = {}):
pass
elif typ == BINARY:
pass
+ elif typ == BOOL:
+ value = (value[:1] in ['t','T'])
elif typ == INTEGER:
value = int(value)
elif typ == LONG:
try:
params = string.split(host, ":")
dbhost = params[0]
- dbport = params[1]
+ dbport = int(params[1])
except:
pass
#define CASHOID 790
static PyObject *PGError;
-static const char *PyPgVersion = "3.0";
+static const char *PyPgVersion = "3.1";
/* taken from fileobject.c */
#define BUF(v) PyString_AS_STRING((PyStringObject *)(v))
if (pgport != -1)
{
- bzero(port_buffer, sizeof(port_buffer));
+ memset(port_buffer, 0, sizeof(port_buffer));
sprintf(port_buffer, "%d", pgport);
npgobj->cnx = PQsetdbLogin(pghost, port_buffer, pgopt, pgtty, pgdbname,
pguser, pgpasswd);
if (!PyArg_ParseTuple(args, "z", &temp))
{
PyErr_SetString(PyExc_TypeError,
- "set_defpasswd(password), with password (string/
-None).");
+ "set_defpasswd(password), with password (string/None).");
return NULL;
}
from distutils.core import setup
setup (name = "PyGreSQL",
- version = "3.0",
+ version = "3.1",
description = "Python PostgreSQL Interfaces",
author = "D'Arcy J. M. Cain",
author_email = "darcy@druid.net",
This module is designed for being imported from python prompt
In order to run the samples included here, first create a connection
-using : cnx = advanced.DB(...)
+using : cnx = basics.DB(...)
The "..." should be replaced with whatever arguments you need to open an
existing database. Usually all you need is the name of the database and,