annotate DBInterface.py @ 19:132ae1c0255a

V1.7: new connection caching. some cleanup.
author casties
date Fri, 11 Jan 2013 17:58:56 +0100
parents 60fea3a6c695
children 5f3d6623b71e
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
4
0ade331198de first version of ZDBInlineSearch
casties
parents: 3
diff changeset
18 def sqlName(s, lc=True, more=''):
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
19 """returns restricted ASCII-only version of string"""
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
20 if s is None:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
21 return ""
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
22
11
22c16a632909 add single-quote to ignored characters in sqlName.
casties
parents: 8
diff changeset
23 # remove '
22c16a632909 add single-quote to ignored characters in sqlName.
casties
parents: 8
diff changeset
24 s = s.replace("'","")
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
25 # all else -> "_"
4
0ade331198de first version of ZDBInlineSearch
casties
parents: 3
diff changeset
26 s = re.sub('[^A-Za-z0-9_'+more+']','_',s)
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
27 if lc:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
28 return s.lower()
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
29
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
30 return s
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
31
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
32
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
33 class DBInterface:
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
34 """Object for database queries"""
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
35
8
17b19345d011 added autocommit option.
casties
parents: 6
diff changeset
36 def __init__(self, connection_id=None, autocommit=False):
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
37 """init"""
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
38 # database connection id
8
17b19345d011 added autocommit option.
casties
parents: 6
diff changeset
39 self.connection_id = connection_id
17b19345d011 added autocommit option.
casties
parents: 6
diff changeset
40 self.autocommit = autocommit
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
41
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
42 def getConnectionIDs(self):
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
43 """return list of available connection ids"""
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
44 return SQLConnectionIDs(self)
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
45
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
46 def getDB(self):
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
47 """returns DB object"""
19
132ae1c0255a V1.7: new connection caching. some cleanup.
casties
parents: 18
diff changeset
48 db = None
132ae1c0255a V1.7: new connection caching. some cleanup.
casties
parents: 18
diff changeset
49
132ae1c0255a V1.7: new connection caching. some cleanup.
casties
parents: 18
diff changeset
50 # connection caching according to http://pypi.python.org/pypi/alm.solrindex
132ae1c0255a V1.7: new connection caching. some cleanup.
casties
parents: 18
diff changeset
51 jar = self._p_jar
132ae1c0255a V1.7: new connection caching. some cleanup.
casties
parents: 18
diff changeset
52 oid = self._p_oid
132ae1c0255a V1.7: new connection caching. some cleanup.
casties
parents: 18
diff changeset
53 fc = None
132ae1c0255a V1.7: new connection caching. some cleanup.
casties
parents: 18
diff changeset
54 if jar is not None and oid is not None:
132ae1c0255a V1.7: new connection caching. some cleanup.
casties
parents: 18
diff changeset
55 fc = getattr(jar, 'foreign_connections', None)
132ae1c0255a V1.7: new connection caching. some cleanup.
casties
parents: 18
diff changeset
56 if fc is None:
132ae1c0255a V1.7: new connection caching. some cleanup.
casties
parents: 18
diff changeset
57 jar.foreign_connections = fc = {}
132ae1c0255a V1.7: new connection caching. some cleanup.
casties
parents: 18
diff changeset
58
132ae1c0255a V1.7: new connection caching. some cleanup.
casties
parents: 18
diff changeset
59 db = fc.get(oid, None)
132ae1c0255a V1.7: new connection caching. some cleanup.
casties
parents: 18
diff changeset
60 if db is not None:
132ae1c0255a V1.7: new connection caching. some cleanup.
casties
parents: 18
diff changeset
61 logging.debug("getDb: using cached db=%s"%repr(db))
132ae1c0255a V1.7: new connection caching. some cleanup.
casties
parents: 18
diff changeset
62 return db
132ae1c0255a V1.7: new connection caching. some cleanup.
casties
parents: 18
diff changeset
63
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
64 if self.connection_id is None:
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
65 # try to take the first existing ID
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
66 connids = self.getConnectionIDs()
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
67 if len(connids) > 0:
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
68 connection_id = connids[0][1]
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
69 self.connection_id = connection_id
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
70 logging.debug("connection_id: %s"%repr(connection_id))
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
71
19
132ae1c0255a V1.7: new connection caching. some cleanup.
casties
parents: 18
diff changeset
72 # get Connection/DA instance
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
73 con = getattr(self, self.connection_id)
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
74 # call to get db object
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
75 db = con()
8
17b19345d011 added autocommit option.
casties
parents: 6
diff changeset
76 if self.autocommit:
17b19345d011 added autocommit option.
casties
parents: 6
diff changeset
77 # force our transaction isolation level
17b19345d011 added autocommit option.
casties
parents: 6
diff changeset
78 db.tilevel = psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT
17b19345d011 added autocommit option.
casties
parents: 6
diff changeset
79
19
132ae1c0255a V1.7: new connection caching. some cleanup.
casties
parents: 18
diff changeset
80 if fc is not None and oid is not None:
132ae1c0255a V1.7: new connection caching. some cleanup.
casties
parents: 18
diff changeset
81 # cache db
132ae1c0255a V1.7: new connection caching. some cleanup.
casties
parents: 18
diff changeset
82 fc[oid] = db
132ae1c0255a V1.7: new connection caching. some cleanup.
casties
parents: 18
diff changeset
83
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
84 return db
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
85
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
86 def executeZSQL(self, query, args=None, max_rows=None):
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
87 """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
88 logging.debug("executeZSQL query=%s args=%s"%(query,args))
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
89 dbc = self.getDB()
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
90 res = dbc.query(query, max_rows=max_rows, query_data=args)
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
91 # return result set as Result object with Brains
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
92 return Results(res)
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
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
95 #
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
96 # Old way using cursor from DA
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
97 #
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
98
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
99 def getCursor(self,autocommit=True):
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
100 """returns fresh DB cursor"""
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
101 conn = getattr(self,"_v_database_connection", None)
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
102 if conn is None:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
103 # create a new connection object
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
104 try:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
105 if self.connection_id is None:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
106 # try to take the first existing ID
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
107 connids = self.getConnectionIDs()
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
108 if len(connids) > 0:
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
109 connection_id = connids[0][1]
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
110 self.connection_id = connection_id
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
111 logging.debug("connection_id: %s"%repr(connection_id))
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
112
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
113 da = getattr(self, self.connection_id)
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
114 logging.debug('da=%s'%da)
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
115 da.connect('')
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
116 # we copy the DAs database connection
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
117 conn = da._v_database_connection
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
118 #conn._register() # register with the Zope transaction system(?)
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
119 self._v_database_connection = conn
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
120
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
121 except Exception, e:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
122 raise IOError("No database connection! (%s)"%str(e))
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
123
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
124 cursor = conn.getcursor()
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
125 if autocommit:
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
126 # TODO: is there a better version to get to the connection?
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
127 cursor.connection.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
128
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
129 return cursor
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
130
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
131 def getFieldNameMap(self,fields):
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
132 """returns a dict mapping field names to row indexes"""
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
133 map = {}
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
134 i = 0
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
135 for f in fields:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
136 map[f[0]] = i
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
137 i += 1
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
138
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
139 return map
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
140
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
141 def executeSQL(self, query, args=None, hasResult=True, autocommit=True):
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
142 """execute query with args on database and return all results.
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
143 result format: {"fields":fields, "rows":data}"""
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
144 logging.debug("executeSQL query=%s args=%s"%(query,args))
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
145 cur = self.getCursor(autocommit=autocommit)
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
146 if args is not None:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
147 # make sure args is a list
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
148 if isinstance(args,basestring):
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
149 args = (args,)
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
150
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
151 cur.execute(query, args)
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
152 # description of returned fields
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
153 fields = cur.description
18
60fea3a6c695 better fix for psycopg 2.4. better quoting of sql arguments.
casties
parents: 16
diff changeset
154 #logging.debug("fields: %s"%repr(fields))
16
5b99c04c567c fix for psycopg 2.4 Column type.
casties
parents: 11
diff changeset
155 if len(fields) > 0:
5b99c04c567c fix for psycopg 2.4 Column type.
casties
parents: 11
diff changeset
156 # re-pack Column object in tuple
18
60fea3a6c695 better fix for psycopg 2.4. better quoting of sql arguments.
casties
parents: 16
diff changeset
157 fs = []
60fea3a6c695 better fix for psycopg 2.4. better quoting of sql arguments.
casties
parents: 16
diff changeset
158 for f in fields:
60fea3a6c695 better fix for psycopg 2.4. better quoting of sql arguments.
casties
parents: 16
diff changeset
159 fs.append(f[0:])
60fea3a6c695 better fix for psycopg 2.4. better quoting of sql arguments.
casties
parents: 16
diff changeset
160
60fea3a6c695 better fix for psycopg 2.4. better quoting of sql arguments.
casties
parents: 16
diff changeset
161 fields = fs
60fea3a6c695 better fix for psycopg 2.4. better quoting of sql arguments.
casties
parents: 16
diff changeset
162 #logging.debug("re-packed fields: %s"%repr(fields))
16
5b99c04c567c fix for psycopg 2.4 Column type.
casties
parents: 11
diff changeset
163
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
164 if hasResult:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
165 # get all data in an array
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
166 data = cur.fetchall()
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
167 cur.close()
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
168 #logging.debug("fields: %s"%repr(fields))
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
169 #logging.debug("rows: %s"%repr(data))
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
170 return {"fields":fields, "rows":data}
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
171 else:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
172 cur.close()
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
173 return None
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
174