Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit eafb636

Browse files
committed
Update 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. D'Arcy J.M. Cain
1 parent 960c186 commit eafb636

File tree

9 files changed

+104
-50
lines changed

9 files changed

+104
-50
lines changed

src/interfaces/python/Announce

+22-12
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11

2-
Announce: Release of PyGreSQL version 3.0
2+
Announce: Release of PyGreSQL version 3.1
33
===============================================
44

5-
PyGreSQL v3.0 has been released.
5+
PyGreSQL v3.1 has been released.
66
It is available at: ftp://ftp.druid.net/pub/distrib/PyGreSQL.tgz. If
77
you are running NetBSD, look in the packages directory under databases.
88
There is also a package in the FreeBSD ports collection.
@@ -25,16 +25,11 @@ PyGreSQL is a python module that interfaces to a PostgreSQL database. It
2525
embeds the PostgreSQL query library to allow easy use of the powerful
2626
PostgreSQL features from a Python script.
2727

28-
This release of PyGreSQL is the first DB-SIG API. That's why we have
29-
a bump in the major number. There is also a potential problem in
30-
backwards compatibility. Previously when there was a NULL in a returned
31-
field it was returned as a blank. Now it is more properly returned as
32-
a Python None. Any scripts that expect NULLs to be blanks will have
33-
problems with this.
28+
This release fixes a few bugs, adds a few minor features and makes a
29+
few speedups in the code.
3430

35-
Due to the fact that the DB-API is brand new, it is expected that there
36-
will be a 3.1 release shortly with corrections once many people have
37-
had a chance to test it.
31+
The next release (unless serious bugs are found) will be to match PyGreSQL
32+
to version 2.0 of Python.
3833

3934
See the other changes below or in the Changelog file.
4035

@@ -44,7 +39,22 @@ andre@chimay.via.ecp.fr. I changed the version to 2.0 and updated the
4439
code for Python 1.5 and PostgreSQL 6.2.1. While I was at it I upgraded
4540
the code to use full ANSI style prototypes and changed the order of
4641
arguments to connect. Later versions are fixes and enhancements to that.
47-
The latest version of PyGreSQL works with Python 1.5.2 and PostgreSQL 6.5.
42+
The latest version of PyGreSQL works with Python 1.5.2 and PostgreSQL 7.0.x
43+
44+
Important changes from PyGreSQL 3.0 to PyGreSQL 3.1
45+
- Fix some quoting functions. In particular handle NULLs better.
46+
- Use a method to add primary key information rather than direct
47+
manipulation of the class structures.
48+
- Break decimal out in _quote (in pg.py) and treat it as float.
49+
- Treat timestamp like date for quoting purposes.
50+
- Remove a redundant SELECT from the get method speeding it, and insert
51+
since it calls get, up a little.
52+
- Add test for BOOL type in typecast method to pgdbTypeCache class.
53+
(tv@beamnet.de)
54+
- Fix pgdb.py to send port as integer to lower level function
55+
(dildog@l0pht.com)
56+
- Change pg.py to speed up some operations
57+
- Allow updates on tables with no primary keys.
4858

4959
Important changes from PyGreSQL 2.4 to PyGreSQL 3.0:
5060
- Remove strlen() call from pglarge_write() and get size from object.

src/interfaces/python/ChangeLog

+15
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,21 @@ This software is copyright (c) 1995, Pascal Andre (andre@via.ecp.fr)
55
Further copyright 1997, 1998 and 1999 by D'Arcy J.M. Cain (darcy@druid.net)
66
See file README for copyright information.
77

8+
Version 3.1
9+
- Fix some quoting functions. In particular handle NULLs better.
10+
- Use a method to add primary key information rather than direct
11+
manipulation of the class structures.
12+
- Break decimal out in _quote (in pg.py) and treat it as float.
13+
- Treat timestamp like date for quoting purposes.
14+
- Remove a redundant SELECT from the get method speeding it, and insert
15+
since it calls get, up a little.
16+
- Add test for BOOL type in typecast method to pgdbTypeCache class.
17+
(tv@beamnet.de)
18+
- Fix pgdb.py to send port as integer to lower level function
19+
(dildog@l0pht.com)
20+
- Change pg.py to speed up some operations
21+
- Allow updates on tables with no primary keys.
22+
823
Version 3.0
924
- Remove strlen() call from pglarge_write() and get size from object.
1025
(Richard@Bouska.cz)

