2c8595098c
git-svn-id: http://google-refine.googlecode.com/svn/trunk@883 7d457c2a-affb-35e4-300a-418c747d4874
238 lines
7.0 KiB
Python
238 lines
7.0 KiB
Python
# $Id: isql.py 6639 2009-08-10 17:06:51Z fwierzbicki $
|
|
|
|
import dbexts, cmd, sys, os
|
|
|
|
"""
|
|
Isql works in conjunction with dbexts to provide an interactive environment
|
|
for database work.
|
|
"""
|
|
|
|
__version__ = "$Revision: 6639 $"[11:-2]
|
|
|
|
class IsqlExit(Exception): pass
|
|
|
|
class Prompt:
|
|
"""
|
|
This class fixes a problem with the cmd.Cmd class since it uses an ivar 'prompt'
|
|
as opposed to a method 'prompt()'. To get around this, this class is plugged in
|
|
as a 'prompt' attribute and when invoked the '__str__' method is called which
|
|
figures out the appropriate prompt to display. I still think, even though this
|
|
is clever, the attribute version of 'prompt' is poor design.
|
|
"""
|
|
def __init__(self, isql):
|
|
self.isql = isql
|
|
def __str__(self):
|
|
prompt = "%s> " % (self.isql.db.dbname)
|
|
if len(self.isql.sqlbuffer) > 0:
|
|
prompt = "... "
|
|
return prompt
|
|
if os.name == 'java':
|
|
def __tojava__(self, cls):
|
|
import java.lang.String
|
|
if cls == java.lang.String:
|
|
return self.__str__()
|
|
return False
|
|
|
|
class IsqlCmd(cmd.Cmd):
|
|
|
|
def __init__(self, db=None, delimiter=";", comment=('#', '--')):
|
|
cmd.Cmd.__init__(self, completekey=None)
|
|
if db is None or type(db) == type(""):
|
|
self.db = dbexts.dbexts(db)
|
|
else:
|
|
self.db = db
|
|
self.kw = {}
|
|
self.sqlbuffer = []
|
|
self.comment = comment
|
|
self.delimiter = delimiter
|
|
self.prompt = Prompt(self)
|
|
|
|
def parseline(self, line):
|
|
command, arg, line = cmd.Cmd.parseline(self, line)
|
|
if command and command <> "EOF":
|
|
command = command.lower()
|
|
return command, arg, line
|
|
|
|
def do_which(self, arg):
|
|
"""\nPrints the current db connection parameters.\n"""
|
|
print self.db
|
|
return False
|
|
|
|
def do_EOF(self, arg):
|
|
return False
|
|
|
|
def do_p(self, arg):
|
|
"""\nExecute a python expression.\n"""
|
|
try:
|
|
exec arg.strip() in globals()
|
|
except:
|
|
print sys.exc_info()[1]
|
|
return False
|
|
|
|
def do_column(self, arg):
|
|
"""\nInstructions for column display.\n"""
|
|
return False
|
|
|
|
def do_use(self, arg):
|
|
"""\nUse a new database connection.\n"""
|
|
# this allows custom dbexts
|
|
self.db = self.db.__class__(arg.strip())
|
|
return False
|
|
|
|
def do_table(self, arg):
|
|
"""\nPrints table meta-data. If no table name, prints all tables.\n"""
|
|
if len(arg.strip()):
|
|
self.db.table(arg, **self.kw)
|
|
else:
|
|
self.db.table(None, **self.kw)
|
|
return False
|
|
|
|
def do_proc(self, arg):
|
|
"""\nPrints store procedure meta-data.\n"""
|
|
if len(arg.strip()):
|
|
self.db.proc(arg, **self.kw)
|
|
else:
|
|
self.db.proc(None, **self.kw)
|
|
return False
|
|
|
|
def do_schema(self, arg):
|
|
"""\nPrints schema information.\n"""
|
|
print
|
|
self.db.schema(arg)
|
|
print
|
|
return False
|
|
|
|
def do_delimiter(self, arg):
|
|
"""\nChange the delimiter.\n"""
|
|
delimiter = arg.strip()
|
|
if len(delimiter) > 0:
|
|
self.delimiter = delimiter
|
|
|
|
def do_o(self, arg):
|
|
"""\nSet the output.\n"""
|
|
if not arg:
|
|
fp = self.db.out
|
|
try:
|
|
if fp:
|
|
fp.close()
|
|
finally:
|
|
self.db.out = None
|
|
else:
|
|
fp = open(arg, "w")
|
|
self.db.out = fp
|
|
|
|
def do_q(self, arg):
|
|
"""\nQuit.\n"""
|
|
try:
|
|
if self.db.out:
|
|
self.db.out.close()
|
|
finally:
|
|
return True
|
|
|
|
def do_set(self, arg):
|
|
"""\nSet a parameter. Some examples:\n set owner = 'informix'\n set types = ['VIEW', 'TABLE']\nThe right hand side is evaluated using `eval()`\n"""
|
|
if len(arg.strip()) == 0:
|
|
items = self.kw.items()
|
|
if len(items):
|
|
print
|
|
# format the results but don't include how many rows affected
|
|
for a in dbexts.console(items, ("key", "value"))[:-1]:
|
|
print a
|
|
print
|
|
return False
|
|
d = filter(lambda x: len(x) > 0, map(lambda x: x.strip(), arg.split("=")))
|
|
if len(d) == 1:
|
|
if self.kw.has_key(d[0]):
|
|
del self.kw[d[0]]
|
|
else:
|
|
self.kw[d[0]] = eval(d[1])
|
|
|
|
def do_i(self, arg):
|
|
fp = open(arg)
|
|
try:
|
|
print
|
|
for line in fp.readlines():
|
|
line = self.precmd(line)
|
|
stop = self.onecmd(line)
|
|
stop = self.postcmd(stop, line)
|
|
finally:
|
|
fp.close()
|
|
return False
|
|
|
|
def default(self, arg):
|
|
try:
|
|
token = arg.strip()
|
|
if not token:
|
|
return False
|
|
comment = [token.startswith(x) for x in self.comment]
|
|
if reduce(lambda x,y: x or y, comment):
|
|
return False
|
|
if token[0] == '\\':
|
|
token = token[1:]
|
|
# is it possible the line contains the delimiter
|
|
if len(token) >= len(self.delimiter):
|
|
# does the line end with the delimiter
|
|
if token[-1 * len(self.delimiter):] == self.delimiter:
|
|
# now add all up to the delimiter
|
|
self.sqlbuffer.append(token[:-1 * len(self.delimiter)])
|
|
if self.sqlbuffer:
|
|
q = " ".join(self.sqlbuffer)
|
|
print q
|
|
self.db.isql(q, **self.kw)
|
|
self.sqlbuffer = []
|
|
if self.db.updatecount:
|
|
print
|
|
if self.db.updatecount == 1:
|
|
print "1 row affected"
|
|
else:
|
|
print "%d rows affected" % (self.db.updatecount)
|
|
print
|
|
return False
|
|
if token:
|
|
self.sqlbuffer.append(token)
|
|
except:
|
|
self.sqlbuffer = []
|
|
print
|
|
print sys.exc_info()[1]
|
|
print
|
|
return False
|
|
|
|
def emptyline(self):
|
|
return False
|
|
|
|
def postloop(self):
|
|
raise IsqlExit()
|
|
|
|
def cmdloop(self, intro=None):
|
|
while 1:
|
|
try:
|
|
cmd.Cmd.cmdloop(self, intro)
|
|
except IsqlExit, e:
|
|
break
|
|
except Exception, e:
|
|
print
|
|
print e
|
|
print
|
|
intro = None
|
|
|
|
if __name__ == '__main__':
|
|
import getopt
|
|
|
|
try:
|
|
opts, args = getopt.getopt(sys.argv[1:], "b:", [])
|
|
except getopt.error, msg:
|
|
print
|
|
print msg
|
|
print "Try `%s --help` for more information." % (sys.argv[0])
|
|
sys.exit(0)
|
|
|
|
dbname = None
|
|
for opt, arg in opts:
|
|
if opt == '-b':
|
|
dbname = arg
|
|
|
|
intro = "\nisql - interactive sql (%s)\n" % (__version__)
|
|
|
|
isql = IsqlCmd(dbname)
|
|
isql.cmdloop()
|