diff --git a/sql.py b/sql.py index 54fe907..465e3e6 100755 --- a/sql.py +++ b/sql.py @@ -7,97 +7,123 @@ import readline import traceback +def softpad(s, l, padchar=" "): + padding = padchar * l + if len(s) >= l: + return s + padchar + return (s + padding)[:l] -def softpad(s, l, padchar = " "): - padding = padchar * l - if len(s) >= l: - return s + padchar - 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 + + +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(): - global rowbuffer, cur, db - if not cur or not cur.description: - return False - try: - page = int(opts['page']) - colhdrs = [x[0] for x in cur.description] - allcols = [] - lens = [] - for i in range(len(colhdrs)): - l = min(len(colhdrs[i]), 10) - lens.append(l) - if rowbuffer: - rowbuffer = [repr(x) for x in rowbuffer] - allcols = [rowbuffer] - for i in range(len(rowbuffer)): - l = len(rowbuffer[i]) - if i > len(lens): - print(lens) - print(rowbuffer) - if l > lens[i]: - lens[i] = l - rowbuffer = None - while len(allcols) < page: - cols = cur.fetchone() - if not cols: - break - cols = [repr(x) for x in cols] - allcols.append(cols) - for i in range(len(cols)): - l = len(cols[i]) - if l > lens[i]: - lens[i] = l - if not allcols: - return False - for i in range(len(colhdrs)): - colhdrs[i] = pad(colhdrs[i], lens[i]) + global rowbuffer, cur, db + if not cur or not cur.description: + return False + try: + page = int(opts['page']) + colhdrs = [x[0] for x in cur.description] + allcols = [] + lens = [] + for i in range(len(colhdrs)): + l = min(len(colhdrs[i]), 10) + lens.append(l) + if rowbuffer: + rowbuffer = [repr(x) for x in rowbuffer] + allcols = [rowbuffer] + for i in range(len(rowbuffer)): + l = len(rowbuffer[i]) + if i > len(lens): + print(lens) + print(rowbuffer) + if l > lens[i]: + lens[i] = l + rowbuffer = None + while len(allcols) < page: + cols = cur.fetchone() + if not cols: + break + cols = [repr(x) for x in cols] + allcols.append(cols) + for i in range(len(cols)): + l = len(cols[i]) + if l > lens[i]: + lens[i] = l + if not allcols: + return False + for i in range(len(colhdrs)): + colhdrs[i] = pad(colhdrs[i], lens[i]) - for i in range(len(allcols)): - cols = allcols[i] - for j in range(len(cols)): - cols[j] = pad(cols[j], lens[j]) + for i in range(len(allcols)): + cols = allcols[i] + for j in range(len(cols)): + cols[j] = pad(cols[j], lens[j]) - colhdrrow = ' | '.join(colhdrs) - seprow = '-' * len(colhdrrow) - print(colhdrrow) - print(seprow) - for cols in allcols: - colsrow = ' | '.join(cols) - print(colsrow) + colhdrrow = ' | '.join(colhdrs) + seprow = '-' * len(colhdrrow) + print(colhdrrow) + print(seprow) + for cols in allcols: + colsrow = ' | '.join(cols) + 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 opts = { - 'page': '20', - 'hide_null_tablespace': '1', - 'hide_tablespaces': 'SYSTEM;SYSAUX;SDE;SPATIAL_DATA' + 'page': '20', + 'hide_null_tablespace': '1', + 'hide_tablespaces': 'SYSTEM;SYSAUX;SDE;SPATIAL_DATA' } + connstr = "" -if len(sys.argv) < 2: - if os.path.exists('settings.ini'): - try: - from cecil.core import inifile - config = inifile.inifile('settings.ini') - connstr = config['settings']['db'] - except: - pass - - if not connstr: - connstr = input('Connect string: ') -else: - connstr = sys.argv[1] +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() @@ -105,69 +131,131 @@ 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 while True: - try: - v = input('# ') - except EOFError: - do_quit = True + try: + v = input('# ') + except EOFError: + do_quit = True - if do_quit: - break - v = v.strip() - vl = v.lower() + if do_quit: + break + v = v.strip() + vl = v.lower() - if vl == 'quit' or vl == 'exit': - break - elif vl == 'commit': - db.commit() - elif vl == 'rollback': - db.rollback() - elif vl == 'tables': - rowbuffer = None - cur.execute("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES") - 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: - print("%s%s" % (softpad(coldata[0], 40), coldata[1])) - except: + if vl == 'quit' or vl == 'exit': + break + elif vl == 'commit': + db.commit() + elif vl == 'rollback': + db.rollback() + elif vl[:4] == 'copy' or vl[:5] == 'copyi': + vs = v.split(' ') + try: + configsrc = inifile.inifile(vs[1]) + connstrsrc = configsrc['settings']['db'] + esrc = sqlalchemy.create_engine(connstrsrc) + poolsrc = e.connect() + dbsrc = pool.connection + cursrc = db.cursor() + + c2 = db.cursor() + #c2.execute("select * from %s where 1 is null" % (vs[2],)) + cursrc.execute("select * from %s" % (vs[2],)) + colnames = [] + dstart = 1 + if vs[0] == "copyi": + dstart = 0 + for coldata in cursrc.description[dstart:]: + colnames.append(coldata[0]) + rowload = 0 + rowerror = 0 + for r in cursrc: + try: + colnamesql = ", ".join(colnames) + colmarks = ", ".join("%s" for cn in colnames) + srcq = "insert into %s (%s) values (%s)" % (vs[2], colnamesql, colmarks) + print(srcq) + print(r[0]) + print(r[1]) + print(r[2]) + print(len(r)) + c2.execute(srcq, tuple(r[dstart:])) + except: + traceback.print_exc() + rowerror += 1 + 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(""" + 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: - tables lists tables - cols