src/interfaces/python/README

+9-1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ version of PyGreSQL works with PostgreSQL 6.5 and Python 1.5.2.
8989
that uses RPMs, then you can pick up an RPM at
9090
ftp://ftp.druid.net/pub/distrib/pygresql.i386.rpm
9191

92+
* Note that if you are using the DB-API module you must also install
93+
mxDateTime from http://starship.python.net/~lemburg/mxDateTime.html.
94+
9295
* Also, check out setup.py for an alternate method of installing the package.
9396

9497
You have two options. You can compile PyGreSQL as a stand-alone module
@@ -114,7 +117,7 @@ GENERAL
114117
STAND-ALONE
115118

116119
* In the directory containing pgmodule.c, run the following command
117-
cc -fpic -shared -o _pg.so -I[pyInc] -I[pgInc] -L[pgLib] -lpq # -lcrypt # needed on some systems
120+
cc -fpic -shared -o _pg.so -I[pyInc] -I[pgInc] -L[pgLib] -lpq pgmodule.c
118121
where:
119122
[pyInc] = path of the Python include (usually Python.h)
120123
[pgInc] = path of the PostgreSQL include (usually postgres.h)
@@ -126,6 +129,9 @@ STAND-ALONE
126129
-DNO_SNPRINTF - if running a system with no snprintf call
127130
-DNO_PQSOCKET - if running an older PostgreSQL
128131

132+
On some systems you may need to include -lcrypt in the list of libraries
133+
to make it compile.
134+
129135
Define NO_PQSOCKET if you are using a version of PostgreSQL before 6.4
130136
that does not have the PQsocket function. The other options will be
131137
described in the next sections.
@@ -1050,6 +1056,8 @@ The C module needs to be cleaned up and redundant code merged.
10501056

10511057
The DB-API module needs to be documented.
10521058

1059+
The fetch method should use real cursers.
1060+
10531061

10541062
6. Future directions
10551063
====================

src/interfaces/python/README.linux

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Thanks to thilo@eevolute.com for this README and the RPM
1+
Thanks to thilo@eevolute.com and others for this README and the RPM
22

33
Note: The precompiled RPM package is not available at www.eevolute.com.
44
You may use the spec file provided with PyGreSQL to build your
@@ -36,3 +36,11 @@ bash# cp _pg.so /usr/lib/python1.5/lib-dynload
3636

3737
done!
3838

39+
Oliver White (ojw@muzak.iinet.net.au) sent me the following information
40+
about installing on Debian.
41+
42+
Hi, I thought you might want to upgrade your documentation for PyGreSQL
43+
to let people know they can get it by simply typing 'apt-get install
44+
python-pygresql', on debian (duh). This would have saved me a lot of
45+
trouble.
46+

src/interfaces/python/pg.py

+41-29
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,30 @@ def _quote(d, t):
1313
if d == None:
1414
return "NULL"
1515

16-
if t in ['int', 'decimal', 'seq']:
17-
if d == "": return 0
16+
if t in ['int', 'seq']:
17+
if d == "": return "NULL"
1818
return "%d" % int(d)
1919

20+
if t == 'decimal':
21+
if d == "": return "NULL"
22+
return "%f" % float(d)
23+
2024
if t == 'money':
21-
if d == "": return '0.00'
25+
if d == "": return "NULL"
2226
return "'%.2f'" % float(d)
2327

2428
if t == 'bool':
25-
if string.upper(d) in ['T', 'TRUE', 'Y', 'YES', 1, '1', 'ON']:
29+
# Can't run upper() on these
30+
if d in (0, 1): return ('f', 't')[d]
31+
32+
if string.upper(d) in ['T', 'TRUE', 'Y', 'YES', '1', 'ON']:
2633
return "'t'"
2734
else:
2835
return "'f'"
2936

