From f88e77d033a79fd0188d5dbb7a3a30cc94c0d108 Mon Sep 17 00:00:00 2001 From: adustman Date: Tue, 20 Jul 1999 04:04:20 +0000 Subject: [PATCH] Minor tweaks. ZMySQLDA.patch makes Zope's ZMySQLDA compatible with MySQLdb (maybe). --- mysql/MySQL_doc.py | 27 ++++++++++++---- mysql/MySQLdb.py | 6 ++-- mysql/ZMySQLDA.patch | 77 ++++++++++++++++++++++++++++++++++++++++++++ mysql/_mysqlmodule.c | 1 + 4 files changed, 102 insertions(+), 9 deletions(-) create mode 100644 mysql/ZMySQLDA.patch diff --git a/mysql/MySQL_doc.py b/mysql/MySQL_doc.py index 128939b..360b61f 100644 --- a/mysql/MySQL_doc.py +++ b/mysql/MySQL_doc.py @@ -78,6 +78,12 @@ def main(): P("This module requires Python 1.5.2. Earlier versions will not\n"\ "work, because support for C long longs is required by MySQL.\n" \ "Thanks to Nikolas Kauer for pointing this out."), + P("This version has been tested against MySQL-3.23.25, which seems\n" \ + "to have a strange bug when handling TIME columns. For this\n" \ + "reason, there is presently no type converter for TIME columns\n" \ + "(the value is returned as a string)."), + P("The type converter dictionary is no longer stored within the\n", \ + TT("_mysql"), " module. See below for more details."), P("If you work out\n" \ "an installation routine for Windows, please contact the author."), P("This module works better if you have the ", @@ -218,7 +224,9 @@ def main(): BDT("passwd"), DD("password to authenticate with"), BDT("db"), - DD("database to use")))), + DD("database to use"), + BDT("conv"), + DD("type conversion dictionary")))), BDT("apilevel"), DD(P("String constant stating the supported DB API level. '2.0'")), BDT("threadsafety"), @@ -256,16 +264,21 @@ def main(): DD(P("A dictionary mapping MySQL types (from ", TT("FIELD_TYPE.*"), ") to callable Python objects\n" \ "(usually functions) which convert from a string to\n" \ - "the desired type. This is imported from the\n", - TT("_mysql"), " module, where it is initialized with\n" \ - "reasonable defaults for most types. ", TT("MySQLdb"), - "\nalso adds a few additional functions, using some of\n" \ + "the desired type. This is initialized with\n" \ + "reasonable defaults for most types. When creating a\n" \ + "Connection object, you can pass your own type converter\n" \ + "dictionary as a keyword parameter. Otherwise, it uses a\n" \ + "copy of ", TT("type_conv"), " which is safe\n" \ + "to modify on a per-connection basis. The dictionary\n"\ + "includes some of\n" \ "the factory functions from the\n", A("DateTime", href="http://starship.skyport.net/~lemburg/mxDateTime.html"), - " module. Several non-standard types (SET, ENUM) are\n" \ + " module, if it is available.\n" \ + "Several non-standard types (SET, ENUM) are\n" \ "returned as strings, which is how MySQL returns all\n" - "columns."))), + "columns. Note: ", TT("TIME"), " columns are returned as\n" \ + "strings presently. This should be a temporary condition."))), H3("Connection Objects"), DL(BDT("commit()"), DD(P("MySQL does not support transactions, so this method\n" \ diff --git a/mysql/MySQLdb.py b/mysql/MySQLdb.py index f7a7b06..9731528 100644 --- a/mysql/MySQLdb.py +++ b/mysql/MySQLdb.py @@ -56,7 +56,7 @@ try: type_conv[FIELD_TYPE.TIMESTAMP] = mysql_timestamp_converter type_conv[FIELD_TYPE.DATETIME] = ISO.ParseDateTime - type_conv[FIELD_TYPE.TIME] = ISO.ParseTime + #type_conv[FIELD_TYPE.TIME] = ISO.ParseTime type_conv[FIELD_TYPE.DATE] = ISO.ParseDate except ImportError: @@ -234,6 +234,8 @@ class Connection: port -- integer, TCP/IP port to connect to or default MySQL port unix_socket -- string, location of unix_socket to use or use TCP client_flags -- integer, flags to use or 0 (see MySQL docs) + conv -- dictionary, maps MySQL FIELD_TYPE.* to Python functions which + convert a string to the appropriate Python type Returns a Connection object. @@ -251,7 +253,7 @@ class Connection: def __init__(self, **kwargs): from _mysql import connect - if not kwargs.has_key('conv'): kwargs['conv'] = type_conv + if not kwargs.has_key('conv'): kwargs['conv'] = type_conv.copy() self.db = apply(connect, (), kwargs) def close(self): diff --git a/mysql/ZMySQLDA.patch b/mysql/ZMySQLDA.patch new file mode 100644 index 0000000..f3c4dee --- /dev/null +++ b/mysql/ZMySQLDA.patch @@ -0,0 +1,77 @@ +I gave ZMySQLDA a quick once-over and I THINK this will convert it from +using MySQLmodule-1.4 to _mysql. Why _mysql and not MySQLdb? Well, look +at the patch. :) It's basically puny. ZMySQLDA abstracts away the Python +DB API interface anyway, so why wrap another wrapper? Plus, by default +MySQLdb attempts to do type conversions, which Zope doesn't seem to expect. +I made some changes, partially to help Zopistas, to both _mysql and MySQLdb. +The main one is removing type_conv as part of _mysql. It now needs to be +passed to _mysql.connect() as the conv keyword argument; if it is not present, +it uses an empty dictionary (return everything as strings), which is the +Zope-desired behavior. MySQLdb now owns type_conv, and passes as copy if +you don't supply your own converter. + +Special note: Not only is the MySQLdb package provided WITH NO WARRANTY, +this patch is DOUBLE-SECRET NO WARRRANTY. It may not work at all; I have +not tested it PERIOD. I am using Zope-2.0.0a4, but I don't really have the +time to whip up something to test with. The Digicool guys can figure out +whether or not it works. If it makes your testicles fall off (or you grow +some when you shouldn't have any), I am not responsible. + +Oh yeah, to apply the patch, you probably want to use: + + patch -p1 +1999-07-19 + +diff -ur ZMySQLDA.orig/lib/python/Products/ZMySQLDA/db.py ZMySQLDA/lib/python/Products/ZMySQLDA/db.py +--- ZMySQLDA.orig/lib/python/Products/ZMySQLDA/db.py Mon Jan 25 10:42:45 1999 ++++ ZMySQLDA/lib/python/Products/ZMySQLDA/db.py Mon Jul 19 23:19:12 1999 +@@ -103,7 +103,7 @@ + """Db connection implementation""" + __version__='$Revision$'[11:-2] + +-import MySQL, regex, sys ++import _mysql, regex, sys + from string import strip, split, find, join + from time import gmtime, strftime + +@@ -124,7 +124,7 @@ + "timestamp": "d", "varchar": "t", "string": "t", + } + +- Database_Error=MySQL.error ++ Database_Error=_mysql.error + + def __init__(self,connection): + self.connection=connection +@@ -138,8 +138,7 @@ + if len(dbhost) == 1: db, host = dbhost[0], 'localhost' + else: [db, host] = dbhost + +- c=MySQL.connect(host,user,pw) +- c.selectdb(db) ++ c=_mysql.connect(host=host,user=user,passwd=pw,db=db) + self.db=c + return + +@@ -170,8 +169,8 @@ + for qs in queries: + c=db.query(qs) + try: +- desc=c.fields() +- r=c.fetchrows() ++ desc=c.describe() ++ r=c.fetch_all_rows() + except: r=None + if not r: continue + if result: +@@ -182,7 +181,7 @@ + except self.Database_Error, mess: + raise sys.exc_type, sys.exc_value, sys.exc_traceback + +- if desc is None: return (), () ++ if not desc: return (), () + + items=[] + func=items.append diff --git a/mysql/_mysqlmodule.c b/mysql/_mysqlmodule.c index 7f8d809..13ba4a7 100644 --- a/mysql/_mysqlmodule.c +++ b/mysql/_mysqlmodule.c @@ -363,6 +363,7 @@ _mysql_ResultObject_New(conn, result, use, conv) fun = PyObject_GetItem(conv, tmp); Py_XDECREF(tmp); if (!fun) { + PyErr_Clear(); fun = Py_None; Py_INCREF(Py_None); }