annotate DBInterface.py @ 11:22c16a632909

add single-quote to ignored characters in sqlName.
author casties
date Thu, 23 Jun 2011 11:16:19 +0200
parents 17b19345d011
children 5b99c04c567c
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
11
22c16a632909 add single-quote to ignored characters in sqlName.
casties
parents: 8
diff changeset
62 # remove '
22c16a632909 add single-quote to ignored characters in sqlName.
casties
parents: 8
diff changeset
63 s = s.replace("'","")
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
64 # all else -> "_"
4
0ade331198de first version of ZDBInlineSearch
casties
parents: 3
diff changeset
65 s = re.sub('[^A-Za-z0-9_'+more+']','_',s)
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
66 if lc:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
67 return s.lower()
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
68
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
69 return s
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
70
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
71
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
72 class DBInterface:
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
73 """Object for database queries"""
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
74
8
17b19345d011 added autocommit option.
casties
parents: 6
diff changeset
75 def __init__(self, connection_id=None, autocommit=False):
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
76 """init"""
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
77 # database connection id
8
17b19345d011 added autocommit option.
casties
parents: 6
diff changeset
78 self.connection_id = connection_id
17b19345d011 added autocommit option.
casties
parents: 6
diff changeset
79 self.autocommit = autocommit
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
80
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
81 def getConnectionIDs(self):
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
82 """return list of available connection ids"""
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
83 return SQLConnectionIDs(self)
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
84
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
85 def getDB(self):
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
86 """returns DB object"""
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
87 # TODO: can we cache and reuse a DB object?
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
88 if self.connection_id is None:
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
89 # try to take the first existing ID
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
90 connids = self.getConnectionIDs()
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
91 if len(connids) > 0:
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
92 connection_id = connids[0][1]
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
93 self.connection_id = connection_id
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
94 logging.debug("connection_id: %s"%repr(connection_id))
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 # get Connection instance
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
97 con = getattr(self, self.connection_id)
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
98 # call to get db object
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
99 db = con()
8
17b19345d011 added autocommit option.
casties
parents: 6
diff changeset
100 if self.autocommit:
17b19345d011 added autocommit option.
casties
parents: 6
diff changeset
101 # force our transaction isolation level
17b19345d011 added autocommit option.
casties
parents: 6
diff changeset
102 db.tilevel = psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT
17b19345d011 added autocommit option.
casties
parents: 6
diff changeset
103
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
104 return db
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
105
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
106 def executeZSQL(self, query, args=None, max_rows=None):
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
107 """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
108 logging.debug("executeZSQL query=%s args=%s"%(query,args))
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
109 dbc = self.getDB()
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
110 res = dbc.query(query, max_rows=max_rows, query_data=args)
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
111 # return result set as Result object with Brains
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
112 return Results(res)
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
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 # Old way using cursor from DA
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
117 #
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
118
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
119 def getCursor(self,autocommit=True):
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
120 """returns fresh DB cursor"""
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
121 conn = getattr(self,"_v_database_connection", None)
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
122 if conn is None:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
123 # create a new connection object
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
124 try:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
125 if self.connection_id is None:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
126 # try to take the first existing ID
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
127 connids = self.getConnectionIDs()
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
128 if len(connids) > 0:
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
129 connection_id = connids[0][1]
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
130 self.connection_id = connection_id
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
131 logging.debug("connection_id: %s"%repr(connection_id))
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
132
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
133 da = getattr(self, self.connection_id)
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
134 logging.debug('da=%s'%da)
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
135 da.connect('')
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
136 # we copy the DAs database connection
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
137 conn = da._v_database_connection
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
138 #conn._register() # register with the Zope transaction system(?)
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
139 self._v_database_connection = conn
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
140
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
141 except Exception, e:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
142 raise IOError("No database connection! (%s)"%str(e))
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
143
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
144 cursor = conn.getcursor()
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
145 if autocommit:
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
146 # TODO: is there a better version to get to the connection?
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
147 cursor.connection.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
148
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
149 return cursor
3
d70e57193731 new executeZSQL method that returns Zope Results.
casties
parents: 2
diff changeset
150
2
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
151 def getFieldNameMap(self,fields):
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
152 """returns a dict mapping field names to row indexes"""
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
153 map = {}
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
154 i = 0
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
155 for f in fields:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
156 map[f[0]] = i
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
157 i += 1
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
158
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
159 return map
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
160
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
161 def executeSQL(self, query, args=None, hasResult=True, autocommit=True):
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
162 """execute query with args on database and return all results.
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
163 result format: {"fields":fields, "rows":data}"""
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
164 logging.debug("executeSQL query=%s args=%s"%(query,args))
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
165 cur = self.getCursor(autocommit=autocommit)
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
166 if args is not None:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
167 # make sure args is a list
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
168 if isinstance(args,basestring):
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
169 args = (args,)
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
170
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
171 cur.execute(query, args)
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
172 # description of returned fields
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
173 fields = cur.description
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
174 if hasResult:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
175 # get all data in an array
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
176 data = cur.fetchall()
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
177 cur.close()
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
178 #logging.debug("fields: %s"%repr(fields))
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
179 #logging.debug("rows: %s"%repr(data))
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
180 return {"fields":fields, "rows":data}
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
181 else:
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
182 cur.close()
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
183 return None
881fcea6a57d new base class (unused)
casties
parents:
diff changeset
184