30-
if d == "": return "null"
37+
if t == 'date' and d == '': return "NULL"
38+
if t in ('inet', 'cidr') and d == '': return "NULL"
39+
3140
return "'%s'" % string.strip(re.sub("'", "''", \
3241
re.sub("\\\\", "\\\\\\\\", "%s" %d)))
3342

@@ -68,7 +77,11 @@ def query(self, qstr):
6877
print self.debug % qstr
6978
return self.db.query(qstr)
7079

71-
def pkey(self, cl):
80+
# If third arg supplied set primary key to it
81+
def pkey(self, cl, newpkey = None):
82+
if newpkey:
83+
self.__pkeys__[cl] = newpkey
84+
7285
# will raise an exception if primary key doesn't exist
7386
return self.__pkeys__[cl]
7487

@@ -115,6 +128,8 @@ def get_attnames(self, cl):
115128
l[attname] = 'date'
116129
elif re.match("^date", typname):
117130
l[attname] = 'date'
131+
elif re.match("^timestamp", typname):
132+
l[attname] = 'date'
118133
elif re.match("^bool", typname):
119134
l[attname] = 'bool'
120135
elif re.match("^float", typname):
@@ -129,15 +144,20 @@ def get_attnames(self, cl):
129144

130145
# return a tuple from a database
131146
def get(self, cl, arg, keyname = None, view = 0):
147+
if cl[-1] == '*': # need parent table name
148+
xcl = cl[:-1]
149+
else:
150+
xcl = cl
151+
132152
if keyname == None: # use the primary key by default
133-
keyname = self.__pkeys__[cl]
153+
keyname = self.__pkeys__[xcl]
134154

135-
fnames = self.get_attnames(cl)
155+
fnames = self.get_attnames(xcl)
136156

