--- ZSQLExtend/ZSQLExtend.py 2007/03/08 17:00:48 1.106 +++ ZSQLExtend/ZSQLExtend.py 2007/04/19 20:47:00 1.113 @@ -4,9 +4,8 @@ from Globals import DTMLFile,package_hom import urllib import re import string -import sys #from pyPgSQL import libpq -from AccessControl import getSecurityManager +from AccessControl import getSecurityManager,Unauthorized from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate from Products.PageTemplates.PageTemplateFile import PageTemplateFile @@ -19,12 +18,12 @@ import os.path import os import copy import unicodedata - -import logging +import tempfile +import sys #ersetzt logging def logger(txt,method,txt2): - """logging""" + """logging""" logging.info(txt+ txt2) @@ -70,6 +69,9 @@ def sql_quote(v): def showSQLConnectionIDs(self): return SQLConnectionIDs(self) +class Options: + """options class""" + class ZSQLIndex(SimpleItem): """index""" meta_type="ZSQLIndex" @@ -319,7 +321,7 @@ class ZSQLExtendFolder(Folder,Persistent return ret - def importXMLFile(self,table,data=None,identify=None,filename=None,RESPONSE=None): + def importXMLFile(self,table,containerTagName,fieldNames,data=None,identify=None,filename=None,RESPONSE=None): #TODO: finish importXMLFile ''' Import XML file into the table @@ -329,6 +331,7 @@ class ZSQLExtendFolder(Folder,Persistent @param identify: (optional) field res. tag which identifies a entry uniquely for updating purposes. @param RESPONSE: (optional) ''' + ret="" from xml.dom.pulldom import parseString doc=parseString(file.read()) @@ -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={} @@ -721,6 +623,63 @@ class ZSQLExtendFolder(Folder,Persistent return 1 return 0 + def ZSQLMultiSearch(self,_table,_searchField,_value,_idField,_additionalStatement="",_select=None,_storename=None): + """ + Durchsucht in einer Tabelle "table" die Spalte "searchfield" nach dem allen Vorkommnissen + von Worten in value und gibt alle Werte mit gleichem id field zurŸck, d.h. es wird die "und" suche realisiert, + z.B. fŸr simplesearch ueber mehrere Felder + """ + if _storename: + """store""" + else: + _storename="foundCount" + + queries=[] + #baue jede einzelne abfrage + splitted=_value.split(" ") + if not _select: + _select=_idField + + queries.append("select %s from %s %s where lower(%s) like '%%%s%%'"%(_select,_table,_additionalStatement,_searchField,splitted[0].lower())) + + if len(splitted)>1: + for v in splitted[1:]: + queries.append("select %s from %s where lower(%s) like '%%%s%%'"%(_idField,_table,_searchField,v.lower())) + + q=" and %s in ("%_idField + query=q.join(queries) # nun baue sie zusammen + for i in range(len(queries)-1): + query+=")" #noch die klammern schliessen + + + if _additionalStatement: + query=query+" " + + logging.info("ZSQLSimple: %s"%query) + retT=self.ZSQLSimpleSearch(query) + logging.info("ZSQLSimple: %s"%retT) + + retFinalT={} + for x in retT: + split=_idField.split(".") + if len(split)>1: + f=split[1] + else: + f=_idField + + retFinalT[getattr(x,f)]=x + + ret=list(retFinalT.values()) + + + + if not self.REQUEST.SESSION.has_key(_storename): + self.REQUEST.SESSION[_storename]={} + + self.REQUEST.SESSION[_storename]['searchFieldsOnly']={} + self.REQUEST.SESSION[_storename]['qs']=query + return ret + def ZSQLsearchOptions(self,fieldname=""): """return HTML Fragment with search options""" @@ -789,7 +748,8 @@ class ZSQLExtendFolder(Folder,Persistent valueName=None,start=None, multiple='',startValue=None, additionalSelect="",size=None, - linelen=None,selected=None): + linelen=None,selected=None, + clear=False): """generate select options form a search list es wird """ return ret @@ -922,6 +886,7 @@ class ZSQLExtendFolder(Folder,Persistent if x: value=x else: + value=str(argTmp[a]) qs.append(aFiltered+"="+urllib.quote(value)) @@ -951,7 +916,7 @@ class ZSQLExtendFolder(Folder,Persistent def ZSQLSimpleSearch(self,query=None,max_rows=1000000): """simple search""" - + logging.error("ZSQLSimpleSearch X %s"%query) #print query if not query: query=self.query @@ -963,14 +928,17 @@ class ZSQLExtendFolder(Folder,Persistent self._v_searchSQL.max_rows_=max_rows try: - return self._v_searchSQL.__call__(var=query) + logging.error("I am here") + t=self._v_searchSQL.__call__(var=query) + logging.error("I am here %s"%t) + return t except : - + logger("ZSQLSimpleSearch ERROR1",logging.ERROR, '%s %s'%sys.exc_info()[:2]) if sys.exc_info()[0]=="Database Error": try: self.getConnectionObj().manage_open_connection() except: - logger("ZSQLSimpleSearch",logging.ERROR, '%s %s'%sys.exc_info()[:2]) + logger("ZSQLSimpleSearch ERROR2",logging.ERROR, '%s %s'%sys.exc_info()[:2]) else: try: @@ -978,7 +946,7 @@ class ZSQLExtendFolder(Folder,Persistent return self._v_searchSQL.__call__(var=query) except : - + logger("ZSQLSimpleSearch ERROR2",logging.ERROR, '%s %s'%sys.exc_info()[:2]) if sys.exc_info()[0]=="Database Error": try: self.getConnectionObj().manage_open_connection() @@ -1111,7 +1079,7 @@ class ZSQLExtendFolder(Folder,Persistent table=urllib.unquote(value) elif name=="-identify": identify=urllib.unquote(value) - identify=identify.split("=")[0]+"="+sql_quote(identify.split("=")[1]) + identify="lower("+identify.split("=")[0]+")="+sql_quote(identify.split("=")[1].lower()) elif name=="-format": format=urllib.unquote(value) #elif (not (name[0]=="-" or name[0]=="_")) and (not len(value)==0): @@ -1136,7 +1104,7 @@ class ZSQLExtendFolder(Folder,Persistent return True - def ZSQLFindIndexed(self,qs="",select="oid,*",storename=None,indexedFields=['data_line'],restrictField='id_text',**argv): + def ZSQLFindIndexed(self,tableList=[],qs="",select="oid,*",storename=None,indexedFields=['data_line'],restrictField='id_text',**argv): """find2""" for index in self.ZopeFind(self,obj_ids=indexedFields): @@ -1222,9 +1190,11 @@ class ZSQLExtendFolder(Folder,Persistent #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 @@ -1272,9 +1242,11 @@ class ZSQLExtendFolder(Folder,Persistent for query in querys: arg=query.split("=")[0] if arg[0]=="_": arg="-"+arg[1:] # sicherstellen, dass an Anfang stets "_" - queryList[arg]=query.split("=")[1] - - + try: + queryList[arg]=query.split("=")[1] + except: + queryList[arg]='' + argList=[] arg="" @@ -1448,6 +1420,7 @@ class ZSQLExtendFolder(Folder,Persistent #something is defined by _op_TABELLE.SUCHFELD_IN_DIESER_TABELLE.SELECT_FIELD.IDENTIFIER_IN_TABELLE elif (not name[0]==iCT) and len(punktsplit)==4: + if opfields.has_key(name): op=opfields[name] else: @@ -1488,10 +1461,10 @@ class ZSQLExtendFolder(Folder,Persistent op="all" + if value!='': #lehre Werte werde nicht hinzugefuegt + searchTmp="""%s in (select %s from %s where %s)"""%(punktsplit[3],punktsplit[2],punktsplit[0],tmp) - searchTmp="""%s in (select %s from %s where %s)"""%(punktsplit[3],punktsplit[2],punktsplit[0],tmp) - - queryTemplate.append(searchTmp) + queryTemplate.append(searchTmp) elif (not name[0]==iCT) and (not len(value)==0): @@ -1538,7 +1511,7 @@ class ZSQLExtendFolder(Folder,Persistent op="all" - if (not tableExt) or (namealt.split('.')[0]==tableExt): + if (value!='') and ((not tableExt) or (namealt.split('.')[0]==tableExt)): #keine leeren werde und keine auschluss if searchFields.has_key(namealt): searchFields[namealt]+=lopfields.get(name,'OR')+" "+tmp searchFieldsOnly[namealt]+=lopfields.get(name,'OR')+" "+value