interactive-mining/interactive-mining-3rdparty.../madis/src/mterm.py

961 lines
30 KiB
Python
Executable File

#!/usr/bin/env python
import os
import sys
# Workaround for MAC utf-8 encoding
if sys.platform == 'darwin':
os.environ['LC_ALL']='en_US.UTF-8'
reload(sys)
sys.setdefaultencoding("utf-8")
# Workaround for windows - DISABLED
#try: import lib.winunicode
#except ImportError: pass
#else: del lib.winunicode
import functions
import re
import apsw
import traceback
import json
import math
import random
pipedinput=not sys.stdin.isatty()
errorexit = True
nobuf = False
if pipedinput:
# If we get piped input use dummy readline
readline=lambda x:x
readline.remove_history_item=lambda x:x
readline.read_history_file=lambda x:x
readline.write_history_file=lambda x:x
readline.set_completer=lambda x:x
readline.add_history=lambda x:x
readline.parse_and_bind=lambda x:x
readline.set_completer_delims=lambda x:x
else:
# Workaround for absence of a real readline module in win32
import lib.reimport
if sys.platform == 'win32':
import pyreadline as readline
else:
import readline
import datetime
import time
import locale
import os
from lib.dsv import writer
import csv
try:
if pipedinput:
raise 'go to except'
import lib.colorama as colorama
from colorama import Fore, Back, Style
colnums = True
except:
colorama=lambda x:x
def dummyfunction():
pass
colorama.deinit = colorama.init = dummyfunction
Fore = Style = Back = dummyfunction
Fore.RED = Style.BRIGHT = Style.RESET_ALL = ''
colnums = False
pass
DELIM = Fore.RED+Style.BRIGHT+'|'+Style.RESET_ALL
class mtermoutput(csv.Dialect):
def __init__(self):
self.delimiter='|'
if not allquote:
self.quotechar='|'
self.quoting=csv.QUOTE_MINIMAL
else:
self.quotechar='"'
self.quoting=csv.QUOTE_NONNUMERIC
self.escapechar="\\"
self.lineterminator='\n'
def createConnection(db):
try:
if 'SQLITE_OPEN_URI' in apsw.__dict__:
connection = functions.Connection(db, flags=apsw.SQLITE_OPEN_READWRITE | apsw.SQLITE_OPEN_CREATE | apsw.SQLITE_OPEN_URI)
else:
connection = functions.Connection(db)
functions.register(connection)
connection.enableloadextension(True)
except Exception, e:
exitwitherror(e)
# Change TEMP store to where the mterm is run from
try:
connection.cursor().execute("PRAGMA temp_store_directory='.';PRAGMA page_size=16384;PRAGMA default_cache_size=3000;")
# if pipedinput:
except:
pass
functions.settings['stacktrace'] = True
return connection
def reloadfunctions():
global connection, automatic_reload, db
if not automatic_reload:
return
modified=lib.reimport.modified()
if len(modified)==0 or (modified==['__main__']):
return
tmp_settings=functions.settings
tmp_vars=functions.variables
connection.close()
try:
lib.reimport.reimport(*[x for x in modified if x != '__main__'])
except ValueError:
pass
try:
lib.reimport.reimport('functionslocal')
except ValueError:
pass
connection = createConnection(db)
functions.settings=tmp_settings
functions.variables=tmp_vars
def raw_input_no_history(*args):
global pipedinput
if pipedinput:
try:
input = raw_input()
except EOFError:
connection.close()
exit(0)
return input
try:
input = raw_input(*args)
except:
return None
if input!='':
try:
readline.remove_history_item(readline.get_current_history_length()-1)
except:
pass
return input
def update_tablelist():
global alltables, alltablescompl, connection
alltables=[]
alltablescompl=[]
cursor = connection.cursor()
cexec=cursor.execute('PRAGMA database_list;')
for row in cexec:
cursor1 = connection.cursor()
if row[1]=='temp':
cexec1 = cursor1.execute("select name from sqlite_temp_master where type='table';")
else:
cexec1 = cursor1.execute("select name from "+row[1]+".sqlite_master where type='table';")
for row1 in cexec1:
tname=row1[0].lower().encode('ascii')
if row[1] in ('main', 'temp'):
alltables.append(tname)
alltablescompl.append(tname)
else:
dbtname=(row[1]+'.'+tname).lower().encode('ascii')
alltables.append(dbtname)
alltablescompl.append(dbtname)
if tname not in alltablescompl:
alltablescompl.append(tname)
cursor1.close()
cursor.close()
def get_table_cols(t):
global connection
if '.' in t:
ts=t.split('.')
dbname=ts[0]
tname='.'.join(ts[1:])
else:
dbname='main'
tname=t
cursor = connection.cursor()
if dbname=='main':
cexec=cursor.execute('pragma table_info('+str(tname)+')')
cols=[x[1] for x in cexec]
else:
cexec=cursor.execute('select * from '+str(tname))
cols=[x[0] for x in cursor.getdescriptionsafe()]
return cols
def sizeof_fmt(num, use_kibibyte=False):
base, infix = [(1000.,''),(1024.,'i')][use_kibibyte]
for x in ['','K%s'%infix,'M%s'%infix,'G%s'%infix]:
if num < base and num > -base:
if x == '':
return str(int(num))
else:
return "%3.1f%s" % (num, x)
num /= base
return "%3.1f %s" % (num, 'T%sB'%infix)
def approx_rowcount(t):
timer = time.time()
minrowid = list(connection.cursor().execute('select min(_rowid_) from ' + t, parse=False))[0][0]
maxrowid = list(connection.cursor().execute('select max(_rowid_) from ' + t, parse=False))[0][0]
if maxrowid is None or minrowid is None:
return 0
idrange = maxrowid - minrowid + 1
if (time.time() - timer) > 0.5:
return idrange
samplesize = min(int(math.sqrt(idrange)), 100)
if samplesize == 0:
return 0
step = idrange / samplesize
sample = range(random.randrange(0, step) + minrowid, maxrowid + 1, step)
samplesize = len(sample)
samplehits = 0
samplestep = 1
timer = time.time()
while sample != []:
samplehits += list(connection.cursor().execute(
'select count(*) from ' + t +
' where _rowid_ in (' + ','.join([str(x) for x in sample[:samplestep]]) + ');', parse=False))[0][0]
sample = sample[samplestep:]
samplestep *= 2
estimt = samplesize * (time.time() - timer) / (samplesize - len(sample))
if estimt > 0.5:
return idrange
return int(idrange * float(samplehits) / samplesize)
def update_cols_for_table(t):
global alltablescompl, colscompl, lastcols, connection, updated_tables
if t!='':
if t[-1]=='.':
t=t[0:-1]
if t[-2:]=='..':
t=t[0:-2]
if t in alltablescompl and t not in updated_tables:
try:
cols=get_table_cols(t)
updated_tables.add(t)
colscompl+= ['.'.join([ t, x ]) for x in cols]
colscompl+= [x for x in cols]
colscompl+=[t+'..']
except:
pass
try:
if '.' in t:
ts=t.split('.')
dbname=ts[0]
tname='.'.join(ts[1:])
else:
dbname='main'
tname=t
cursor = connection.cursor()
cexec=cursor.execute('select * from '+dbname+".sqlite_master where type='index' and tbl_name='"+str(tname)+"'")
icompl= [x[1] for x in cexec]
colscompl+= ['.'.join([ t, x ]) for x in icompl]
colscompl+= icompl
except:
pass
try:
colscompl=list(set(colscompl)-set(lastcols))
except:
pass
_update_cols_from_tables_last_text=''
def update_cols_from_tables_in_text(t):
global alltablescompl, _update_cols_from_tables_last_text
if t==_update_cols_from_tables_last_text:
return
_update_cols_from_tables_last_text=t
stablesreg='|'.join( (x.replace('$','\$').replace('.', '\.') for x in sorted(alltablescompl, key=len, reverse=True)) )
foundtables=re.findall(r'[^a-zA-Z0-9_$]('+stablesreg+r')[,.\s)]', t+u' ')
for i in foundtables:
update_cols_for_table(i)
def mcomplete(textin,state):
global number_of_kb_exceptions
number_of_kb_exceptions = 0
def normalizename(col):
if re.match(ur'\.*[\w_$\d.]+\s*$', col,re.UNICODE):
return col
else:
return "`"+col.lower()+"`"
def numberedlist(c):
maxcolchars=len(str(len(c)+1))
formatstring='{:'+'>'+str(maxcolchars)+'}'
o=[]
for num in xrange(len(c)):
o.append( formatstring.format(num+1)+'|'+c[num] )
return o
text=textin
#Complete \t to tabs
if text[-2:]=='\\t':
if state==0: return text[:-2]+'\t'
else: return
prefix=''
localtables=[]
completions=[]
linebuffer=readline.get_line_buffer()
beforecompl= linebuffer[0:readline.get_begidx()]
# Only complete '.xxx' completions when space chars exist before completion
if re.match(r'\s*$', beforecompl):
completions+=dotcompletions
# If at the start of the line, show all tables
if beforecompl=='' and text=='':
localtables=alltables[:]
# Check if all tables start with the same character
if localtables!=[]:
prefcharset=set( (x[0] for x in localtables) )
if len(prefcharset)==1:
localtables+=[' ']
completions=localtables
# If completion starts at a string boundary, complete from local dir
elif beforecompl!='' and beforecompl[-1] in ("'", '"'):
completions=os.listdir(os.getcwdu())
hits=[x for x in completions if x[:len(text)]==unicode(text)]
if state<len(hits):
return hits[state]
else: return
# Detect if in simplified 'from' or .schema
elif re.search(r'(?i)(from\s(?:\s*[\w\d._$]+(?:\s*,\s*))*(?:\s*[\w\d._$]+)?$)|(^\s*\.schema)|(^\s*\.t)|(^\s*\.tables)', beforecompl, re.DOTALL| re.UNICODE):
localtables=alltablescompl[:]
completions=localtables
else:
localtables=alltablescompl[:]
completions+=lastcols+colscompl
completions+=sqlandmtermstatements+allfuncs+localtables
hits= [x.lower() for x in completions if x.lower()[:len(text)]==unicode(text.lower())]
update_cols_from_tables_in_text(linebuffer)
if hits==[] and text.find('.')!=-1 and re.match(r'[\w\d._$]+', text):
tablename=re.match(r'(.+)\.', text).groups()[0].lower()
update_cols_for_table(tablename)
hits= [x.lower() for x in colscompl if x.lower()[:len(text)]==unicode(text.lower())]
# If completing something that looks like a table, complete only from cols
if hits==[] and text[-2:]!='..':
prepost=re.match(r'(.+\.)([^.]*)$', text)
if prepost:
prefix, text=prepost.groups()
hits= [x.lower() for x in lastcols+[y for y in colscompl if y.find('.')==-1] if x.lower()[:len(text)]==unicode(text.lower())]
# Complete table.number
if len(hits) == 0 and text.isdigit():
cols= get_table_cols(prefix[:-1])
colnum = int(text)
if 0 < colnum <= len(cols):
hits = [cols[colnum-1]]
elif colnum == 0:
hits = numberedlist(cols)
if state<len(hits):
return hits[state]
else: return
try:
# Complete from colnums
icol=int(text)
if len(hits)==0 and text.isdigit() and icol>=0:
# Show all tables when completing 0
if icol==0 and newcols!=[]:
if len(newcols)==1:
if state>0: return
return prefix+normalizename(newcols[0])
hits = numberedlist(newcols)
if state<len(hits):
return hits[state]
else: return
# Complete from last seen when completing for other number
if icol<=len(lastcols) and lastcols!=[] and state<1:
return prefix+normalizename(lastcols[icol-1])
except:
pass
if state<len(hits):
sqlstatem=set(sqlandmtermstatements)
altset=set(localtables)
if hits[state]=='..':
if text=='..' and lastcols!=[]:
return prefix+', '.join([normalizename(x) for x in lastcols])+' '
else:
return prefix+hits[state]
if hits[state] in sqlstatem:
return prefix+hits[state]
if hits[state] in colscompl:
if text[-2:]=='..':
tname=text[:-2]
try:
cols=get_table_cols(tname)
return prefix+', '.join(cols)+' '
except:
pass
if hits[state] in altset:
if text in altset:
update_cols_for_table(hits[state])
return prefix+hits[state]
else:
return prefix+normalizename(hits[state])
else:
return
def buildrawprinter(separator):
return writer(sys.stdout, dialect=mtermoutput(), delimiter=str(separator))
def schemaprint(cols):
global pipedinput
if pipedinput:
return
if cols!=[]:
sys.stdout.write(Style.BRIGHT+'--- '+Style.NORMAL+ Fore.RED+'['+Style.BRIGHT+'0'+Style.NORMAL+'|'+Style.RESET_ALL+Style.BRIGHT+'Column names '+'---'+Style.RESET_ALL+'\n')
colschars=0
i1=1
for i in cols:
colschars+=len(i)+len(str(i1))+3
i1+=1
if colschars<=80:
i1=1
for i in cols:
sys.stdout.write(Fore.RED+'['+Style.BRIGHT+str(i1)+Style.NORMAL+'|'+Style.RESET_ALL+i+' ')
i1+=1
sys.stdout.write('\n')
else:
totalchars=min(colschars/80 +1, 12) * 80
mincolchars=12
colschars=0
i1=1
for i in cols:
charspercolname=max((totalchars-colschars)/(len(cols)+1-i1)-5, mincolchars)
colschars+=min(len(i), charspercolname)+len(str(i1))+3
if len(i)>charspercolname and len(cols)>1:
i=i[0:charspercolname-1]+'..'
else:
i=i+' '
sys.stdout.write(Fore.RED+'['+Style.BRIGHT+str(i1)+Style.NORMAL+'|'+Style.RESET_ALL+i)
i1+=1
sys.stdout.write('\n')
def printrow(row):
global rawprinter, colnums
if not colnums:
rawprinter.writerow(row)
return
rowlen=len(row)
i1=1
for d in row:
if rowlen>3:
if i1==1:
sys.stdout.write(Fore.RED+Style.BRIGHT+'['+'1'+'|'+Style.RESET_ALL)
else:
sys.stdout.write(Fore.RED+'['+str(i1)+Style.BRIGHT+'|'+Style.RESET_ALL)
else:
if i1!=1:
sys.stdout.write(Fore.RED+Style.BRIGHT+'|'+Style.RESET_ALL)
if type(d) in (int, float, long):
d=str(d)
elif d is None:
d=Style.BRIGHT+'null'+Style.RESET_ALL
try:
sys.stdout.write(d)
except KeyboardInterrupt:
raise
except:
sys.stdout.write(d.encode('utf_8', 'replace'))
i1+=1
sys.stdout.write('\n')
def printterm(*args, **kwargs):
global pipedinput
msg=','.join([unicode(x) for x in args])
if not pipedinput:
print(msg)
def exitwitherror(*args):
msg=','.join([unicode(x) for x in args])
if errorexit:
print
sys.exit(msg)
else:
print(json.dumps({"error":msg}, separators=(',',':'), ensure_ascii=False).encode('utf_8', 'replace'))
print
sys.stdout.flush()
def process_args():
global connection, functions, errorexit, db, nobuf
args = sys.argv[1:]
# Continue on error when input is piped in
if len(args) >= 1 and pipedinput:
setargs = set(args)
if '-bailoff' in setargs or '-coe' in setargs:
try:
setargs.remove('-bailoff')
except KeyError:
pass
try:
setargs.remove('-coe')
except KeyError:
pass
errorexit = False
if '-nobuf' in setargs:
setargs.remove('-nobuf')
nobuf = True
args = list(setargs)
if len(args) >= 1:
db = args[-1]
if db == "-q":
db = ':memory:'
connection = createConnection(db)
if db == '' or db == ':memory':
functions.variables.execdb = None
else:
functions.variables.execdb = str(os.path.abspath(os.path.expandvars(os.path.expanduser(os.path.normcase(db)))))
# Found query in args
if len(args)>2:
st = ' '.join(args[2:])
st = st.decode(output_encoding)
c = connection.cursor()
try:
for r in c.execute(st):
rawprinter.writerow(r)
c.close()
except KeyboardInterrupt:
sys.exit()
finally:
try:
c.close()
except:
pass
sys.exit()
VERSION='1.0'
mtermdetails="mTerm - version "+VERSION
intromessage="""Enter ".help" for instructions
Enter SQL statements terminated with a ";" """
helpmessage=""".functions Lists all functions
.help Show this message (also accepts '.h' )
.help FUNCTION Show FUNCTION's help page
.quit Exit this program
.schema TABLE Show the CREATE statements
.quote Toggle between normal quoting mode and quoting all mode
.beep Make a sound when a query finishes executing
.tables List names of tables (you can also use ".t" or double TAB)
.t TABLE Browse table
.explain Explain query plan
.colnums Toggle showing column numbers
.separator SEP Change separator to SEP. For tabs use 'tsv' or '\\t' as SEP
Separator is used only when NOT using colnums
.vacuum Vacuum DB using a temp file in current path
.queryplan query Displays the queryplan of the query
Use: FILE or CLIPBOARD function for importing data
OUTPUT or CLIPOUT function for exporting data"""
if 'HOME' not in os.environ: # Windows systems
if 'HOMEDRIVE' in os.environ and 'HOMEPATH' in os.environ:
os.environ['HOME'] = os.path.join(os.environ['HOMEDRIVE'], os.environ['HOMEPATH'])
else:
os.environ['HOME'] = "C:\\"
histfile = os.path.join(os.environ["HOME"], ".mterm")
automatic_reload=False
if not pipedinput:
try:
readline.read_history_file(histfile)
except IOError:
pass
import atexit
atexit.register(readline.write_history_file, histfile)
automatic_reload=True
readline.set_completer(mcomplete)
readline.parse_and_bind("tab: complete")
readline.set_completer_delims(' \t\n`!@#$^&*()=+[{]}|;:\'",<>?')
separator = "|"
allquote = False
beeping = False
db = ""
language, output_encoding = locale.getdefaultlocale()
if output_encoding==None:
output_encoding='UTF8'
functions.variables.flowname='main'
rawprinter=buildrawprinter(separator)
process_args()
sqlandmtermstatements=['select ', 'create ', 'where ', 'table ', 'group by ', 'drop ', 'order by ', 'index ', 'from ', 'alter ', 'limit ', 'delete ', '..',
"attach database '", 'detach database ', 'distinct', 'exists ']
dotcompletions=['.help ', '.colnums', '.schema ', '.functions ', '.tables', '.explain ', '.vacuum', '.queryplan ']
allfuncs=functions.functions['vtable'].keys()+functions.functions['row'].keys()+functions.functions['aggregate'].keys()
alltables=[]
alltablescompl=[]
updated_tables=set()
update_tablelist()
lastcols=[]
newcols=[]
colscompl=[]
#Intro Message
if not pipedinput:
print mtermdetails
print "running on Python: "+'.'.join([str(x) for x in sys.version_info[0:3]])+', APSW: '+apsw.apswversion()+', SQLite: '+apsw.sqlitelibversion(),
try:
sys.stdout.write(", madIS: "+functions.VERSION+'\n')
except:
print
print intromessage
number_of_kb_exceptions=0
while True:
statement = raw_input_no_history("mterm> ")
if statement==None:
number_of_kb_exceptions+=1
print
if number_of_kb_exceptions<2:
continue
else:
readline.write_history_file(histfile)
break
#Skip comments
if statement.startswith('--'):
continue
number_of_kb_exceptions=0
statement=statement.decode(output_encoding)
#scan for commands
iscommand=re.match("\s*\.(?P<command>\w+)\s*(?P<argument>([\w\.]*))(?P<rest>.*)$", statement)
validcommand=False
queryplan = False
if iscommand:
validcommand=True
command=iscommand.group('command')
argument=iscommand.group('argument')
rest=iscommand.group('rest')
origstatement=statement
statement=None
if command=='separator':
tmpseparator=separator
if argument=='csv':
separator = ","
elif argument in ('tsv','\\t','\t'):
separator = "\t"
else:
separator = argument
if separator == '':
colnums = True
separator = '|'
if separator!=tmpseparator:
colnums = False
rawprinter=buildrawprinter(separator)
elif command=='explain':
statement=re.sub("^\s*\.explain\s+", "explain query plan ", origstatement)
elif command=='queryplan':
try:
statement = re.match(r"\s*\.queryplan\s+(.+)", origstatement).groups()[0]
queryplan = True
except IndexError:
pass
elif command=='quote':
allquote^=True
if allquote:
printterm("Quoting output, uncoloured columns")
colnums=False
else:
printterm("Not quoting output, coloured columns")
colnums=True
rawprinter=buildrawprinter(separator)
elif command=='beep':
beeping^=True
if beeping:
printterm("Beeping enabled")
else:
printterm("Beeping disabled")
elif command=='colnums':
colnums^=True
if colnums:
printterm("Colnums enabled")
else:
printterm("Colnums disabled")
elif 'tables'.startswith(command):
update_tablelist()
argument=argument.rstrip('; ')
if not argument:
maxtlen = 0
for i in sorted(alltables):
maxtlen = max(maxtlen, len(i))
maxtlen += 1
for i in sorted(alltables):
l = ('{:<' + str(maxtlen) + '}').format(i)
try:
l += DELIM + " cols:{:<4}".format(str(len(get_table_cols(i))))
except KeyboardInterrupt:
print
break
except:
pass
try:
l += DELIM + " ~rows:" + sizeof_fmt(approx_rowcount(i))
except KeyboardInterrupt:
print
break
except:
pass
printterm(l)
else:
statement = 'select * from '+argument+' limit 2;'
elif 'select'.startswith(command):
update_tablelist()
argument = argument.rstrip('; ')
if not argument:
for i in sorted(alltables):
printterm(i)
else:
statement = 'select * from '+argument + ';'
elif command=='vacuum':
statement="PRAGMA temp_store_directory = '.';VACUUM;PRAGMA temp_store_directory = '';"
elif command=='schema':
if not argument:
statement="select sql from (select * from sqlite_master union all select * from sqlite_temp_master) where sql is not null;"
else:
argument=argument.rstrip('; ')
update_tablelist()
if argument not in alltables:
printterm("No table found")
else:
db='main'
if '.' in argument:
sa=argument.split('.')
db=sa[0]
argument=''.join(sa[1:])
statement="select sql from (select * from "+db+".sqlite_master union all select * from sqlite_temp_master) where tbl_name like '%s' and sql is not null;" %(argument)
elif "quit".startswith(command):
connection.close()
exit(0)
elif command=="functions":
for ftype in functions.functions:
for f in functions.functions[ftype]:
printterm(f+' :'+ftype)
elif "help".startswith(command):
if not argument:
printterm(helpmessage)
else:
for i in functions.functions:
if argument in functions.functions[i]:
printterm("Function "+ argument + ":")
printterm(functions.mstr(functions.functions[i][argument].__doc__))
elif command=="autoreload":
automatic_reload=automatic_reload ^ True
printterm("Automatic reload is now: " + str(automatic_reload))
else:
validcommand=False
printterm("""unknown command. Enter ".help" for help""")
if validcommand:
histstatement='.'+command+' '+argument+rest
try:
readline.add_history(histstatement.encode('utf-8'))
except:
pass
if statement:
histstatement=statement
while not apsw.complete(statement):
more = raw_input_no_history(' ..> ')
if more==None:
statement=None
break
more=more.decode(output_encoding)
statement = statement + '\n'.decode(output_encoding) + more
histstatement=histstatement+' '+more
reloadfunctions()
number_of_kb_exceptions=0
if not statement:
printterm()
continue
try:
if not validcommand:
readline.add_history(histstatement.encode('utf-8'))
except:
pass
before = datetime.datetime.now()
try:
if queryplan:
cexec = connection.queryplan(statement)
desc = cexec.next()
else:
cursor = connection.cursor()
cexec = cursor.execute(statement)
try:
desc = cursor.getdescriptionsafe()
lastcols[0:len(desc)] = [x for x, y in desc]
except apsw.ExecutionCompleteError, e:
desc = []
newcols=[x for x,y in desc]
colorama.init()
rownum=0
if not pipedinput:
for row in cexec:
printrow(row)
rownum+=1
else:
print(json.dumps({"schema":desc}, separators=(',',':'), ensure_ascii=False).encode('utf_8', 'replace'))
for row in cexec:
print(json.dumps(row, separators=(',',':'), ensure_ascii=False).encode('utf_8', 'replace'))
if nobuf:
sys.stdout.flush()
print
sys.stdout.flush()
if not queryplan:
cursor.close()
after=datetime.datetime.now()
tmdiff=after-before
schemaprint(newcols)
if not pipedinput:
if rownum==0:
printterm( "Query executed in %s min. %s sec %s msec." %((int(tmdiff.days)*24*60+(int(tmdiff.seconds)/60),(int(tmdiff.seconds)%60),(int(tmdiff.microseconds)/1000))) )
else:
print "Query executed and displayed %s"%(rownum),
if rownum==1: print "row",
else: print "rows",
print "in %s min. %s sec %s msec." %((int(tmdiff.days)*24*60+(int(tmdiff.seconds)/60),(int(tmdiff.seconds)%60),(int(tmdiff.microseconds)/1000)))
if beeping:
printterm('\a\a')
colscompl=[]
updated_tables=set()
#Autoupdate in case of schema change
if re.search(r'(?i)(create|attach|drop)', statement):
update_tablelist()
except KeyboardInterrupt:
print
schemaprint(newcols)
printterm("KeyboardInterrupt exception: Query execution stopped", exit=True)
continue
except (apsw.SQLError, apsw.ConstraintError , functions.MadisError), e:
emsg=unicode(e)
if pipedinput:
exitwitherror(functions.mstr(emsg))
else:
try:
if u'Error:' in emsg:
emsgsplit=emsg.split(u':')
print Fore.RED+Style.BRIGHT+ emsgsplit[0] +u':'+Style.RESET_ALL+ u':'.join(emsgsplit[1:])
else:
print e
except:
print e
continue
except Exception, e:
trlines = []
for i in reversed(traceback.format_exc(limit=sys.getrecursionlimit()).splitlines()):
trlines.append(i)
if i.strip().startswith('File'):
break
msg=Fore.RED+Style.BRIGHT+"Unknown error:" + Style.RESET_ALL + "\nTraceback is:\n" + '\n'.join(reversed(trlines))
if pipedinput:
exitwitherror(functions.mstr(msg))
else:
print msg
finally:
colorama.deinit()
try:
cursor.close()
except:
#print "Not proper clean-up"
pass