137157
if type(arg) == type({}):
138158
# To allow users to work with multiple tables we munge the
139159
# name when the key is "oid"
140-
if keyname == 'oid': k = arg['oid_%s' % cl]
160+
if keyname == 'oid': k = arg['oid_%s' % xcl]
141161
else: k = arg[keyname]
142162
else:
143163
k = arg
@@ -151,7 +171,7 @@ def get(self, cl, arg, keyname = None, view = 0):
151171
(cl, keyname, _quote(k, fnames[keyname]))
152172
else:
153173
q = "SELECT oid AS oid_%s, %s FROM %s WHERE %s = %s" % \
154-
(cl, string.join(fnames.keys(), ','),\
174+
(xcl, string.join(fnames.keys(), ','),\
155175
cl, keyname, _quote(k, fnames[keyname]))
156176

157177
if self.debug != None: print self.debug % q
@@ -175,8 +195,7 @@ def insert(self, cl, a):
175195
n = []
176196
for f in fnames.keys():
177197
if a.has_key(f):
178-
if a[f] == "": l.append("null")
179-
else: l.append(_quote(a[f], fnames[f]))
198+
l.append(_quote(a[f], fnames[f]))
180199
n.append(f)
181200

182201
try:
@@ -197,44 +216,37 @@ def insert(self, cl, a):
197216
# otherwise use the primary key. Fail if neither.
198217
def update(self, cl, a):
199218
foid = 'oid_%s' % cl
200-
pk = self.__pkeys__[cl]
201219
if a.has_key(foid):
202220
where = "oid = %s" % a[foid]
203-
elif a.has_key(pk):
204-
where = "%s = '%s'" % (pk, a[pk])
221+
elif self.__pkeys__.has_key(cl) and a.has_key(self.__pkeys__[cl]):
222+
where = "%s = '%s'" % (self.__pkeys__[cl], a[self.__pkeys__[cl]])
205223
else:
206-
raise error, "Update needs key (%s) or oid as %s" % (pk, foid)
207-
208-
q = "SELECT oid FROM %s WHERE %s" % (cl, where)
209-
if self.debug != None: print self.debug % q
210-
res = self.db.query(q).getresult()
211-
212-
if len(res) < 1:
213-
raise error, "No record in %s where %s (%s)" % \
214-
(cl, where, sys.exc_value)
215-
else: a[foid] = res[0][0]
224+
raise error, "Update needs primary key or oid as %s" % foid
216225

217226
v = []
218227
k = 0
219228
fnames = self.get_attnames(cl)
220229

221230
for ff in fnames.keys():
222-
if a.has_key(ff) and a[ff] != res[0][k]:
231+
if a.has_key(ff):
223232
v.append("%s = %s" % (ff, _quote(a[ff], fnames[ff])))
224233

225234
if v == []:
226235
return None
227236

228237
try:
229-
q = "UPDATE %s SET %s WHERE oid = %s" % \
230-
(cl, string.join(v, ','), a[foid])
238+
q = "UPDATE %s SET %s WHERE %s" % \
239+
(cl, string.join(v, ','), where)
231240
if self.debug != None: print self.debug % q
232241
self.db.query(q)
233242
except:
234243
raise error, "Can't update %s: %s" % (cl, sys.exc_value)
235244

236245
# reload the dictionary to catch things modified by engine
237-
return self.get(cl, a, 'oid')
246+
if a.has_key(foid):
247+
return self.get(cl, a, 'oid')
248+
else:
249+
return self.get(cl, a)
238250

239251
# At some point we will need a way to get defaults from a table
240252
def clear(self, cl, a = {}):

src/interfaces/python/pgdb.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ def typecast(self, typ, value):
120120
pass
121121
elif typ == BINARY:
122122
pass
123+
elif typ == BOOL:
124+
value = (value[:1] in ['t','T'])
123125
elif typ == INTEGER:
124126
value = int(value)
125127
elif typ == LONG:
@@ -322,7 +324,7 @@ def connect(dsn = None, user = None, password = None, host = None, database = No
322324
try:
323325
params = string.split(host, ":")
324326
dbhost = params[0]
325-
dbport = params[1]
327+
dbport = int(params[1])
326328
except:
327329
pass
328330

src/interfaces/python/pgmodule.c

+3-4
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
#define CASHOID 790
4545

4646
static PyObject *PGError;
47-
static const char *PyPgVersion = "3.0";
47+
static const char *PyPgVersion = "3.1";
4848

4949
/* taken from fileobject.c */
5050
#define BUF(v) PyString_AS_STRING((PyStringObject *)(v))
@@ -1502,7 +1502,7 @@ pgconnect(pgobject *self, PyObject *args, PyObject *dict)
15021502

15031503
if (pgport != -1)
15041504
{
1505-
bzero(port_buffer, sizeof(port_buffer));
1505+
memset(port_buffer, 0, sizeof(port_buffer));
15061506
sprintf(port_buffer, "%d", pgport);
15071507
npgobj->cnx = PQsetdbLogin(pghost, port_buffer, pgopt, pgtty, pgdbname,
15081508
pguser, pgpasswd);
@@ -2976,8 +2976,7 @@ pgsetdefpasswd(PyObject * self, PyObject *args)
29762976
if (!PyArg_ParseTuple(args, "z", &temp))
29772977
{
29782978
PyErr_SetString(PyExc_TypeError,
2979-
"set_defpasswd(password), with password (string/
2980-
None).");
2979+
"set_defpasswd(password), with password (string/None).");
29812980
return NULL;
29822981
}
29832982

src/interfaces/python/setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from distutils.core import setup
2525

2626
setup (name = "PyGreSQL",
27-
version = "3.0",
27+
version = "3.1",
2828
description = "Python PostgreSQL Interfaces",
2929
author = "D'Arcy J. M. Cain",
3030
author_email = "darcy@druid.net",

src/interfaces/python/tutorial/basics.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
This module is designed for being imported from python prompt
1111
1212
In order to run the samples included here, first create a connection
13-
using : cnx = advanced.DB(...)
13+
using : cnx = basics.DB(...)
1414
1515
The "..." should be replaced with whatever arguments you need to open an
1616
existing database. Usually all you need is the name of the database and,

0 commit comments

Comments
 (0)