--- ZSQLExtend/ZSQLExtend.py 2007/02/20 16:00:03 1.103
+++ ZSQLExtend/ZSQLExtend.py 2007/04/02 12:34:51 1.108
@@ -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,48 @@ 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,ascii_db=False,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
+ options.ascii_db=ascii_db
+ 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 +686,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
@@ -890,7 +798,7 @@ class ZSQLExtendFolder(Folder,Persistent
def ZSQLInlineSearch(self,storename=None,args=None,**argv):
"""inlinesearch"""
-
+
qs=[]
if storename:
"""store"""
@@ -908,7 +816,16 @@ class ZSQLExtendFolder(Folder,Persistent
#print "INLINE:",argv
for a in argTmp.keys():
aFiltered=re.sub(r"^-","_",a) # beginning of a command should always be "_"
- qs.append(aFiltered+"="+urllib.quote(str(argTmp[a])))
+
+ if type(argTmp[a]) is ListType: # ein parameter zweimal
+ value=""
+ #TODO find a better solution, currently only the last non empty entry is used.
+ for x in argTmp[a]:
+ if x:
+ value=x
+ else:
+ value=str(argTmp[a])
+ qs.append(aFiltered+"="+urllib.quote(value))
#return []
@@ -1144,7 +1061,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):
@@ -1196,136 +1113,94 @@ 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"""
-
+
#setzte generische werte
lop="AND" # standardsuche mit and
@@ -1346,6 +1221,7 @@ class ZSQLExtendFolder(Folder,Persistent
searchFieldsOnly={}
queryTemplate=[]
outerjoin=""
+ debug=None
if not select:
select="oid,*"
@@ -1362,8 +1238,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:
@@ -1402,8 +1281,10 @@ class ZSQLExtendFolder(Folder,Persistent
name=re.sub("r'+'"," ",q.split("=")[0].lower())
+
try:
value=urllib.unquote(q.split("=",1)[1])
+
except:
value=""
@@ -1518,6 +1399,7 @@ class ZSQLExtendFolder(Folder,Persistent
#print "OP",op,name
value=value.lower()
+
tmp=""
if opfields.has_key(name):
op=opfields[name]
@@ -1598,7 +1480,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)
@@ -1607,9 +1489,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
@@ -1620,9 +1502,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
@@ -1630,7 +1513,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)
@@ -1639,6 +1526,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)
@@ -1723,7 +1612,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 ""
@@ -1822,64 +1711,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='',