annotate DBInterface.py @ 8:17b19345d011

added autocommit option.
author casties
date Thu, 17 Feb 2011 19:25:16 +0100
parents 1b25a85a2165
children 22c16a632909
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
1 '''
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
2 Created on 14.2.2011
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
3
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
4 @author: casties
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
5 '''
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
6
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
7 import logging
6
1b25a85a2165 fixed bug and improved sqlName
root@xserve09.mpiwg-berlin.mpg.de
parents: 4
diff changeset
8 import re
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
9 import psycopg2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
10 # make psycopg use unicode objects
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
11 import psycopg2.extensions
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
12 psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
13 psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY)
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
14
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
15 from Products.ZSQLMethods.SQL import SQLConnectionIDs
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
16 from Shared.DC.ZRDB.Results import Results
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
17
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
18
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
19 def unicodify(s,alternate='latin-1'):
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
20 """decode str (utf-8 or latin-1 representation) into unicode object"""
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
21 if not s:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
22 return u""
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
23 if isinstance(s, str):
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
24 try:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
25 return s.decode('utf-8')
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
26 except:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
27 return s.decode(alternate)
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
28 else:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
29 return s
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
30
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
31 def utf8ify(s):
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
32 """encode unicode object or string into byte string in utf-8 representation.
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
33 assumes string objects to be utf-8"""
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
34 if not s:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
35 return ""
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
36 if isinstance(s, str):
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
37 return s
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
38 else:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
39 return s.encode('utf-8')
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
40
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
41 def getTextFromNode(node):
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
42 """get the cdata content of a XML node"""
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
43 if node is None:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
44 return ""
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
45
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
46 if isinstance(node, list):
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
47 nodelist = node
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
48 else:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
49 nodelist=node.childNodes
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
50
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
51 rc = ""
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
52 for node in nodelist:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
53 if node.nodeType == node.TEXT_NODE:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
54 rc = rc + node.data
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
55 return rc
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
56
4
0ade331198de first version of ZDBInlineSearch
casties
parents: 3
diff changeset
57 def sqlName(s, lc=True, more=''):
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
58 """returns restricted ASCII-only version of string"""
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
59 if s is None:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
60 return ""
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
61
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
62 # all else -> "_"
4
0ade331198de first version of ZDBInlineSearch
casties
parents: 3
diff changeset
63 s = re.sub('[^A-Za-z0-9_'+more+']','_',s)
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
64 if lc:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
65 return s.lower()
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
66
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
67 return s
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
68
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
69
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
70 class DBInterface:
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
71 """Object for database queries"""
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
72
8
17b19345d011 added autocommit option.
casties
parents: 6
diff changeset
73 def __init__(self, connection_id=None, autocommit=False):
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
74 """init"""
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
75 # database connection id
8
17b19345d011 added autocommit option.
casties
parents: 6
diff changeset
76 self.connection_id = connection_id
17b19345d011 added autocommit option.
casties
parents: 6
diff changeset
77 self.autocommit = autocommit
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
78
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
79 def getConnectionIDs(self):
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
80 """return list of available connection ids"""
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
81 return SQLConnectionIDs(self)
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
82
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
83 def getDB(self):
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
84 """returns DB object"""
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
85 # TODO: can we cache and reuse a DB object?
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
86 if self.connection_id is None:
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
87 # try to take the first existing ID
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
88 connids = self.getConnectionIDs()
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
89 if len(connids) > 0:
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
90 connection_id = connids[0][1]
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
91 self.connection_id = connection_id
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
92 logging.debug("connection_id: %s"%repr(connection_id))
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
93
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
94 # get Connection instance
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
95 con = getattr(self, self.connection_id)
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
96 # call to get db object
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
97 db = con()
8
17b19345d011 added autocommit option.
casties
parents: 6
diff changeset
98 if self.autocommit:
17b19345d011 added autocommit option.
casties
parents: 6
diff changeset
99 # force our transaction isolation level
17b19345d011 added autocommit option.
casties
parents: 6
diff changeset
100 db.tilevel = psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT
17b19345d011 added autocommit option.
casties
parents: 6
diff changeset
101
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
102 return db
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
103
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
104 def executeZSQL(self, query, args=None, max_rows=None):
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
105 """execute query with args on the database and return all results as Result object."""
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
106 logging.debug("executeZSQL query=%s args=%s"%(query,args))
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
107 dbc = self.getDB()
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
108 res = dbc.query(query, max_rows=max_rows, query_data=args)
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
109 # return result set as Result object with Brains
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
110 return Results(res)
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
111
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
112
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
113 #
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
114 # Old way using cursor from DA
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
115 #
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
116
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
117 def getCursor(self,autocommit=True):
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
118 """returns fresh DB cursor"""
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
119 conn = getattr(self,"_v_database_connection", None)
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
120 if conn is None:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
121 # create a new connection object
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
122 try:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
123 if self.connection_id is None:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
124 # try to take the first existing ID
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
125 connids = self.getConnectionIDs()
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
126 if len(connids) > 0:
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
127 connection_id = connids[0][1]
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
128 self.connection_id = connection_id
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
129 logging.debug("connection_id: %s"%repr(connection_id))
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
130
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
131 da = getattr(self, self.connection_id)
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
132 logging.debug('da=%s'%da)
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
133 da.connect('')
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
134 # we copy the DAs database connection
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
135 conn = da._v_database_connection
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
136 #conn._register() # register with the Zope transaction system(?)
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
137 self._v_database_connection = conn
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
138
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
139 except Exception, e:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
140 raise IOError("No database connection! (%s)"%str(e))
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
141
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
142 cursor = conn.getcursor()
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
143 if autocommit:
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
144 # TODO: is there a better version to get to the connection?
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
145 cursor.connection.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
146
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
147 return cursor
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
148
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
149 def getFieldNameMap(self,fields):
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
150 """returns a dict mapping field names to row indexes"""
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
151 map = {}
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
152 i = 0
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
153 for f in fields:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
154 map[f[0]] = i
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
155 i += 1
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
156
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
157 return map
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
158
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
159 def executeSQL(self, query, args=None, hasResult=True, autocommit=True):
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
160 """execute query with args on database and return all results.
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
161 result format: {"fields":fields, "rows":data}"""
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
162 logging.debug("executeSQL query=%s args=%s"%(query,args))
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
163 cur = self.getCursor(autocommit=autocommit)
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
164 if args is not None:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
165 # make sure args is a list
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
166 if isinstance(args,basestring):
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
167 args = (args,)
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
168
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
169 cur.execute(query, args)
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
170 # description of returned fields
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
171 fields = cur.description
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
172 if hasResult:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
173 # get all data in an array
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
174 data = cur.fetchall()
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
175 cur.close()
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
176 #logging.debug("fields: %s"%repr(fields))
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
177 #logging.debug("rows: %s"%repr(data))
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
178 return {"fields":fields, "rows":data}
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
179 else:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
180 cur.close()
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
181 return None
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
182