00001 import os
00002 from dbconf import DBConf
00003
00004
00005 class CommandLine(dict):
00006 """
00007 Base class for composing and invoking command lines in a separate process
00008 """
00009 def _exepath(self):
00010 for cmd in self._exenames:
00011 which = os.popen("which %s" % cmd).read().rstrip("\n")
00012 if os.path.exists(which):
00013 return which
00014 return None
00015 exepath = property( _exepath )
00016 cmd = property( lambda self:self._cmd % self )
00017 cmd_nopw = property( lambda self:self._cmd % dict(self, password="***") )
00018
00019 def __init__(self, *args, **kwa ):
00020 dict.__init__(self, *args, **kwa )
00021 exe = self.exepath
00022 assert exe, "cannot find executable %r check your PATH " % self._exenames
00023 self.update( exepath=exe, path="/dev/null", argline="" )
00024
00025 def __str__(self):
00026 return "%s %s " % (self.__class__.__name__, self.cmd_nopw )
00027
00028 def __call__(self, verbose=False):
00029 if verbose:
00030 print self
00031 return os.popen(self.cmd).read()
00032
00033
00034 class MySQLLoad(CommandLine):
00035 """
00036 Wrapper around sql loading commandline that hooks up to the
00037 config parameters from the :file:`~/.my.cnf`
00038 """
00039 _exenames = ['mysql','mysql5']
00040 _cmd = "cat %(path)s | %(exepath)s --no-defaults --host=%(host)s --user=%(user)s --password=%(password)s %(database)s "
00041
00042 def __call__(self, path, verbose=True ):
00043 """Arguments are used to update the tables list and dumppath """
00044 assert os.path.exists(path), "MySQLLoad ERROR no mysqldump file at %s " % path
00045 assert self['database'].startswith('tmp_'), "MySQLLoad error invalid database name %r " % self
00046 self.update( path=path )
00047 return CommandLine.__call__(self, verbose=verbose)
00048
00049
00050 class MySQLDumpT(CommandLine):
00051 """
00052 Try the mysqldump -T/tmp option
00053 the specified directory must exist and be writable
00054
00055 surprised to find that this worked ...with G connected to C
00056 and writing into /tmp on G
00057
00058 """
00059 _exenames = ['mysqldump','mysqldump5']
00060 _cmd = "time %(exepath)s --no-defaults --skip-opt --host=%(host)s --user=%(user)s --password=%(password)s -T%(tdir)s %(database)s "
00061
00062 def __call__(self, tdir, verbose=True ):
00063 """Arguments are used to update the tables list and dumppath """
00064 self.update( tdir=tdir )
00065 return CommandLine.__call__(self, verbose=verbose)
00066
00067
00068 class MySQLImport(CommandLine):
00069 """
00070 http://dev.mysql.com/doc/refman/5.0/en/mysqlimport.html
00071
00072 `no-defaults` must be the first option
00073 `local` option needed, otherwise mysqlimport: Error: Can't get stat of ...
00074 the table must be pre-existing, otherwise 'tmp_offline_db.SimPmtSpecVld' doesn't exist, when using table: SimPmtSpecVld
00075
00076 a bad import leads to NULLified rows
00077 0 0000-00-00 00:00:00 0000-00-00 00:00:00 NULL NULL NULL NULL NULL 0000-00-00 00:00:00 0000-00-00 00:00:00
00078
00079 """
00080 _exenames = ['mysqlimport','mysqlimport5']
00081 _cmd = '%(exepath)s --no-defaults --local --host=%(host)s --user=%(user)s --password=%(password)s --fields-optionally-enclosed-by="\\"" --fields-terminated-by=, --ignore-lines=1 %(database)s %(tabfile)s '
00082 def __call__(self, tabfile , verbose=True ):
00083 self.update(tabfile=tabfile )
00084 return CommandLine.__call__(self, verbose=verbose)
00085
00086
00087 class MySQLDump(CommandLine):
00088 """
00089 Wrapper around a mysqldump command line that integrates
00090 config parameters from the :file:`~/.my.cnf` with table list and
00091 dumppath call arguments.
00092
00093 For background on mysqldump see http://dev.mysql.com/doc/refman/5.0/en/mysqldump.html
00094
00095 Options used with the mysqldump command includes `--no-defaults` which
00096 ensures the command is fully controlled by this script and does not depend on
00097 users defaults. Also the `--skip-opt` is used to avoid an error when used by
00098 with mysql identities without LOCK TABLES privilege::
00099
00100 mysqldump: Got error: 1044: Access denied for user 'dayabay'@'%' to database 'offline_db' when doing LOCK TABLES
00101
00102 """
00103 _exenames = ['mysqldump','mysqldump5']
00104 _cmd = "time %(exepath)s --no-defaults --skip-opt --host=%(host)s --user=%(user)s --password=%(password)s %(database)s %(argline)s > %(path)s "
00105
00106 def __call__(self, tables, dumppath , verbose=True ):
00107 """Arguments are used to update the tables list and dumppath """
00108 self.update( argline=" ".join(tables), path=dumppath )
00109 return CommandLine.__call__(self, verbose=verbose)
00110
00111
00112
00113 if __name__ == '__main__':
00114 cnf = DBConf("tmp_offline_db")
00115 imp = MySQLImport(cnf)
00116
00117 tmpd = "/tmp"
00118
00119 imp( tabfile=os.path.join(tmpd, "rdumpcat/SimPmtSpec/SimPmtSpecVld.csv") , verbose=True )
00120