--- ZSQLExtend/ZSQLExtend.py 2007/02/20 17:19:38 1.104 +++ ZSQLExtend/ZSQLExtend.py 2007/04/02 09:48:13 1.107 @@ -19,7 +19,7 @@ import os.path import os import copy import unicodedata - +import tempfile import logging #ersetzt logging @@ -70,6 +70,9 @@ def sql_quote(v): def showSQLConnectionIDs(self): return SQLConnectionIDs(self) +class Options: + """options class""" + class ZSQLIndex(SimpleItem): """index""" meta_type="ZSQLIndex" @@ -406,149 +409,47 @@ class ZSQLExtendFolder(Folder,Persistent #print "wrote: %s"%fn - def importXMLFileFMP(self,table,data=None,filename=None,update_fields=None,id_field=None,sync_mode=False,RESPONSE=None): + def importXMLFileFMP(self,table,dsn=None,uploadfile=None,update_fields=None,id_field=None,sync_mode=False,replace=False,redirect_url=None,RESPONSE=None): ''' Import FileMaker XML file (FMPXMLRESULT format) into the table. + @param dsn: database connection string @param table: name of the table the xml shall be imported into - @param data: xml data as bz2 string - @param filename: xmlfile filename + @param uploadfile: xmlfile file @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) + @param redirect_url: (optional) url for redirecting after the upload is done ''' - from xml.dom.pulldom import parseString,parse - import transaction - - ret = "" - - if data: - data=bz2.decompress(base64.decodestring(data)) - logger("fmpxml",logging.INFO,"received file") - doc=parseString(data) - logger("fmpxml",logging.INFO,"parsed file") - - elif filename: - fh=file(filename) - logger("fmpxml",logging.INFO,"reading file") - doc=parse(fh) - logger("fmpxml",logging.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 - - logger("fmpxml",logging.INFO,"%d entries in DB to sync"%rowcnt) - - fieldNames = [] - rowcnt = 0 - id_val = '' - while 1: - node=doc.getEvent() + tfilehd,filename=tempfile.mkstemp() + tfile=os.fdopen(tfilehd,'w') + logging.error("import %s"%uploadfile) + for c in uploadfile.read(): + tfile.write(c) + tfile.close() + + from importFMPXML import importFMPXML + + if not dsn: + dsn=self.getConnectionObj().connection_string + + options=Options() + options.dsn=dsn + options.table=table + options.filename=filename + options.update_fields=update_fields + options.id_field=id_field + options.sync_mode=sync_mode + options.replace_table=replace + options.lc_names=True + importFMPXML(options) - 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 - - logger("fmpxml fieldnames:",logging.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: - logger("fmpxml fieldname:",logging.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')) - logger("fmpxml add field:",logging.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) - #logger("fmpxml update:",logging.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) - #logger("fmpxml: insert",logging.INFO,queryStr) - ret+="ad: %s \n"%dataSet.get(id_field, rowcnt) - - #logger("fmpxml row:",logging.INFO,"%d (%s)"%(rowcnt,id_val)) - if (rowcnt % 10) == 0: - logger("fmpxml row:",logging.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: - logger("fmpxml delete:",logging.INFO,id) - qstr = "DELETE FROM %s WHERE %s = '%s'" - self.ZSQLSimpleSearch(qstr%(table,id_field,id)) - - elif dbIDs[id] > 1: - logger("fmpxml sync:",logging.INFO,"id used more than once?"+id) - - transaction.commit() - - return ret + os.remove(filename) + if RESPONSE and redirect_url: + RESPONSE.redirect(redirect_url) + def generateIndex(self,field,index_name,table,RESPONSE=None): """erzeuge index aus feld""" index={} @@ -784,7 +685,12 @@ class ZSQLExtendFolder(Folder,Persistent ret+="""""" return ret - def ZSQLOptionsFromSearchList(self,fieldname,results,fieldName,valueName=None,start=None, multiple='',startValue=None,additionalSelect="",size=None,linelen=None,selected=None): + def ZSQLOptionsFromSearchList(self,fieldname, + results,fieldName, + valueName=None,start=None, + multiple='',startValue=None, + additionalSelect="",size=None, + linelen=None,selected=None): """generate select options form a search list es wird """ return ret @@ -1155,7 +1060,7 @@ class ZSQLExtendFolder(Folder,Persistent - def ZSQLFind(self,qs="",select="oid,*",storename=None,tableExt=None,NoQuery=None,NoLimit=None,restrictField=None,restrictConnect=None,filter=None,**argv): + def ZSQLFind(self,qs="",select="oid,*",storename="foundCount",tableExt=None,NoQuery=None,NoLimit=None,restrictField=None,restrictConnect=None,filter=None,**argv): """search in database""" def delEmpty(list): @@ -1207,133 +1112,91 @@ class ZSQLExtendFolder(Folder,Persistent qs=string.join(delEmpty(qs.split(",")),",") - if storename: - """store""" - else: - storename="foundCount" #store query for further usage + #TODO: erste der beiden ist ueberfluessig self.REQUEST.SESSION['query']=qs - + if not self.REQUEST.SESSION.has_key(storename): + self.REQUEST.SESSION[storename]={} + + self.REQUEST.SESSION[storename]['qs']=qs + + #print "calling Query with",repr(NoQuery) ret=self.parseQueryString(qs,"-",select=select,storemax="yes",storename=storename,tableExt=tableExt,NoQuery=NoQuery,NoLimit=NoLimit,restrictField=restrictField,restrictConnect=restrictConnect,filter=filter) #print self.REQUEST.SESSION["foundCount"] - return ret def ZSQLFoundCountLen(self,var): return len(var) - def ZSQLFoundCount(self,qs="",select="*",storename=None): - - ## if qs=="": - -## if self.REQUEST['QUERY_STRING']: - -## qs=self.REQUEST['QUERY_STRING'] -## qs=string.join(qs.split("&"),",") -## else: - -## qs=self.REQUEST.SESSION['query'] -## else: -## qs=string.join(qs.split("&"),",") - - -## temp= self.parseQueryString(qs,"-",select=select,storemax="yes",nostore="yes") - if storename: - """store""" - else: - storename="foundCount" - + def ZSQLFoundCount(self,qs="",select="*",storename="foundCount"): + return self.REQUEST.SESSION[storename]['count'] - def ZSQLRangeStart(self,storename=None): - - if storename: - """store""" - else: - storename="foundCount" - + def ZSQLRangeStart(self,storename="foundCount"): + return int(self.REQUEST.SESSION[storename]['rangeStart'])+1 - def ZSQLRangeSize(self,storename=None): + def ZSQLRangeSize(self,storename="foundCount"): - if storename: - """store""" - else: - storename="foundCount" - return self.REQUEST.SESSION[storename]['rangeSize'] - def ZSQLRangeEnd(self,storename=None): - - if storename: - """store""" - else: - storename="foundCount" - + def ZSQLRangeEnd(self,storename="foundCount"): + return str(min(int(self.REQUEST.SESSION[storename]['rangeEnd']),int(self.REQUEST.SESSION[storename]['count']))) - def ZSQLNewQuery(self,linkText,storename=None,**argv): + def ZSQLNewQuery(self,linkText,storename="foundCount",**argv): """suche neu""" return self.ZSQLNewSearch(linkText,storename,url=self.REQUEST['URL'],args=argv) - def ZSQLNewSearch(self,linkText,storename=None,url=None,args=None,**argv): + def ZSQLNewSearch(self,linkText,storename="foundCount",url=None,args=None,**argv): """suche mit alten parametern bis auf die in argv getauschten""" str = self.ZSQLNewSearchURL(storename, url, args, **argv) return """ %s"""%(str,linkText) - def ZSQLNewSearchURL(self, storename=None,url=None,args=None,**argv): + def ZSQLNewSearchURL(self, storename="foundCount",url=None,args=None,**argv): """suche mit alten parametern bis auf die in argv getauschten""" - - if storename: - """store""" - else: - storename="foundCount" - qs=self.REQUEST.SESSION[storename]['qs'] - if args: argv=args - + + #get the old queries + qs=self.REQUEST.SESSION[storename]['qs'] querys=qs.split(",") + + #which arguments are in the old query string + + queryList={} + for query in querys: + arg=query.split("=")[0] + if arg[0]=="_": arg="-"+arg[1:] # sicherstellen, dass an Anfang stets "_" + queryList[arg]=query.split("=")[1] + + argList=[] arg="" - queryList=[x.split("=")[0] for x in querys] + + + #gehe durch die zu aendernden Argumente for argTmp in argv.keys(): - - arg=argTmp[0:] - - - if arg not in queryList: # noch nicht drin - querys.append("%s=%s"%(arg,argv[argTmp])) - argList.append(arg) + arg=argTmp[0:]# sicherstellen, dass der string auh kopiert wird + if arg[0]=="_": arg="-"+arg[1:] # sicherstellen, dass an Anfang stets "_" - - - newquery=[] - for query in querys: - queryArg=query.split("=")[0] - qarg=queryArg[0:] - if qarg[0]=="-":qarg="_"+queryArg[1:] # aender _ in - als standard - - if queryArg in argList: - newquery.append("%s=%s"%(queryArg,argv[qarg])) - else: - newquery.append(query) + queryList[arg]=argv[argTmp] if url: - str=url+"?"+"&".join(newquery) + str=url+"?"+urllib.urlencode(queryList) else: - str="ZSQLSearch?"+"&".join(newquery) + str="ZSQLSearch?"+urllib.urlencode(queryList) return str - def parseQueryString(self,qs,iCT,storemax="no",select=None,nostore=None,storename=None,tableExt=None,NoQuery=None,NoLimit=None,restrictField=None,restrictConnect=None,filter=None): + def parseQueryString(self,qs,iCT,storemax="no",select=None,nostore=None,storename="foundCount",tableExt=None,NoQuery=None,NoLimit=None,restrictField=None,restrictConnect=None,filter=None): """analysieren den QueryString""" @@ -1357,6 +1220,7 @@ class ZSQLExtendFolder(Folder,Persistent searchFieldsOnly={} queryTemplate=[] outerjoin="" + debug=None if not select: select="oid,*" @@ -1373,8 +1237,11 @@ class ZSQLExtendFolder(Folder,Persistent #erster durchgang suche operatoren for q in splitted: - + name=re.sub("r'+'"," ",q.split("=")[0].lower()) + if name=="_debug": + debug=True + try: value=urllib.unquote(q.split("=",1)[1]) except: @@ -1612,7 +1479,7 @@ class ZSQLExtendFolder(Folder,Persistent self.REQUEST.SESSION['qs']=opfields #print "IAMHERE again:", query - if storename and (not NoQuery): + if not NoQuery: query2="SELECT count(*) FROM %s %s"%(table,where) @@ -1621,9 +1488,9 @@ class ZSQLExtendFolder(Folder,Persistent self.REQUEST.SESSION[storename]={} self.REQUEST.SESSION[storename]['qs']=qs #sichere Querystring - + if self.REQUEST.SESSION[storename].has_key('queryString2'): - + if not self.REQUEST.SESSION[storename]['queryString2']==query2: #print "HOOOOO",storename self.REQUEST.SESSION[storename]['queryString2']=query2 @@ -1634,9 +1501,10 @@ class ZSQLExtendFolder(Folder,Persistent #print "QUERY",query2,"::::",self.REQUEST.SESSION[storename]['queryString2'] else: - + self.REQUEST.SESSION[storename]['queryString2']=query2 if self.ZSQLSimpleSearch(query2): + self.REQUEST.SESSION[storename]['count']=self.ZSQLSimpleSearch(query2)[0].count else: self.REQUEST.SESSION[storename]['count']=0 @@ -1644,7 +1512,11 @@ class ZSQLExtendFolder(Folder,Persistent self.REQUEST.SESSION[storename]['rangeStart']=rangeStart - if limit=="all": + + + self.REQUEST.SESSION[storename]['rangeEnd']=self.REQUEST.SESSION[storename]['count'] + + if (limit=="all") or (limit==int(limit)): self.REQUEST.SESSION[storename]['rangeEnd']=self.REQUEST.SESSION[storename]['count'] else: self.REQUEST.SESSION[storename]['rangeEnd']=int(rangeStart)+int(limit) @@ -1653,6 +1525,8 @@ class ZSQLExtendFolder(Folder,Persistent self.REQUEST.SESSION[storename]['searchFieldsOnly']=searchFieldsOnly + if debug: + logging.error("ZSQLSimpleSearch %s"%query) if not NoQuery: return self.ZSQLQuery(query) @@ -1737,7 +1611,7 @@ class ZSQLExtendFolder(Folder,Persistent limit=1 newRangeStart=0 - if newRangeStart>=self.REQUEST.SESSION[storename]['count']: + if (newRangeStart>=self.REQUEST.SESSION[storename]['count']) or (self.REQUEST.SESSION[storename]['count']==self.REQUEST.SESSION[storename]['rangeEnd']): #newRangeStart=self.REQUEST.SESSION[storename]['count']-1 return "" @@ -1836,64 +1710,7 @@ class ZSQLExtendFolder(Folder,Persistent - def prevLink_old(self,html): - """prev link""" - if self.REQUEST['QUERY_STRING']=="": - qs=self.REQUEST.SESSION['query'] - else: - qs=self.REQUEST['QUERY_STRING'] - max=re.search(r'max\=(.*)\,',qs.lower()) - offset=re.search(r'offset\=(.*)\,',qs.lower()) - if not offset: - offsetnew=0 - else: - offsetnew=int(offset)-max - if offsetnew<0: - offsetnew=0 - queries=string.split(qs,",") - newquery=[] - if offset: - for query in queries: - if query.split("=")[0].lower()=="offset": - query="-offset=%i"%offsetnew - newquery.append(query) - newquerystring=string.join(newquery,"&") - else: - queries.append("-offset=%i"%offsetnew) - newquerystring=string.join(queries,"&") - return "%s"%(self.actualPath()+"?"+newquerystring,html) - - def nextLink_old(self,html): - """prev link""" - if self.REQUEST['QUERY_STRING']=="": - qs=self.REQUEST.SESSION['query'] - else: - qs=self.REQUEST['QUERY_STRING'] - max=re.search(r'max\=(.*)\,',qs.lower()) - - offset=re.search(r'offset\=(.*)\,',qs.lower()) - if not offset: - offsetnew=1 - else: - offsetnew=int(offset)+int(max) - if offsetnew<0: - offsetnew=0 - queries=string.split(qs,",") - newquery=[] - if offset: - for query in queries: - - if query.split("=")[0].lower()=="-offset": - query="-offset=%i"%offsetnew - newquery.append(query) - newquerystring=string.join(newquery,"&") - else: - queries.append("-offset=%i"%offsetnew) - newquerystring=string.join(queries,"&") - - return "%s"%(self.actualPath()+"?"+newquerystring,html) - - + manage_addZSQLExtendFolderForm=DTMLFile('ZSQLExtendFolderAdd', globals()) def manage_addZSQLExtendFolder(self, id, title='', label='', description='',