Diff for /ZSQLExtend/importFMPXML.py between versions 1.27 and 1.33

version 1.27, 2008/09/05 19:05:57 version 1.33, 2011/06/23 09:14:53
Line 6  import logging Line 6  import logging
 import sys  import sys
 import types  import types
 import time  import time
   import re
   
 from xml import sax  from xml import sax
 from amara import saxtools  from amara import saxtools
Line 22  except: Line 23  except:
   
 fm_ns = 'http://www.filemaker.com/fmpxmlresult'  fm_ns = 'http://www.filemaker.com/fmpxmlresult'
   
 version_string = "V0.6.1 ROC 2.7.2008"  version_string = "V0.6.7 ROC 21.6.2011"
   
 def unicodify(text, withNone=False):  def unicodify(text, withNone=False):
     """decode str (utf-8 or latin-1 representation) into unicode object"""      """decode str (utf-8 or latin-1 representation) into unicode object"""
Line 68  def sql_quote(v): Line 69  def sql_quote(v):
             v=string.join(string.split(v,dkey),quote_dict[dkey])              v=string.join(string.split(v,dkey),quote_dict[dkey])
     return "'%s'"%v      return "'%s'"%v
   
   def sqlName(s, lc=True, more=''):
       """returns restricted ASCII-only version of string"""
       if s is None:
           return ""
       
       # remove '
       s = s.replace("'","")
       # all else -> "_"
       s = re.sub('[^A-Za-z0-9_'+more+']','_',s)
       if lc:
           return s.lower()
       
       return s
   
 def SimpleSearch(curs,query, args=None, ascii=False):  def SimpleSearch(curs,query, args=None, ascii=False):
     """execute sql query and return data"""      """execute sql query and return data"""
     #logger.debug("executing: "+query)      #logger.debug("executing: "+query)
Line 160  class xml_handler: Line 175  class xml_handler:
         self.replace_table = getattr(options,"replace_table",None)          self.replace_table = getattr(options,"replace_table",None)
         self.backup_table = getattr(options,"backup_table",None)          self.backup_table = getattr(options,"backup_table",None)
         self.read_before_update = getattr(options,"read_before_update",None)          self.read_before_update = getattr(options,"read_before_update",None)
           self.debug_data = getattr(options,"debug_data",None)
   
         self.logger.debug("dsn: "+repr(getattr(options,"dsn",None)))          self.logger.debug("dsn: "+repr(getattr(options,"dsn",None)))
         self.logger.debug("table: "+repr(self.table))          self.logger.debug("table: "+repr(self.table))
Line 172  class xml_handler: Line 188  class xml_handler:
         self.logger.debug("replace_table: "+repr(self.replace_table))          self.logger.debug("replace_table: "+repr(self.replace_table))
         self.logger.debug("backup_table: "+repr(self.backup_table))          self.logger.debug("backup_table: "+repr(self.backup_table))
         self.logger.debug("read_before_update: "+repr(self.read_before_update))          self.logger.debug("read_before_update: "+repr(self.read_before_update))
           self.logger.debug("debug_data: "+repr(self.debug_data))
                   
         self.dbIDs = {}          self.dbIDs = {}
         self.rowcnt = 0          self.rowcnt = 0
Line 203  class xml_handler: Line 220  class xml_handler:
         #First round through the generator corresponds to the          #First round through the generator corresponds to the
         #start element event          #start element event
         self.logger.info("reading metadata...")          self.logger.info("reading metadata...")
           if self.debug_data:
         self.logger.debug("START METADATA")          self.logger.debug("START METADATA")
         yield None          yield None
           
Line 215  class xml_handler: Line 233  class xml_handler:
             yield None              yield None
                   
         #Element closed. Wrap up          #Element closed. Wrap up
           if self.debug_data:
         self.logger.debug("END METADATA")          self.logger.debug("END METADATA")
                   
         # rename table for backup          # rename table for backup
Line 347  class xml_handler: Line 366  class xml_handler:
         #Element closed.  Wrap up          #Element closed.  Wrap up
         if self.lc_names:          if self.lc_names:
             # clean name              # clean name
             sqlname = name.replace(" ","_").lower()               sqlname = sqlName(name)
         else:          else:
             sqlname = name              sqlname = name
         self.xml_field_names.append(name)          self.xml_field_names.append(name)
Line 365  class xml_handler: Line 384  class xml_handler:
         #First round through the generator corresponds to the          #First round through the generator corresponds to the
         #start element event          #start element event
         self.logger.info("reading data...")          self.logger.info("reading data...")
           if self.debug_data:
         self.logger.debug("START RESULTSET")          self.logger.debug("START RESULTSET")
         self.rowcnt = 0          self.rowcnt = 0
         yield None          yield None
Line 378  class xml_handler: Line 398  class xml_handler:
             yield None              yield None
                   
         #Element closed.  Wrap up          #Element closed.  Wrap up
           if self.debug_data:
         self.logger.debug("END RESULTSET")          self.logger.debug("END RESULTSET")
         self.dbCon.commit()          self.dbCon.commit()
                   
         if self.sync_mode:          if self.sync_mode:
             # delete unmatched entries in db              # delete unmatched entries in db
               if self.rowcnt > 0:
             self.logger.info("deleting unmatched rows from db")              self.logger.info("deleting unmatched rows from db")
             delQuery = "DELETE FROM %s WHERE \"%s\" = %%s"%(self.table,self.id_field)              delQuery = "DELETE FROM %s WHERE \"%s\" = %%s"%(self.table,self.id_field)
             for id in self.dbIDs.keys():              for id in self.dbIDs.keys():
Line 396  class xml_handler: Line 418  class xml_handler:
                           
             self.dbCon.commit()              self.dbCon.commit()
                           
               else:
                   # safety in case we had an empty file
                   self.logger.warning("no rows read! not deleting unmatched rows!")
               
         # reinstate backup tables          # reinstate backup tables
         if self.backup_table and not self.id_field:          if self.backup_table and not self.id_field:
             backup_name = "%s_%s"%(self.orig_table,time.strftime('%Y_%m_%d_%H_%M_%S'))              backup_name = "%s_%s"%(self.orig_table,time.strftime('%Y_%m_%d_%H_%M_%S'))
Line 407  class xml_handler: Line 433  class xml_handler:
             self.db.execute(qstr)              self.db.execute(qstr)
             self.dbCon.commit()              self.dbCon.commit()
                   
           self.logger.info("Done (%s rows)"%self.rowcnt)
         return          return
   
     def handle_row(self, end_condition):      def handle_row(self, end_condition):
Line 414  class xml_handler: Line 441  class xml_handler:
             (saxtools.START_ELEMENT, fm_ns, u'COL'):              (saxtools.START_ELEMENT, fm_ns, u'COL'):
             self.handle_col,              self.handle_col,
             }              }
           if self.debug_data:
         self.logger.debug("START ROW")          self.logger.debug("START ROW")
         self.xml_data = {}          self.xml_data = {}
         self.colIdx = 0          self.colIdx = 0
Line 428  class xml_handler: Line 456  class xml_handler:
             yield None              yield None
                   
         #Element closed.  Wrap up          #Element closed.  Wrap up
           if self.debug_data:
         self.logger.debug("END ROW")          self.logger.debug("END ROW")
         self.rowcnt += 1          self.rowcnt += 1
         # process collected row data          # process collected row data
Line 436  class xml_handler: Line 465  class xml_handler:
         # synchronize by id_field          # synchronize by id_field
         if self.id_field:          if self.id_field:
             if self.id_type == 'integer':              if self.id_type == 'integer':
                   try:
                 id_val = int(self.xml_data[self.xml_id])                  id_val = int(self.xml_data[self.xml_id])
                   except:
                       pass
             else:              else:
                 id_val = self.xml_data[self.xml_id]                  id_val = self.xml_data[self.xml_id]
                                   
               if not id_val:
                   # abort update
                   self.logger.error("ERROR: unable to sync! emtpy id in row %s"%self.rowcnt)
                   return
                   
             if id_val in self.dbIDs:              if id_val in self.dbIDs:
                 self.dbIDs[id_val] += 1                  self.dbIDs[id_val] += 1
                 update=True                  update=True
Line 454  class xml_handler: Line 491  class xml_handler:
             f = self.xml_field_map[fn]              f = self.xml_field_map[fn]
             val = self.xml_data[fn]              val = self.xml_data[fn]
             type = self.sql_fields[f.getName()].getType()              type = self.sql_fields[f.getName()].getType()
             if type == "date" and len(val) == 0:               if type == "date" and len(val.strip()) == 0: 
                 # empty date field                  # empty date field
                 val = None                  val = None
                                   
Line 468  class xml_handler: Line 505  class xml_handler:
             # update existing row (by id_field)              # update existing row (by id_field)
             if self.read_before_update:              if self.read_before_update:
                 # read data                  # read data
                   if self.debug_data:
                 self.logger.debug("update check: %s = %s"%(id_val, args))                  self.logger.debug("update check: %s = %s"%(id_val, args))
                 oldrow = SimpleSearch(self.db, self.selQuery, [id_val], ascii=self.ascii_db)                  oldrow = SimpleSearch(self.db, self.selQuery, [id_val], ascii=self.ascii_db)
                 #i = 0                  #i = 0
Line 476  class xml_handler: Line 514  class xml_handler:
                 #    i += 1                  #    i += 1
                 if tuple(oldrow[0]) != tuple(args):                  if tuple(oldrow[0]) != tuple(args):
                     # data has changed -- update                      # data has changed -- update
                       if self.debug_data:
                     self.logger.debug("really update: %s = %s"%(id_val, args))                      self.logger.debug("really update: %s = %s"%(id_val, args))
                     args.append(id_val) # last arg is id                      args.append(id_val) # last arg is id
                     SimpleSearch(self.db, self.updQuery, args, ascii=self.ascii_db)                      SimpleSearch(self.db, self.updQuery, args, ascii=self.ascii_db)
                                           
             else:              else:
                 # always update                  # always update
                   if self.debug_data:
                 self.logger.debug("update: %s = %s"%(id_val, args))                  self.logger.debug("update: %s = %s"%(id_val, args))
                 args.append(id_val) # last arg is id                  args.append(id_val) # last arg is id
                 SimpleSearch(self.db, self.updQuery, args, ascii=self.ascii_db)                  SimpleSearch(self.db, self.updQuery, args, ascii=self.ascii_db)
   
         else:          else:
             # create new row              # create new row
               if self.debug_data:
             self.logger.debug("insert: %s"%args)              self.logger.debug("insert: %s"%args)
             SimpleSearch(self.db, self.addQuery, args, ascii=self.ascii_db)              SimpleSearch(self.db, self.addQuery, args, ascii=self.ascii_db)
   
Line 618  if __name__ == "__main__": Line 659  if __name__ == "__main__":
     opars.add_option("-d", "--debug", default=False, action="store_true",       opars.add_option("-d", "--debug", default=False, action="store_true", 
                      dest="debug",                        dest="debug", 
                      help="debug mode (more output)")                       help="debug mode (more output)")
       opars.add_option("--debug-data", default=False, action="store_true", 
                        dest="debug_data", 
                        help="debug mode for data (even more output)")
           
     (options, args) = opars.parse_args()      (options, args) = opars.parse_args()
           

Removed from v.1.27  
changed lines
  Added in v.1.33


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>