Compare commits

...
Sign in to create a new pull request.

7 commits

393
sql.py
View file

@ -1,172 +1,261 @@
#!/usr/bin/env python2.4 #!/usr/bin/python3
import cx_Oracle
import sys
import os import os
import sys
import sqlalchemy
import readline
import traceback import traceback
try:
import readline
except ImportError:
pass
if len(sys.argv) < 2:
connstr = raw_input('Connect string: ')
else:
connstr = sys.argv[1]
def softpad(s, l, padchar = " "): def softpad(s, l, padchar=" "):
padding = padchar * l padding = padchar * l
if len(s) >= l: if len(s) >= l:
return s + padchar return s + padchar
return (s + padding)[:l] return (s + padding)[:l]
def pad(s, l, padchar = " "):
padding = padchar * l
return (s + padding)[:l] def pad(s, l, padchar=" "):
padding = padchar * l
return (s + padding)[:l]
rowbuffer = None rowbuffer = None
def execute_cmdline_query(v):
global rowbuffer
rowbuffer = None
try:
v = v.rstrip(';')
cur.execute(v)
print_row()
except:
try:
c2 = db.cursor()
c2.execute(
"SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE 1 IS NULL")
except:
print("Database connection lost!")
sys.exit(1)
traceback.print_exc()
sys.stdout.write('\n')
def print_row(): def print_row():
global rowbuffer global rowbuffer, cur, db
if not cur or not cur.description: if not cur or not cur.description:
return False return False
try: try:
page = int(opts['page']) page = int(opts['page'])
colhdrs = [x[0] for x in cur.description] colhdrs = [x[0] for x in cur.description]
allcols = [] allcols = []
lens = [] lens = []
for i in range(len(colhdrs)): for i in range(len(colhdrs)):
l = min(len(colhdrs[i]), 10) l = min(len(colhdrs[i]), 10)
lens.append(l) lens.append(l)
if rowbuffer: if rowbuffer:
rowbuffer = [repr(x) for x in rowbuffer] rowbuffer = [repr(x) for x in rowbuffer]
allcols = [rowbuffer] allcols = [rowbuffer]
for i in range(len(rowbuffer)): for i in range(len(rowbuffer)):
l = len(rowbuffer[i]) l = len(rowbuffer[i])
if i > len(lens): if i > len(lens):
print lens print(lens)
print rowbuffer print(rowbuffer)
if l > lens[i]: if l > lens[i]:
lens[i] = l lens[i] = l
rowbuffer = None rowbuffer = None
while len(allcols) < page: while len(allcols) < page:
cols = cur.fetchone() cols = cur.fetchone()
if not cols: if not cols:
break break
cols = [repr(x) for x in cols] cols = [repr(x) for x in cols]
allcols.append(cols) allcols.append(cols)
for i in range(len(cols)): for i in range(len(cols)):
l = len(cols[i]) l = len(cols[i])
if l > lens[i]: if l > lens[i]:
lens[i] = l lens[i] = l
if not allcols: if not allcols:
return False return False
for i in range(len(colhdrs)): for i in range(len(colhdrs)):
colhdrs[i] = pad(colhdrs[i], lens[i]) colhdrs[i] = pad(colhdrs[i], lens[i])
for i in range(len(allcols)): for i in range(len(allcols)):
cols = allcols[i] cols = allcols[i]
for j in range(len(cols)): for j in range(len(cols)):
cols[j] = pad(cols[j], lens[j]) cols[j] = pad(cols[j], lens[j])
colhdrrow = ' | '.join(colhdrs) colhdrrow = ' | '.join(colhdrs)
seprow = '-' * len(colhdrrow) seprow = '-' * len(colhdrrow)
print colhdrrow print(colhdrrow)
print seprow print(seprow)
for cols in allcols: for cols in allcols:
colsrow = ' | '.join(cols) colsrow = ' | '.join(cols)
print colsrow print(colsrow)
rowbuffer = cur.fetchone()
if rowbuffer:
print(" ( more ) ")
return True
except:
traceback.print_exc()
return False
rowbuffer = cur.fetchone()
if rowbuffer:
print " ( more ) "
return True
except:
traceback.print_exc()
return False
db = cx_Oracle.connect(connstr)
cur = db.cursor()
opts = { opts = {
'page': '20', 'page': '20',
'hide_null_tablespace': '1', 'hide_null_tablespace': '1',
'hide_tablespaces': 'SYSTEM;SYSAUX;SDE;SPATIAL_DATA' 'hide_tablespaces': 'SYSTEM;SYSAUX;SDE;SPATIAL_DATA'
} }
connstr = ""
if os.path.exists('settings.ini'):
try:
from cecil.core import inifile
config = inifile.inifile('settings.ini')
connstr = config['settings']['db']
except None:
pass
cmdline_query = None
if not connstr:
if len(sys.argv) < 2:
if not connstr:
connstr = input('Connect string: ')
else:
connstr = sys.argv[-1]
elif len(sys.argv) > 1:
cmdline_query = sys.argv[-1]
e = sqlalchemy.create_engine(connstr)
pool = e.connect()
db = pool.connection
cur = db.cursor()
c2 = db.cursor()
if cmdline_query != None:
execute_cmdline_query(cmdline_query)
db.commit()
sys.exit(0)
do_quit = False do_quit = False
while True: while True:
try: try:
v = raw_input('# ') v = input('# ')
except EOFError: except EOFError:
do_quit = True do_quit = True
if do_quit: if do_quit:
break break
v = v.strip() v = v.strip()
vl = v.lower() vl = v.lower()
if vl == 'quit' or vl == 'exit': if vl == 'quit' or vl == 'exit':
break break
elif vl == 'commit': elif vl == 'commit':
db.commit() db.commit()
elif vl == 'rollback': elif vl == 'rollback':
db.rollback() db.rollback()
elif vl == 'tables': elif vl[:4] == 'copy' or vl[:5] == 'copyi':
rowbuffer = None vs = v.split(' ')
conds = ["tablespace_name != '%s'" % (x,) for x in opts['hide_tablespaces'].split(';')] try:
if opts['hide_null_tablespace'][0:1] in ('1', 'Y', 'y', 'T', 't'): configsrc = inifile.inifile(vs[1])
conds += ['tablespace_name is not null'] connstrsrc = configsrc['settings']['db']
conds = ' and '.join(conds) esrc = sqlalchemy.create_engine(connstrsrc)
if conds: poolsrc = e.connect()
conds = ' where ' + conds dbsrc = pool.connection
cur.execute("select table_name, tablespace_name from all_tables %s" % (conds,)) cursrc = db.cursor()
print_row()
elif vl[:5] == 'exec ': c2 = db.cursor()
cmd = v[5:] #c2.execute("select * from %s where 1 is null" % (vs[2],))
try: cursrc.execute("select * from %s" % (vs[2],))
exec cmd colnames = []
except: dstart = 1
traceback.print_exc() if vs[0] == "copyi":
elif vl[:5] == 'cols ': dstart = 0
rowbuffer = None for coldata in cursrc.description[dstart:]:
vs = v.split(' ') colnames.append(coldata[0])
c2 = db.cursor() rowload = 0
try: rowerror = 0
c2.execute("select * from %s where 1 is null" % (vs[1],)) for r in cursrc:
for coldata in c2.description: try:
print "%s%s" % (softpad(coldata[0], 40), coldata[1]) colnamesql = ", ".join(colnames)
except cx_Oracle.DatabaseError, e: colmarks = ", ".join("%s" for cn in colnames)
sys.stdout.write(str(e)) srcq = "insert into %s (%s) values (%s)" % (vs[2], colnamesql, colmarks)
elif vl[:4] == 'set ': print(srcq)
vs = v[4:] print(r[0])
vi = vs.find('=') print(r[1])
vn = vs[:vi] print(r[2])
vv = vs[vi+1:] print(len(r))
opts[vn] = vv c2.execute(srcq, tuple(r[dstart:]))
elif vl == '': except:
print_row() traceback.print_exc()
elif vl == 'help': rowerror += 1
print """ print(f"Rows loaded {rowload}, errors {rowerror}")
except:
traceback.print_exc()
elif vl == 'tables':
rowbuffer = None
cur.execute("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES")
print_row()
elif vl[:7] == 'tables ':
v2 = v[7:]
rowbuffer = None
cur.execute("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE %s" % (v2,))
print_row()
elif vl[:5] == 'cols ':
rowbuffer = None
vs = v.split(' ')
c2 = db.cursor()
try:
c2.execute("select * from %s where 1 is null" % (vs[1],))
for coldata in c2.description:
typedata = coldata[1]
try:
import pytds.tds_base
tdlist = []
for x in dir(pytds.tds_base):
if getattr(pytds.tds_base, x) == typedata:
tdlist.append(x)
if tdlist:
tdlist2 = [x.replace("NTYPE", "").replace(
"TYPE", "") for x in tdlist if "TYPE" in x]
if tdlist2:
tdlist = tdlist2
if tdlist:
tdlist.sort()
tdlist.sort(key=len)
typedata = " ".join(tdlist)
except:
pass
print("%s%s" % (softpad(coldata[0], 40), typedata))
except:
traceback.print_exc()
sys.stdout.write('\n')
elif vl[:4] == 'set ':
vs = v[4:]
vi = vs.find('=')
vn = vs[:vi]
vv = vs[vi+1:]
opts[vn] = vv
elif vl == '':
print_row()
elif vl == 'help':
print("""
commands: commands:
tables lists tables tables lists tables
cols <table> lists columns of table cols <table> lists columns of table
commit commits any pending updates or inserts commit commits any pending updates or inserts
rollback aborts and pending updates or inserts rollback aborts and pending updates or inserts
help displays this help set <key>=<val> sets internal options, like "set page=40" to page at 40 rows
quit exits sql.py help displays this help
""" copy <path> <tbl> reads the config from <path> connects to that database and copies the contents of <tbl>
quit exits sql.py
<empty line> next page if there are (MORE) pages, just hit "ENTER"
<anything else> executes SQL query on the server
""")
else:
execute_cmdline_query(v)
else:
rowbuffer = None
try:
v = v.rstrip(';')
cur.execute(v)
print_row()
except cx_Oracle.DatabaseError, e:
try:
cur.execute("SELECT 1 FROM DUAL")
except cx_Oracle.DatabaseError:
print "Database connection lost!"
sys.exit(1)
sys.stdout.write(str(e))
print ""