#!/usr/bin/env python2.2

import re
import sys

class mysql_var_def:
  def __init__( self, vname, vdef ):
    self.errors = []
    self.name   = vname
    if len(vdef) > 0 and vdef[-1:] == ',':
      vdef = vdef[:-1]
    self.vdef   = vdef

  def dump( self ):
    print "    TVAR: %s ['%s']" % (self.name, self.vdef)

  def __eq__( self, other ):
    self.errors = []
    if self.name == other.name:
      if self.vdef == other.vdef:
        return 1
      else:
        self.errors.append( '    DUMP 1: "%s"' % (self.vdef)  )
        self.errors.append( '    DUMP 2: "%s"' % (other.vdef) )
    else:
      self.errors.append( "YOUR CODE IS BUGGY: FIELDNAMES DIFFER: <<<%s>>> => <<<%s>>>" % (self.name, other.name))
    return 0


class mysql_table:
  def __init__( self, title, titleoptions ):
    self.errors = []
    self.title = title
    self.options = ''
    self.titleoptions = titleoptions
    self.vardefs = {}
    self.primary_key = ''

  def __eq__( self, other ):
    # compare title, options and titleoptions
    # next is primary key
    # next is var defs
    self.errors = []

    if not (self.title == other.title):
      self.errors.append( "  YOUR CODE IS BUGGY: TABLENAMES DIFFER: '%s' => '%s'" % (self.title, other.title))
    else:
      if not (self.options == other.options):
        self.errors.append( "  TABLE OPTIONS DIFFER: '%s' => '%s'" % (self.options, other.options ) )
      if not (self.titleoptions == other.titleoptions):
        self.errors.append( "  TABLE TITLE OPTIONS DIFFER: '%s' => '%s'" % (self.titleoptions, other.titleoptions ) )
      if not (self.primary_key == other.primary_key):
        self.errors.append( "  PRIMARY KEYS DIFFER: '%s' => '%s'" % (self.primary_key, other.primary_key ) )

      # compare fields:
      my_keys = self.vardefs.keys()
      my_keys.sort()
      ot_keys = other.vardefs.keys()
      ot_keys.sort()
      if not (my_keys == ot_keys):
        self.errors.append( "  IN LIST OF FIELD NAMES:" )

      # complicated way to get a list of all field names:
      all_keys1 = {}
      for k in my_keys:
        all_keys1[ k ] = 1
      for k in ot_keys:
        all_keys1[ k ] = 1
      all_keys = all_keys1.keys()
      all_keys.sort()
      

      for k in all_keys:
        if not self.vardefs.has_key( k ):
          self.errors.append( "  MISSING IN DATABASE #1: '%s.%s'" % (self.title, k) )
        else:
          if not other.vardefs.has_key( k ):
            self.errors.append( "  MISSING IN DATABASE #2: '%s.%s'" % (other.title, k) )
          else:
            # compare field definition:
            if not (self.vardefs[k] == other.vardefs[k]):
              self.errors.append("  DIFFERENT FIELD DEFINITIONS FOR '%s.%s':" % (self.title, k))
              self.errors.extend( self.vardefs[k].errors )

    if len(self.errors) == 0:
      return 1
    return 0

  def close( self, opts ):
    self.options = opts

  def newVar( self, name, value ):
    mvd = mysql_var_def( name, value )
    self.vardefs[ mvd.name ] = mvd

  def dump( self ):
    print "  DUMPING TABLE %s [%s] [%s]:" % (self.title,self.titleoptions,self.options)
    print "  PRIMARY KEY:", self.primary_key
    for k in self.vardefs.keys():
      self.vardefs[ k ].dump()
    print "  EOTD"

# ----------------------------------------------------------

class mysql_database:
  def __init__( self, dumpname ):
    self.dumpname = dumpname
    self.tables = {}
    self.errors = []
    current_table = None
    self.re_create_table = re.compile("^CREATE TABLE (\w+) (.*)$")
    self.re_var_def      = re.compile("^\s+(\w+) (.*)$")
    self.re_close_table  = re.compile("^\) (.*)$" )
    self.re_primary_key  = re.compile("^\s+PRIMARY KEY\s+\(([^\)]+).*$")
    in_create = 0
    f = open( dumpname, 'r' )
    for line in f:
      line = line.rstrip()
      if in_create:
        g = self.re_close_table.search( line )
        if g:
          current_table.close( g.group(1) )
          self.tables[ current_table.title ] = current_table
          in_create = 0
        else:

          i = self.re_primary_key.search( line )
          if i:
            current_table.primary_key = i.group(1)
          else:
            h = self.re_var_def.search( line )
            if h:
              current_table.newVar( h.group(1), h.group(2) )

      else:
        g = self.re_create_table.search( line )
        if g:
          current_table = mysql_table( g.group(1), g.group(2) )
          in_create = 1
    f.close()

  def dump( self ):
    print "DUMPING DATABASE (read from file '%s')" % (self.dumpname)
    for k in self.tables.keys():
      self.tables[k].dump()


  def __eq__( self, other ):
    L = self.tables.keys()
    L.extend( other.tables.keys() )
    d = {}
    for ele in L:
      d[ele] = 1
    all_table_names = d.keys()
    all_table_names.sort()

    self.errors = []
    for tname in all_table_names:
      if not self.tables.has_key( tname ):
        self.errors.append("\nDATABASE '%s' HAS NO TABLE '%s'" % (self.dumpname, tname))
      else:
        if not other.tables.has_key( tname ):
          self.errors.append("\nDATABASE '%s' HAS NO TABLE '%s'" % (other.dumpname, tname))
        else:
          t1 = self.tables[tname]
          t2 = other.tables[tname]
          if not (t1 == t2):
            self.errors.append( "\nTABLE '%s':" % (tname) )
            self.errors.extend( t1.errors )

    if len(self.errors) > 0:
      return 0
    return 1
    
    
# -------------------------------------------------------

class mysql_table_comparer:
  def __init__( self, filename1, filename2 ):
    self.databases = []
    self.databases.append( mysql_database( filename1 ) )
    self.databases.append( mysql_database( filename2 ) )
    
  def dump( self ):
    for db in self.databases:
      db.dump()


  def compare( self ):
    if self.databases[0] == self.databases[1]:
      print "EQUAL! :-)"
    else:
      for err in self.databases[0].errors:
        print err
      
      
if __name__ == "__main__":
   argc = len( sys.argv ) - 1
   if argc != 2:
     print "\n Usage: %s %s %s\n" % (sys.argv[0], 'mysqldump1', 'mysqldump2')
   else:
     mtc = mysql_table_comparer( sys.argv[1], sys.argv[2] )
     # mtc.dump()
     mtc.compare()
     print
   

