Commit 406b1c68 authored by Julien Muchembled's avatar Julien Muchembled

ZMySQLDA: code cleanup

parent 48600cf8
...@@ -91,15 +91,14 @@ __version__='$Revision: 1.4 $'[11:-2] ...@@ -91,15 +91,14 @@ __version__='$Revision: 1.4 $'[11:-2]
import os import os
from collections import defaultdict from collections import defaultdict
from weakref import WeakKeyDictionary from weakref import WeakKeyDictionary
from db import DB
import transaction import transaction
import Shared.DC.ZRDB import Shared.DC.ZRDB
import DABase
from App.Dialogs import MessageDialog from App.Dialogs import MessageDialog
from App.special_dtml import HTMLFile from App.special_dtml import HTMLFile
from App.ImageFile import ImageFile from App.ImageFile import ImageFile
from ExtensionClass import Base
from DateTime import DateTime from DateTime import DateTime
from . import DABase
from .db import DB
SHARED_DC_ZRDB_LOCATION = os.path.dirname(Shared.DC.ZRDB.__file__) SHARED_DC_ZRDB_LOCATION = os.path.dirname(Shared.DC.ZRDB.__file__)
...@@ -165,8 +164,6 @@ class Connection(DABase.Connection): ...@@ -165,8 +164,6 @@ class Connection(DABase.Connection):
return connection.string_literal(v) return connection.string_literal(v)
classes=('DA.Connection',)
meta_types=( meta_types=(
{'name':'Z %s Database Connection' % database_type, {'name':'Z %s Database Connection' % database_type,
'action':'manage_addZ%sConnectionForm' % database_type, 'action':'manage_addZ%sConnectionForm' % database_type,
......
from Queue import Queue, Full, Empty
class Pool(Queue):
"""Manage a fixed-size pool of reusable, identical objects."""
def __init__(self, constructor, poolsize=5):
Queue.__init__(self, poolsize)
self.constructor = constructor
def get(self, block=1):
"""Get an object from the pool or a new one if empty."""
try:
return self.empty() and self.constructor() or Queue.get(self, block)
except Empty:
return self.constructor()
def put(self, obj, block=1):
"""Put an object into the pool if it is not full. The caller must
not use the object after this."""
try:
return self.full() and None or Queue.put(self, obj, block)
except Full:
pass
class Constructor:
"""Returns a constructor that returns apply(function, args, kwargs)
when called."""
def __init__(self, function, *args, **kwargs):
self.f = function
self.args = args
self.kwargs = kwargs
def __call__(self):
return apply(self.f, self.args, self.kwargs)
...@@ -87,8 +87,7 @@ __doc__='''Generic Database Adapter Package Registration ...@@ -87,8 +87,7 @@ __doc__='''Generic Database Adapter Package Registration
$Id: __init__.py,v 1.4 2001/08/17 02:17:38 adustman Exp $''' $Id: __init__.py,v 1.4 2001/08/17 02:17:38 adustman Exp $'''
__version__='$Revision: 1.4 $'[11:-2] __version__='$Revision: 1.4 $'[11:-2]
import sys, string from . import DA
import DA
methods=DA.folder_methods methods=DA.folder_methods
misc_=DA.misc_ misc_=DA.misc_
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
<tr> <tr>
<th align="LEFT" valign="TOP">Connect immediately</th> <th align="LEFT" valign="TOP">Connect immediately</th>
<td align="LEFT" valign="TOP"> <td align="LEFT" valign="TOP">
<input name="check" type="CHECKBOX" value="YES" CHECKED> <input name="check:int" type="CHECKBOX" value="1" CHECKED>
</td> </td>
</tr> </tr>
<tr> <tr>
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
<tr> <tr>
<th align="LEFT" valign="TOP">Connect immediately</th> <th align="LEFT" valign="TOP">Connect immediately</th>
<td align="LEFT" valign="TOP"> <td align="LEFT" valign="TOP">
<input name="check" type="CHECKBOX" value="YES" CHECKED> <input name="check:int" type="CHECKBOX" value="1" CHECKED>
</td> </td>
</tr> </tr>
......
...@@ -105,7 +105,6 @@ from zLOG import LOG, ERROR ...@@ -105,7 +105,6 @@ from zLOG import LOG, ERROR
from ZODB.POSException import ConflictError from ZODB.POSException import ConflictError
import sys import sys
from string import strip, split, upper, rfind
hosed_connection = ( hosed_connection = (
CR.SERVER_GONE_ERROR, CR.SERVER_GONE_ERROR,
...@@ -150,19 +149,14 @@ type_xlate = { ...@@ -150,19 +149,14 @@ type_xlate = {
} }
def _mysql_timestamp_converter(s): def _mysql_timestamp_converter(s):
if len(s) < 14: s = s.ljust(14, '0')
s = s + "0"*(14-len(s))
parts = map(int, (s[:4],s[4:6],s[6:8], parts = map(int, (s[:4],s[4:6],s[6:8],
s[8:10],s[10:12],s[12:14])) s[8:10],s[10:12],s[12:14]))
return DateTime("%04d-%02d-%02d %02d:%02d:%02d" % tuple(parts)) return DateTime("%04d-%02d-%02d %02d:%02d:%02d" % tuple(parts))
def DateTime_or_None(s): def DateTime_or_None(s):
try: return DateTime('%s UTC' % s) try: return DateTime('%s UTC' % s)
except: return None except Exception: return None
def int_or_long(s):
try: return int(s)
except: return long(s)
def ord_or_None(s): def ord_or_None(s):
if s is not None: if s is not None:
...@@ -171,7 +165,7 @@ def ord_or_None(s): ...@@ -171,7 +165,7 @@ def ord_or_None(s):
class DB(TM): class DB(TM):
conv=conversions.copy() conv=conversions.copy()
conv[FIELD_TYPE.LONG] = int_or_long conv[FIELD_TYPE.LONG] = int
conv[FIELD_TYPE.DATETIME] = DateTime_or_None conv[FIELD_TYPE.DATETIME] = DateTime_or_None
conv[FIELD_TYPE.DATE] = DateTime_or_None conv[FIELD_TYPE.DATE] = DateTime_or_None
conv[FIELD_TYPE.DECIMAL] = float conv[FIELD_TYPE.DECIMAL] = float
...@@ -187,7 +181,7 @@ class DB(TM): ...@@ -187,7 +181,7 @@ class DB(TM):
transactionality once instead of once per DB instance. transactionality once instead of once per DB instance.
""" """
self._connection = connection self._connection = connection
self._kw_args = self._parse_connection_string(connection) self._parse_connection_string()
self._forceReconnection() self._forceReconnection()
transactional = self.db.server_capabilities & CLIENT.TRANSACTIONS transactional = self.db.server_capabilities & CLIENT.TRANSACTIONS
if self._try_transactions == '-': if self._try_transactions == '-':
...@@ -197,50 +191,40 @@ class DB(TM): ...@@ -197,50 +191,40 @@ class DB(TM):
self._transactions = transactional self._transactions = transactional
self._use_TM = transactional or self._mysql_lock self._use_TM = transactional or self._mysql_lock
def _parse_connection_string(self, connection): def _parse_connection_string(self):
kwargs = {'conv': self.conv} self._mysql_lock = self._try_transactions = None
items = split(connection) self._kw_args = kwargs = {'conv': self.conv}
self._use_TM = None items = self._connection.split()
if not items: return kwargs if not items:
compress = items[0] return
if compress == "~": if items[0] == "~":
kwargs['compress'] = True kwargs['compress'] = True
items = items[1:] del items[0]
lockreq, items = items[0], items[1:] if items[0][0] == "*":
if lockreq[0] == "*": self._mysql_lock = items.pop(0)[1:]
self._mysql_lock = lockreq[1:] db = items.pop(0)
db_host, items = items[0], items[1:] if '@' in db:
self._use_TM = 1 db, host = db.split('@', 1)
else:
self._mysql_lock = None
db_host = lockreq
if '@' in db_host:
db, host = split(db_host,'@',1)
kwargs['db'] = db
if host.startswith('['): if host.startswith('['):
host, port = split(host[1:], ']', 1) host, port = host[1:].split(']', 1)
if port.startswith(':'): if port.startswith(':'):
kwargs['port'] = int(port[1:]) kwargs['port'] = int(port[1:])
elif ':' in host: elif ':' in host:
host, port = split(host,':',1) host, port = host.split(':', 1)
kwargs['port'] = int(port) kwargs['port'] = int(port)
kwargs['host'] = host kwargs['host'] = host
else: if db:
kwargs['db'] = db_host if db[0] in '+-':
if kwargs['db'] and kwargs['db'][0] in ('+', '-'): self._try_transactions = db[0]
self._try_transactions = kwargs['db'][0] db = db[1:]
kwargs['db'] = kwargs['db'][1:] if db:
else: kwargs['db'] = db
self._try_transactions = None if items:
if not kwargs['db']: kwargs['user'] = items.pop(0)
del kwargs['db'] if items:
if not items: return kwargs kwargs['passwd'] = items.pop(0)
kwargs['user'], items = items[0], items[1:] if items:
if not items: return kwargs kwargs['unix_socket'] = items.pop(0)
kwargs['passwd'], items = items[0], items[1:]
if not items: return kwargs
kwargs['unix_socket'], items = items[0], items[1:]
return kwargs
defs={ defs={
FIELD_TYPE.CHAR: "i", FIELD_TYPE.DATE: "d", FIELD_TYPE.CHAR: "i", FIELD_TYPE.DATE: "d",
...@@ -271,23 +255,23 @@ class DB(TM): ...@@ -271,23 +255,23 @@ class DB(TM):
return r return r
def columns(self, table_name): def columns(self, table_name):
from string import join
try: try:
c = self._query('SHOW COLUMNS FROM %s' % table_name) c = self._query('SHOW COLUMNS FROM %s' % table_name)
except: except Exception:
return () return ()
join = str.join
r=[] r=[]
for Field, Type, Null, Key, Default, Extra in c.fetch_row(0): for Field, Type, Null, Key, Default, Extra in c.fetch_row(0):
info = {} info = {}
field_default = Default and "DEFAULT %s"%Default or '' field_default = Default and "DEFAULT %s"%Default or ''
if Default: info['Default'] = Default if Default: info['Default'] = Default
if '(' in Type: if '(' in Type:
end = rfind(Type,')') end = Type.rfind(')')
short_type, size = split(Type[:end],'(',1) short_type, size = Type[:end].split('(', 1)
if short_type not in ('set','enum'): if short_type not in ('set','enum'):
if ',' in size: if ',' in size:
info['Scale'], info['Precision'] = \ info['Scale'], info['Precision'] = \
map(int, split(size,',',1)) map(int, size.split(',', 1))
else: else:
info['Scale'] = int(size) info['Scale'] = int(size)
else: else:
...@@ -302,7 +286,7 @@ class DB(TM): ...@@ -302,7 +286,7 @@ class DB(TM):
info['Description'] = join([Type, field_default, Extra or '', info['Description'] = join([Type, field_default, Extra or '',
key_types.get(Key, Key or ''), key_types.get(Key, Key or ''),
Null != 'YES' and 'NOT NULL' or '']), Null != 'YES' and 'NOT NULL' or '']),
info['Nullable'] = (Null == 'YES') and 1 or 0 info['Nullable'] = Null == 'YES'
if Key: if Key:
info['Index'] = 1 info['Index'] = 1
if Key == 'PRI': if Key == 'PRI':
...@@ -331,8 +315,7 @@ class DB(TM): ...@@ -331,8 +315,7 @@ class DB(TM):
raise OperationalError(m[0], '%s: %s' % (m[1], query)) raise OperationalError(m[0], '%s: %s' % (m[1], query))
if m[0] in lock_error: if m[0] in lock_error:
raise ConflictError('%s: %s: %s' % (m[0], m[1], query)) raise ConflictError('%s: %s: %s' % (m[0], m[1], query))
if ((not force_reconnect) and \ if not force_reconnect and self._use_TM or \
(self._mysql_lock or self._transactions)) or \
m[0] not in hosed_connection: m[0] not in hosed_connection:
LOG('ZMySQLDA', ERROR, 'query failed: %s' % (query,)) LOG('ZMySQLDA', ERROR, 'query failed: %s' % (query,))
raise raise
...@@ -370,39 +353,33 @@ class DB(TM): ...@@ -370,39 +353,33 @@ class DB(TM):
def query(self, query_string, max_rows=1000): def query(self, query_string, max_rows=1000):
self._use_TM and self._register() self._use_TM and self._register()
desc=None desc = None
result=()
# XXX deal with a typical mistake that the user appends # XXX deal with a typical mistake that the user appends
# an unnecessary and rather harmful semicolon at the end. # an unnecessary and rather harmful semicolon at the end.
# Unfortunately, MySQLdb does not want to be graceful. # Unfortunately, MySQLdb does not want to be graceful.
if query_string[-1:] == ';': if query_string[-1:] == ';':
query_string = query_string[:-1] query_string = query_string[:-1]
for qs in filter(None, map(strip,split(query_string, '\0'))): for qs in query_string.split('\0'):
qtype = upper(split(qs, None, 1)[0]) qs = qs.strip()
if qtype == "SELECT" and max_rows: if qs:
qs = "%s LIMIT %d" % (qs,max_rows) if qs[:6].upper() == "SELECT" and max_rows:
r=0 qs = "%s LIMIT %d" % (qs, max_rows)
c = self._query(qs) c = self._query(qs)
if c: if c:
if desc is not None is not c.describe(): if desc is not None is not c.describe():
raise 'Query Error', ( raise Exception(
'Multiple select schema are not allowed' 'Multiple select schema are not allowed'
) )
desc=c.describe() desc = c.describe()
result=c.fetch_row(max_rows) result = c.fetch_row(max_rows)
if desc is None:
if desc is None: return (),() return (), ()
get_def = self.defs.get
items=[] items = [{'name': d[0],
func=items.append 'type': get_def(d[1], "t"),
defs=self.defs
for d in desc:
item={'name': d[0],
'type': defs.get(d[1],"t"),
'width': d[2], 'width': d[2],
'null': d[6] 'null': d[6]
} } for d in desc]
func(item)
return items, result return items, result
def string_literal(self, s): def string_literal(self, s):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment