comparison sqlpyPlus.py @ 3:cd23cd62de3c

history working pretty well
author devlinjs@FA7CZA6N1254998.wrightpatterson.afmc.ds.af.mil
date Mon, 03 Dec 2007 16:43:43 -0500
parents 59903dcaf327
children 23c3a58d7804
comparison
equal deleted inserted replaced
2:59903dcaf327 3:cd23cd62de3c
259 except KeyError: 259 except KeyError:
260 if not givenBindVars.has_key(varname): 260 if not givenBindVars.has_key(varname):
261 print 'Bind variable %s not defined.' % (varname) 261 print 'Bind variable %s not defined.' % (varname)
262 return result 262 return result
263 263
264 class HistoryItem(str):
265 def __init__(self, instr):
266 str.__init__(self, instr)
267 self.lowercase = self.lower()
268 self.idx = None
269 def pr(self):
270 print '-------------------------[%d]' % (self.idx)
271 print self
272
273 class History(list):
274 def append(self, new):
275 new = HistoryItem(new)
276 list.append(self, new)
277 new.idx = len(self)
278 def extend(self, new):
279 for n in new:
280 self.append(n)
281 def get(self, getme):
282 try:
283 idx = int(getme)
284 try:
285 return [self[idx-1]]
286 except IndexError:
287 return []
288 except ValueError: # search for a string
289 try:
290 getme = getme.strip()
291 except:
292 print "Don't know how to handle %s." % (str(getme))
293 return
294 if getme.startswith(r'/') and getme.endswith(r'/'):
295 finder = re.compile(getme[1:-1], re.DOTALL | re.MULTILINE | re.IGNORECASE)
296 def isin(hi):
297 return finder.search(hi)
298 else:
299 def isin(hi):
300 return (getme.lower() in hi.lowercase)
301 return [itm for itm in self[:-1] if isin(itm)]
302
264 class sqlpyPlus(sqlpython.sqlpython): 303 class sqlpyPlus(sqlpython.sqlpython):
265 def __init__(self): 304 def __init__(self):
266 sqlpython.sqlpython.__init__(self) 305 sqlpython.sqlpython.__init__(self)
267 self.binds = CaselessDict() 306 self.binds = CaselessDict()
268 self.sqlBuffer = [] 307 self.sqlBuffer = []
269 self.history = [] 308 self.history = History()
270 self.settable = ['maxtselctrows', 'maxfetch', 'autobind', 'failover', 'timeout'] # settables must be lowercase 309 self.settable = ['maxtselctrows', 'maxfetch', 'autobind', 'failover', 'timeout'] # settables must be lowercase
271 self.stdoutBeforeSpool = sys.stdout 310 self.stdoutBeforeSpool = sys.stdout
272 self.spoolFile = None 311 self.spoolFile = None
273 self.autobind = False 312 self.autobind = False
274 self.failover = False 313 self.failover = False
326 args = line.split(None,1) 365 args = line.split(None,1)
327 args[0] = args[0].lower() 366 args[0] = args[0].lower()
328 statement = ' '.join(args) 367 statement = ' '.join(args)
329 if args[0] in self.singleline: 368 if args[0] in self.singleline:
330 statement = sqlpython.finishStatement(statement) 369 statement = sqlpython.finishStatement(statement)
370 self.history.append(statement)
331 return statement 371 return statement
332 except Exception: 372 except Exception:
333 return line 373 return line
334 374
335 def do_shortcuts(self,arg): 375 def do_shortcuts(self,arg):
609 self.write(query, fnames[n]) 649 self.write(query, fnames[n])
610 diffMergeSearcher.invoke(fnames[0], fnames[1]) 650 diffMergeSearcher.invoke(fnames[0], fnames[1])
611 651
612 bufferPosPattern = re.compile('\d+') 652 bufferPosPattern = re.compile('\d+')
613 rangeIndicators = ('-',':') 653 rangeIndicators = ('-',':')
614 def bufferPositions(self, arg): 654
615 if not self.sqlBuffer: 655 def last_matching_command(self, arg):
616 return []
617 arg = arg.strip(self.terminator)
618 arg = arg.strip()
619 if not arg: 656 if not arg:
620 return [0] 657 return self.history[-2]
621 arg = arg.strip().lower() 658 else:
622 if arg in ('*', 'all', '-', ':'): 659 history = self.history.get(arg)
623 return range(len(self.sqlBuffer)) 660 if history:
624 661 return history[-1]
625 edges = [e for e in self.bufferPosPattern.findall(arg)] 662 return None
626 edges = [int(e) for e in edges] 663
627 if len(edges) > 1:
628 edges = edges[:2]
629 else:
630 if arg[0] in self.rangeIndicators or arg[-1] in self.rangeIndicators:
631 edges.append(0)
632 edges.sort()
633 start = max(edges[0], 0)
634 end = min(edges[-1], len(self.sqlBuffer)-1)
635 return range(start, end+1)
636 def do_run(self, arg): 664 def do_run(self, arg):
637 'run [N]: runs the SQL that was run N commands ago' 665 """run [arg]: re-runs an earlier command
638 for pos in self.bufferPositions(arg): 666
639 self.onecmd(self.sqlBuffer[-1-pos]) 667 no arg -> run most recent command
668 arg is integer -> run one history item, by index
669 arg is string -> run most recent command by string search
670 arg is /enclosed in forward-slashes/ -> run most recent by regex
671 """
672 'run [N]: runs the SQL that was run N commands ago'
673 runme = self.last_matching_command(arg)
674 print runme
675 self.onecmd(runme)
676 do_r = do_run
640 def do_history(self, arg): 677 def do_history(self, arg):
641 for (i, itm) in enumerate(self.history): 678 """history [arg]: lists past commands issued
642 print '-------------------------[%d]' % (i+1) 679
643 print itm 680 no arg -> list all
681 arg is integer -> list one history item, by index
682 arg is string -> string search
683 arg is /enclosed in forward-slashes/ -> regular expression search
684 """
685 if arg:
686 history = self.history.get(arg)
687 else:
688 history = self.history
689 for hi in history:
690 hi.pr()
644 def do_list(self, arg): 691 def do_list(self, arg):
645 'list [N]: lists the SQL that was run N commands ago' 692 """list: lists single most recent command issued"""
646 for pos in self.bufferPositions(arg): 693 self.last_matching_command(None).pr()
647 print '*** %i statements ago ***' % pos 694 do_hi = do_history
648 print self.sqlBuffer[-1-pos] 695 do_l = do_list
649 def load(self, fname): 696 def load(self, fname):
650 """Pulls command(s) into sql buffer. Returns number of commands loaded.""" 697 """Pulls command(s) into sql buffer. Returns number of commands loaded."""
651 initialLength = len(self.sqlBuffer)
652 try: 698 try:
653 f = open(fname, 'r') 699 f = open(fname, 'r')
654 except IOError, e: 700 except IOError, e:
655 try: 701 try:
656 f = open('%s.sql' % fname, 'r') 702 f = open('%s.sql' % fname, 'r')
657 except: 703 except:
658 print 'Problem opening file %s: \n%s' % (fname, e) 704 print 'Problem opening file %s: \n%s' % (fname, e)
659 return 0 705 return 0
660 txt = f.read() 706 txt = f.read()
661 f.close() 707 f.close()
662 self.sqlBuffer.extend(commandSeparator.separate(txt)) 708 result = commandSeparator.separate(txt)
663 return len(self.sqlBuffer) - initialLength 709 self.history.extend(result)
710 return len(result)
664 def do_ed(self, arg): 711 def do_ed(self, arg):
665 'ed [N]: brings up SQL from N commands ago in text editor, and puts result in SQL buffer.' 712 'ed [N]: brings up SQL from N commands ago in text editor, and puts result in SQL buffer.'
666 fname = 'mysqlpy_temp.sql' 713 fname = 'sqlpython_temp.sql'
667 try: 714 buffer = self.last_matching_command(arg)
668 buffer = self.sqlBuffer[-1 - (int(arg or 0))]
669 except IndexError:
670 buffer = ''
671 f = open(fname, 'w') 715 f = open(fname, 'w')
672 f.write(buffer) 716 f.write(buffer)
673 f.close() 717 f.close()
674 editSearcher.invoke(fname) 718 editSearcher.invoke(fname)
675 self.load(fname) 719 self.load(fname)
679 commandsLoaded = self.load(fname) 723 commandsLoaded = self.load(fname)
680 if commandsLoaded: 724 if commandsLoaded:
681 self.do_list('1-%d' % (commandsLoaded-1)) 725 self.do_list('1-%d' % (commandsLoaded-1))
682 def do_getrun(self, fname): 726 def do_getrun(self, fname):
683 'Brings SQL commands from a file to the in-memory SQL buffer, and executes them.' 727 'Brings SQL commands from a file to the in-memory SQL buffer, and executes them.'
684 commandNums = range(self.load(fname)) 728 newCommands = self.load(fname) * -1
685 commandNums.reverse() 729 if newCommands:
686 for commandNum in commandNums: 730 for command in self.history[newCommands:]:
687 self.do_run(str(commandNum)) 731 self.onecmd(command)
688 self.sqlBuffer.pop()
689 def do_psql(self, arg): 732 def do_psql(self, arg):
690 '''Shortcut commands emulating psql's backslash commands. 733 '''Shortcut commands emulating psql's backslash commands.
691 734
692 \c connect 735 \c connect
693 \d desc 736 \d desc
714 self.onecmd('q') 757 self.onecmd('q')
715 except KeyError: 758 except KeyError:
716 print 'psql command \%s not yet supported.' % abbrev 759 print 'psql command \%s not yet supported.' % abbrev
717 def do_save(self, fname): 760 def do_save(self, fname):
718 'save FILENAME: Saves most recent SQL command to disk.' 761 'save FILENAME: Saves most recent SQL command to disk.'
719 f = open(fname, 'w') 762 try:
720 f.write(self.sqlBuffer[-1]) 763 f = open(fname, 'w')
721 f.close() 764 f.write(self.sqlBuffer[-1])
765 f.close()
766 except Exception, e:
767 print 'Error saving %s: %s' % (fname, str(e))
722 768
723 def do_print(self, arg): 769 def do_print(self, arg):
724 'print VARNAME: Show current value of bind variable VARNAME.' 770 'print VARNAME: Show current value of bind variable VARNAME.'
725 if arg: 771 if arg:
726 if arg[0] == ':': 772 if arg[0] == ':':