|
|
| version 1.105, 2007/02/22 13:23:20 | version 1.109, 2007/04/03 14:44:24 |
|---|---|
| Line 4 from Globals import DTMLFile,package_hom | Line 4 from Globals import DTMLFile,package_hom |
| import urllib | import urllib |
| import re | import re |
| import string | import string |
| import sys | |
| #from pyPgSQL import libpq | #from pyPgSQL import libpq |
| from AccessControl import getSecurityManager | from AccessControl import getSecurityManager,Unauthorized |
| from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate | from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate |
| from Products.PageTemplates.PageTemplateFile import PageTemplateFile | from Products.PageTemplates.PageTemplateFile import PageTemplateFile |
| Line 19 import os.path | Line 18 import os.path |
| import os | import os |
| import copy | import copy |
| import unicodedata | import unicodedata |
| import tempfile | |
| import logging | import sys |
| #ersetzt logging | #ersetzt logging |
| def logger(txt,method,txt2): | def logger(txt,method,txt2): |
| Line 70 def sql_quote(v): | Line 69 def sql_quote(v): |
| def showSQLConnectionIDs(self): | def showSQLConnectionIDs(self): |
| return SQLConnectionIDs(self) | return SQLConnectionIDs(self) |
| class Options: | |
| """options class""" | |
| class ZSQLIndex(SimpleItem): | class ZSQLIndex(SimpleItem): |
| """index""" | """index""" |
| meta_type="ZSQLIndex" | meta_type="ZSQLIndex" |
| Line 319 class ZSQLExtendFolder(Folder,Persistent | Line 321 class ZSQLExtendFolder(Folder,Persistent |
| return ret | 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 | #TODO: finish importXMLFile |
| ''' | ''' |
| Import XML file into the table | Import XML file into the table |
| Line 329 class ZSQLExtendFolder(Folder,Persistent | Line 331 class ZSQLExtendFolder(Folder,Persistent |
| @param identify: (optional) field res. tag which identifies a entry uniquely for updating purposes. | @param identify: (optional) field res. tag which identifies a entry uniquely for updating purposes. |
| @param RESPONSE: (optional) | @param RESPONSE: (optional) |
| ''' | ''' |
| ret="" | |
| from xml.dom.pulldom import parseString | from xml.dom.pulldom import parseString |
| doc=parseString(file.read()) | doc=parseString(file.read()) |
| Line 406 class ZSQLExtendFolder(Folder,Persistent | Line 409 class ZSQLExtendFolder(Folder,Persistent |
| #print "wrote: %s"%fn | #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. | 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 table: name of the table the xml shall be imported into |
| @param data: xml data as bz2 string | @param uploadfile: xmlfile file |
| @param filename: xmlfile filename | |
| @param update_fields: (optional) list of fields to update; default is to create all fields | @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 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 sync_mode: (optional) really synchronise, i.e. delete entries not in XML file |
| @param RESPONSE: (optional) | @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() | |
| 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)) | tfilehd,filename=tempfile.mkstemp() |
| # get list of fields in db table | tfile=os.fdopen(tfilehd,'w') |
| qstr="""select attname from pg_attribute, pg_class where attrelid = pg_class.oid and relname = '%s'""" | logging.error("import %s"%uploadfile) |
| columns=[x.attname for x in self.ZSQLSimpleSearch(qstr%table)] | for c in uploadfile.read(): |
| tfile.write(c) | |
| # adjust db table to fields in XML and fieldlist | tfile.close() |
| for fieldName in fieldNames: | |
| logger("fmpxml fieldname:",logging.INFO,repr(fieldName)) | from importFMPXML import importFMPXML |
| if (fieldName not in columns) and (fieldName in update_fields): | |
| qstr="""alter table %s add %s %s""" | if not dsn: |
| self.ZSQLSimpleSearch(qstr%(table,fieldName,'text')) | dsn=self.getConnectionObj().connection_string |
| logger("fmpxml add field:",logging.INFO,qstr%(table,fieldName,'text')) | |
| 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) | |
| # ROW tags (in RESULTSET tag) hold data | os.remove(filename) |
| elif node[1].nodeName == 'ROW': | |
| rowcnt += 1 | |
| doc.expandNode(node[1]) | if RESPONSE and redirect_url: |
| cols=node[1].getElementsByTagName('COL') | RESPONSE.redirect(redirect_url) |
| 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 | |
| def generateIndex(self,field,index_name,table,RESPONSE=None): | def generateIndex(self,field,index_name,table,RESPONSE=None): |
| """erzeuge index aus feld""" | """erzeuge index aus feld""" |
| Line 784 class ZSQLExtendFolder(Folder,Persistent | Line 686 class ZSQLExtendFolder(Folder,Persistent |
| ret+="""</select>""" | ret+="""</select>""" |
| return 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 | """generate select options form a search list |
| es wird | es wird |
| <select name=fieldname mutiple> | <select name=fieldname mutiple> |
| Line 797 class ZSQLExtendFolder(Folder,Persistent | Line 704 class ZSQLExtendFolder(Folder,Persistent |
| @parameter fieldName: Name des Feldes, das als value in den option-tag geschrieben werden soll. | @parameter fieldName: Name des Feldes, das als value in den option-tag geschrieben werden soll. |
| @parameter valueName: (optional) Name des Feldes, dass als im option-tag ausgegeben wird, default wert ist valueName=fieldName | @parameter valueName: (optional) Name des Feldes, dass als im option-tag ausgegeben wird, default wert ist valueName=fieldName |
| @start: (optional) falls zusaetzliches option tag erzeugt werden soll, gibt start an was im option tag steht | @start: (optional) falls zusaetzliches option tag erzeugt werden soll, gibt start an was im option tag steht |
| @startValue: gibt den entsprechenden Wert an. | @startValue (optional): gibt den entsprechenden Wert an. |
| @selected (optional): Wert der ausgewaehlt sein soll. | |
| @linelen: (optional) maximale laenge eines Eintrages | @linelen: (optional) maximale laenge eines Eintrages |
| der im Klappmenue noch angezeigt wird, laengeres wird abgeschnitten. | der im Klappmenue noch angezeigt wird, laengeres wird abgeschnitten. |
| @addionalSaelect (optional): zusaetzlicher text fuer den select tag | |
| """ | """ |
| if not valueName: | if not valueName: |
| valueName=fieldName | valueName=fieldName |
| Line 817 class ZSQLExtendFolder(Folder,Persistent | Line 726 class ZSQLExtendFolder(Folder,Persistent |
| startValue=start | startValue=start |
| ret+="""<option value="%s" >%s</option>"""%(startValue,start) | ret+="""<option value="%s" >%s</option>"""%(startValue,start) |
| for result in results: | for result in results: |
| field=getattr(result,fieldName) | field=getattr(result,fieldName) |
| fieldValue=getattr(result,valueName) | fieldValue=getattr(result,valueName) |
| if fieldValue: | if linelen and fieldValue and (len(fieldValue) > string.atoi(linelen)): |
| displayValue = fieldValue[:string.atoi(linelen)] | |
| if not linelen: | else: |
| displayValue = fieldValue | |
| if field == selected: | if field == selected: |
| ret+="""<option value="%s" selected>%s</option>"""%(field,fieldValue) | ret+="""<option value="%s" selected>%s</option>"""%(field,displayValue) |
| else: | else: |
| ret+="""<option value="%s">%s</option>"""%(field,fieldValue) | ret+="""<option value="%s">%s</option>"""%(field,displayValue) |
| else: | |
| mist = """%s"""%(fieldValue) | |
| if len(mist) > string.atoi(linelen): | |
| mist = mist[:string.atoi(linelen)] | |
| ret+="""<option value="%s">%s</option>"""%(field,mist) | |
| ret+="""</select>""" | ret+="""</select>""" |
| return ret | return ret |
| Line 947 class ZSQLExtendFolder(Folder,Persistent | Line 853 class ZSQLExtendFolder(Folder,Persistent |
| def ZSQLSimpleSearch(self,query=None,max_rows=1000000): | def ZSQLSimpleSearch(self,query=None,max_rows=1000000): |
| """simple search""" | """simple search""" |
| logging.error(query) | |
| #print query | #print query |
| if not query: | if not query: |
| query=self.query | query=self.query |
| Line 1132 class ZSQLExtendFolder(Folder,Persistent | Line 1038 class ZSQLExtendFolder(Folder,Persistent |
| return True | 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""" | """find2""" |
| for index in self.ZopeFind(self,obj_ids=indexedFields): | for index in self.ZopeFind(self,obj_ids=indexedFields): |
| Line 1315 class ZSQLExtendFolder(Folder,Persistent | Line 1221 class ZSQLExtendFolder(Folder,Persistent |
| searchFieldsOnly={} | searchFieldsOnly={} |
| queryTemplate=[] | queryTemplate=[] |
| outerjoin="" | outerjoin="" |
| debug=None | |
| if not select: | if not select: |
| select="oid,*" | select="oid,*" |
| Line 1333 class ZSQLExtendFolder(Folder,Persistent | Line 1240 class ZSQLExtendFolder(Folder,Persistent |
| for q in splitted: | for q in splitted: |
| name=re.sub("r'+'"," ",q.split("=")[0].lower()) | name=re.sub("r'+'"," ",q.split("=")[0].lower()) |
| if name=="_debug": | |
| debug=True | |
| try: | try: |
| value=urllib.unquote(q.split("=",1)[1]) | value=urllib.unquote(q.split("=",1)[1]) |
| except: | except: |
| Line 1616 class ZSQLExtendFolder(Folder,Persistent | Line 1526 class ZSQLExtendFolder(Folder,Persistent |
| self.REQUEST.SESSION[storename]['searchFieldsOnly']=searchFieldsOnly | self.REQUEST.SESSION[storename]['searchFieldsOnly']=searchFieldsOnly |
| if debug: | |
| logging.error("ZSQLSimpleSearch %s"%query) | |
| if not NoQuery: | if not NoQuery: |
| return self.ZSQLQuery(query) | return self.ZSQLQuery(query) |