--- ZSQLExtend/ZSQLExtend.py 2006/12/08 16:23:54 1.98 +++ ZSQLExtend/ZSQLExtend.py 2007/02/09 17:39:44 1.102 @@ -14,12 +14,20 @@ from Products.ZSQLMethods.SQL import SQL from xml.sax.saxutils import escape from types import * import Shared.DC.ZRDB.DA -import zLOG +import logging import os.path import os import copy import unicodedata +import logging + +#ersetzt logging +def logger(txt,method,txt2): + """logging""" + logging.info(txt+ txt2) + + from OFS.SimpleItem import SimpleItem def getTextFromNode(nodename): @@ -161,7 +169,7 @@ class ZSQLExtendFolder(Folder,Persistent #from xml.dom.minidom import parseString,parse from Ft.Xml import Parse - zLOG.LOG("import xsd",zLOG.INFO,"called") + logger("import xsd",logging.INFO,"called") #fh=file("/tmp/fmpxml.xml") import bz2 import base64 @@ -171,16 +179,16 @@ class ZSQLExtendFolder(Folder,Persistent if data: data=bz2.decompress(base64.decodestring(data)) - #zLOG.LOG("import xsd",zLOG.INFO,"received file") + #logger("import xsd",logging.INFO,"received file") doc=Parse(data) - #zLOG.LOG("import xsd",zLOG.INFO,"parsed file") + #logger("import xsd",logging.INFO,"parsed file") elif filename: fh=file(filename) txt=fh.read() doc=Parse(txt) - #zLOG.LOG("import xsd",zLOG.INFO,"parsed file") + #logger("import xsd",logging.INFO,"parsed file") Nss={'xsd':'http://www.w3.org/2001/XMLSchema'} @@ -199,7 +207,7 @@ class ZSQLExtendFolder(Folder,Persistent else: create=False - zLOG.LOG("update xsd: fieldnames",zLOG.INFO,repr(fieldNames)) + logger("update xsd: fieldnames",logging.INFO,repr(fieldNames)) qstr="""select attname from pg_attribute, pg_class where attrelid = pg_class.oid and relname = '%s' """ columns=[x.attname for x in self.ZSQLSimpleSearch(qstr%table)] @@ -214,7 +222,7 @@ class ZSQLExtendFolder(Folder,Persistent for fieldName in fieldNames: if type(fieldName) is UnicodeType: fieldName=fieldName.encode('utf-8') - zLOG.LOG("update xml: fieldname",zLOG.INFO,repr(fieldName)) + logging.info("update xml: fieldname",logging.INFO,repr(fieldName)) if fieldName.lower() not in columns: if create:# table does not exist therefore create with one column @@ -224,7 +232,7 @@ class ZSQLExtendFolder(Folder,Persistent qstr="""alter table %s add %s %s""" self.ZSQLSimpleSearch(qstr%(table,fieldName,'text')) - zLOG.LOG("update xsd: fieldname add",zLOG.INFO,qstr%(table,fieldName,'text')) + logger("update xsd: fieldname add",logging.INFO,qstr%(table,fieldName,'text')) def importXMLFileAccess(self,table,container,data=None,identify=None,filename=None,RESPONSE=None): @@ -238,7 +246,7 @@ class ZSQLExtendFolder(Folder,Persistent ''' from xml.dom.pulldom import parseString,parse - zLOG.LOG("import xml",zLOG.INFO,"called") + logger("import xml",logging.INFO,"called") #fh=file("/tmp/fmpxml.xml") import bz2 import base64 @@ -247,14 +255,14 @@ class ZSQLExtendFolder(Folder,Persistent if data: data=bz2.decompress(base64.decodestring(data)) - zLOG.LOG("import xml",zLOG.INFO,"received file") + logger("import xml",logging.INFO,"received file") doc=parseString(data) - zLOG.LOG("import xml",zLOG.INFO,"parsed file") + logger("import xml",logging.INFO,"parsed file") elif filename: fh=file(filename) doc=parse(fh) - zLOG.LOG("import xml",zLOG.INFO,"parsed file") + logger("import xml",logging.INFO,"parsed file") while 1: node=doc.getEvent() @@ -277,7 +285,7 @@ class ZSQLExtendFolder(Folder,Persistent field=dataSet[identify] searchStr="""select %s from %s where %s = '%s'"""%(identify,table,identify,field) - zLOG.LOG("import xml",zLOG.INFO,searchStr) + logger("import xml",logging.INFO,searchStr) search=self.ZSQLSimpleSearch(searchStr) if search: update=True @@ -291,7 +299,7 @@ class ZSQLExtendFolder(Folder,Persistent field=dataSet[identify] queryStr="""UPDATE %s SET %s WHERE %s = '%s' """%(table,setStr,identify,field) - zLOG.LOG("update xml",zLOG.INFO,queryStr) + logger("update xml",logging.INFO,queryStr) self.ZSQLSimpleSearch(queryStr) ret+="ud: %s \n"%field else: @@ -303,7 +311,7 @@ class ZSQLExtendFolder(Folder,Persistent queryStr="""INSERT INTO %s (%s) VALUES (%s)"""%(table,fields,values) self.ZSQLSimpleSearch(queryStr) - zLOG.LOG("update xml",zLOG.INFO,queryStr) + logger("update xml",logging.INFO,queryStr) @@ -344,7 +352,7 @@ class ZSQLExtendFolder(Folder,Persistent field=dataSet[nr] searchStr="""select %s from %s where %s = '%s'"""%(identify,table,identify,field) - zLOG.LOG("import xml",zLOG.INFO,searchStr) + logger("import xml",logging.INFO,searchStr) search=self.ZSQLSimpleSearch(searchStr) if search: update=True @@ -358,7 +366,7 @@ class ZSQLExtendFolder(Folder,Persistent field=dataSet[nr] queryStr="""UPDATE %s SET %s WHERE %s = '%s' """%(table,setStr,identify,field) - zLOG.LOG("update xml",zLOG.INFO,queryStr) + logger("update xml",logging.INFO,queryStr) self.ZSQLSimpleSearch(queryStr) ret+="ud: %s \n"%field else: @@ -370,7 +378,7 @@ class ZSQLExtendFolder(Folder,Persistent queryStr="""INSERT INTO %s (%s) VALUES (%s)"""%(table,fields,values) self.ZSQLSimpleSearch(queryStr) - zLOG.LOG("update xml",zLOG.INFO,queryStr) + logger("update xml",logging.INFO,queryStr) ret+="ad: %s \n"%field elif node[1].nodeName=="METADATA": @@ -382,21 +390,164 @@ class ZSQLExtendFolder(Folder,Persistent for name in names: fieldNames.append(name.getAttribute('NAME')) - zLOG.LOG("update xml: fieldnames",zLOG.INFO,repr(fieldNames)) + logger("update xml: fieldnames",logging.INFO,repr(fieldNames)) qstr="""select attname from pg_attribute, pg_class where attrelid = pg_class.oid and relname = '%s' """ columns=[x.attname for x in self.ZSQLSimpleSearch(qstr%table)] for fieldName in fieldNames: - zLOG.LOG("update xml: fieldname",zLOG.INFO,repr(fieldName)) + logger("update xml: fieldname",logging.INFO,repr(fieldName)) if fieldName not in columns: qstr="""alter table %s add %s %s""" self.ZSQLSimpleSearch(qstr%(table,fieldName,'text')) - zLOG.LOG("update xml: fieldname add",zLOG.INFO,qstr%(table,fieldName,'text')) + logger("update xml: fieldname add",logging.INFO,qstr%(table,fieldName,'text')) #fn=node[1].getAttribute("xml:id") #nf=file("xtf/"+fn+".xtf",'w') #nf.write(""""""+node[1].toxml()+"") #print "wrote: %s"%fn + + + def importXMLFileFMP(self,table,data=None,filename=None,update_fields=None,id_field=None,sync_mode=False,RESPONSE=None): + ''' + Import FileMaker XML file (FMPXMLRESULT format) into the table. + @param table: name of the table the xml shall be imported into + @param data: xml data as bz2 string + @param filename: xmlfile filename + @param update_fields: (optional) list of fields to update; default is to create all fields + @param id_field: (optional) field which uniquely identifies an entry for updating purposes. + @param sync_mode: (optional) really synchronise, i.e. delete entries not in XML file + @param RESPONSE: (optional) + ''' + from xml.dom.pulldom import parseString,parse + import transaction + + ret = "" + + if data: + data=bz2.decompress(base64.decodestring(data)) + zLOG.LOG("fmpxml",zLOG.INFO,"received file") + doc=parseString(data) + zLOG.LOG("fmpxml",zLOG.INFO,"parsed file") + + elif filename: + fh=file(filename) + zLOG.LOG("fmpxml",zLOG.INFO,"reading file") + doc=parse(fh) + zLOG.LOG("fmpxml",zLOG.INFO,"parsed file") + + dbIDs = {} + rowcnt = 0 + + if id_field is not None: + # prepare a list of ids for sync mode + qstr="select %s from %s"%(id_field,table) + for id in self.ZSQLSimpleSearch(qstr): + # value 0: not updated + dbIDs[id[0]] = 0; + rowcnt += 1 + + zLOG.LOG("fmpxml",zLOG.INFO,"%d entries in DB to sync"%rowcnt) + + fieldNames = [] + rowcnt = 0 + id_val = '' + + while 1: + node=doc.getEvent() + + if node is None: + break; + + # METADATA tag defines number and names of fields in FMPXMLRESULT + if node[1].nodeName == 'METADATA': + doc.expandNode(node[1]) + + names=node[1].getElementsByTagName('FIELD') + + for name in names: + fn = name.getAttribute('NAME') + fieldNames.append(fn) + if update_fields is None: + # update all fields + update_fields = fieldNames + + zLOG.LOG("fmpxml fieldnames:",zLOG.INFO,repr(fieldNames)) + # get list of fields in db table + qstr="""select attname from pg_attribute, pg_class where attrelid = pg_class.oid and relname = '%s'""" + columns=[x.attname for x in self.ZSQLSimpleSearch(qstr%table)] + + # adjust db table to fields in XML and fieldlist + for fieldName in fieldNames: + zLOG.LOG("fmpxml fieldname:",zLOG.INFO,repr(fieldName)) + if (fieldName not in columns) and (fieldName in update_fields): + qstr="""alter table %s add %s %s""" + self.ZSQLSimpleSearch(qstr%(table,fieldName,'text')) + zLOG.LOG("fmpxml add field:",zLOG.INFO,qstr%(table,fieldName,'text')) + + # ROW tags (in RESULTSET tag) hold data + elif node[1].nodeName == 'ROW': + rowcnt += 1 + + doc.expandNode(node[1]) + cols=node[1].getElementsByTagName('COL') + dataSet={} + i = 0 + # populate with data + for col in cols: + data=col.getElementsByTagName('DATA') + dataSet[fieldNames[i]] = getTextFromNode(data[0]) + i += 1 + + update=False + + # synchronize by id_field + if id_field: + id_val=dataSet[id_field] + if id_val in dbIDs: + dbIDs[id_val] += 1 + update=True + + if update: + # update existing row (by id_field) + setvals=[] + for fieldName in update_fields: + setvals.append("%s = %s"%(fieldName,self.ZSQLQuote(dataSet[fieldName]))) + setStr=string.join(setvals, ',') + id_val=dataSet[id_field] + qstr="""UPDATE %s SET %s WHERE %s = '%s' """%(table,setStr,id_field,id_val) + #zLOG.LOG("fmpxml update:",zLOG.INFO,queryStr) + self.ZSQLSimpleSearch(qstr) + ret+="up: %s \n"%id_val + else: + # create new row + fields=string.join(update_fields, ',') + values=string.join([" %s "%self.ZSQLQuote(dataSet[x]) for x in update_fields], ',') + qstr="""INSERT INTO %s (%s) VALUES (%s)"""%(table,fields,values) + self.ZSQLSimpleSearch(qstr) + #zLOG.LOG("fmpxml: insert",zLOG.INFO,queryStr) + ret+="ad: %s \n"%dataSet.get(id_field, rowcnt) + + #zLOG.LOG("fmpxml row:",zLOG.INFO,"%d (%s)"%(rowcnt,id_val)) + if (rowcnt % 10) == 0: + zLOG.LOG("fmpxml row:",zLOG.INFO,"%d (%s)"%(rowcnt,id_val)) + transaction.commit() + + transaction.commit() + if sync_mode: + # delete unmatched entries in db + for id in dbIDs.keys(): + # find all not-updated fields + if dbIDs[id] == 0: + zLOG.LOG("fmpxml delete:",zLOG.INFO,id) + qstr = "DELETE FROM %s WHERE %s = '%s'" + self.ZSQLSimpleSearch(qstr%(table,id_field,id)) + + elif dbIDs[id] > 1: + zLOG.LOG("fmpxml sync:",zLOG.INFO,"id used more than once?"+id) + + transaction.commit() + + return ret def generateIndex(self,field,index_name,table,RESPONSE=None): """erzeuge index aus feld""" @@ -734,6 +885,8 @@ class ZSQLExtendFolder(Folder,Persistent ret[field[0]]=(self.ZSQLInlineSearch(storename=storename,args=argTmp2),field[3],field[4],field[5],field[6]) return ret + + def ZSQLInlineSearch(self,storename=None,args=None,**argv): """inlinesearch""" @@ -774,11 +927,11 @@ class ZSQLExtendFolder(Folder,Persistent try: self.getConnectionObj().manage_close_connection() except: - zLOG.LOG("ZSQLResetConnection",zLOG.ERROR, '%s %s'%sys.exc_info()[:2]) + logger("ZSQLResetConnection",logging.ERROR, '%s %s'%sys.exc_info()[:2]) try: self.getConnectionObj().manage_open_connection() except: - zLOG.LOG("ZSQLResetConnection",zLOG.ERROR, '%s %s'%sys.exc_info()[:2]) + logger("ZSQLResetConnection",logging.ERROR, '%s %s'%sys.exc_info()[:2]) def ZSQLSimpleSearch(self,query=None,max_rows=1000000): """simple search""" @@ -801,7 +954,7 @@ class ZSQLExtendFolder(Folder,Persistent try: self.getConnectionObj().manage_open_connection() except: - zLOG.LOG("ZSQLSimpleSearch",zLOG.ERROR, '%s %s'%sys.exc_info()[:2]) + logger("ZSQLSimpleSearch",logging.ERROR, '%s %s'%sys.exc_info()[:2]) else: try: @@ -814,7 +967,7 @@ class ZSQLExtendFolder(Folder,Persistent try: self.getConnectionObj().manage_open_connection() except: - zLOG.LOG("ZSQLSimpleSearch",zLOG.ERROR, '%s %s'%sys.exc_info()[:2]) + logger("ZSQLSimpleSearch",logging.ERROR, '%s %s'%sys.exc_info()[:2]) def getConnectionObj(self): if hasattr(self,'connection_id'): @@ -902,7 +1055,7 @@ class ZSQLExtendFolder(Folder,Persistent else: return True - def ZSQLChange(self,format=None,RESPONSE=None,USE_FORM=None,**argv): + def ZSQLChange(self,format=None,RESPONSE=None,USE_FORM=None,args=None,**argv): """change entries""" #qs=self.REQUEST['QUERY_STRING'] # very bad hack @@ -914,19 +1067,23 @@ class ZSQLExtendFolder(Folder,Persistent qs_temp.append(a+"="+urllib.quote(str(self.REQUEST.form[a]))) - - for field in argv.keys(): + if args: + arg_tmp=args + else: + arg_tmp=argv + + for field in arg_tmp.keys(): if field[0]=="_": fieldTmp="-"+field[1:] else: fieldTmp=field - qs_temp.append("%s=%s"%(fieldTmp,argv[field])) + qs_temp.append("%s=%s"%(fieldTmp,arg_tmp[field])) changeList=[] - + logging.info("ZSQLChange qs_temp: %s"%repr(qs_temp)) for q in qs_temp: name=urllib.unquote(re.sub("r'+'"," ",q.split("=")[0].lower())) @@ -952,7 +1109,7 @@ class ZSQLExtendFolder(Folder,Persistent changeString=string.join(changeList,",") queryString="UPDATE %s SET %s WHERE %s"%(table,changeString,identify) - zLOG.LOG("ZSQLExtend",zLOG.INFO,"CHANGE: "+queryString) + logger("ZSQLExtend",logging.INFO,"CHANGE: "+queryString) self.ZSQLSimpleSearch(queryString) @@ -1497,7 +1654,7 @@ class ZSQLExtendFolder(Folder,Persistent def ZSQLQuery(self,query,debug=None): """query""" if debug: - zLOG.LOG("ZSQLQuery", zLOG.INFO, query) + logger("ZSQLQuery", logging.INFO, query) return self.ZSQLSimpleSearch(query) @@ -1525,7 +1682,7 @@ class ZSQLExtendFolder(Folder,Persistent self.REQUEST.SESSION['query']=string.join(self.REQUEST['QUERY_STRING'].split("&"),",") self.REQUEST.SESSION['come_from_search']="yes" - return self.REQUEST.RESPONSE.redirect(urllib.unquote(formatfile)) + return self.REQUEST.RESPONSE.redirect(urllib.unquote(formatfile)+"?"+rq) def ZSQLint(self,string):