# HG changeset patch # User catherine@dellzilla # Date 1235696986 18000 # Node ID 7f999b141fcdadc986829ff21ba176af36365499 # Parent 8e5f58d504d4a63150d99e29afebbda657f954fe debugging streamlined wild sql diff -r 8e5f58d504d4 -r 7f999b141fcd sqlpython/sqlpyPlus.py --- a/sqlpython/sqlpyPlus.py Thu Feb 26 19:01:22 2009 -0500 +++ b/sqlpython/sqlpyPlus.py Thu Feb 26 20:09:46 2009 -0500 @@ -498,67 +498,58 @@ columnlistPattern = pyparsing.SkipTo(pyparsing.CaselessKeyword('from'))('columns') + \ pyparsing.SkipTo(pyparsing.stringEnd)('remainder') - negator = pyparsing.Optional('!')('exclude') - colNumber = negator + pyparsing.Literal('*') + pyparsing.Word('-' + pyparsing.nums, pyparsing.nums)('column_number') + negator = pyparsing.Literal('!')('exclude') + colNumber = pyparsing.Optional(negator) + pyparsing.Literal('*') + pyparsing.Word('-' + pyparsing.nums, pyparsing.nums)('column_number') colName = negator + pyparsing.Word('$_#' + pyparsing.alphas, '$_#' + pyparsing.alphanums)('standard_word') - wildColName = negator + pyparsing.Word('*$_#' + pyparsing.alphas, '*$_#' + pyparsing.alphanums)('wildcard_word') + wildColName = pyparsing.Optional(negator) + pyparsing.Word('*$_#' + pyparsing.alphas, '*$_#' + pyparsing.alphanums, min=2)('wildcard_word') wildSqlParser = colNumber ^ colName ^ wildColName wildSqlParser.ignore(pyparsing.cStyleComment).ignore(Parser.comment_def). \ - ignore(pyparsing.sglQuotedString).ignore(pyparsing.dblQuotedString) + ignore(pyparsing.sglQuotedString).ignore(pyparsing.dblQuotedString) + emptyCommaRegex = re.compile(',\s*,', re.DOTALL) + deadStarterCommaRegex = re.compile('^\s*,', re.DOTALL) + deadEnderCommaRegex = re.compile(',\s*$', re.DOTALL) def expandWildSql(self, arg): try: columnlist = self.columnlistPattern.parseString(arg) except pyparsing.ParseException: return arg - notcolnums = list(self.wildSqlNotColnum.scanString(arg)) - colnums = list(self.wildSqlColnum.scanString(arg)) - colnames = [cn for cn in self.wildColNamePattern.scanString(arg) if '*' in cn[0][0]] - if not (colnums or colnames or notcolnums): - return arg + parseresults = list(self.wildSqlParser.scanString(columnlist.columns)) + if not parseresults: + return arg self.curs.execute('select * ' + columnlist.remainder, self.varsUsed) - columns_available = [d[0] for d in self.curs.description] + columns_available = [d[0] for d in self.curs.description] replacers = {} - alreadyincluded = [] - alreadyexcluded = [] - for colnum in notcolnums: - colindex = int(colnum[0].column_number) - if colindex > 0: - exclude = columns_available[colindex-1] - else: - exclude = columns_available[colindex] - alreadyexcluded.append(exclude) - columns_to_add = [c for c in columns_available if c not in alreadyexcluded and c not in alreadyincluded] - alreadyincluded.extend(columns_to_add) - substval = ', '.join(columns_to_add) - substkey = arg[colnum[1]:colnum[2]] - replacers[substkey] = columns_to_add - for (k, cols) in replacers.items(): - replacers[k] = [col for col in cols if col not in alreadyexcluded] - for colnum in colnums: - colindex = int(colnum[0].column_number) - if colindex > 0: - substval = columns_available[colindex-1] - else: - substval = columns_available[colindex] - substkey = arg[colnum[1]:colnum[2]] - replacers[substkey] = substval - for colname in colnames: - substvals = [] - target = colname[0][0] - target = target.replace('*', '.*') - for col in columns_available: - if re.match(target, col, flags=re.IGNORECASE): - substvals.append(col) - if substvals: - replacers[colname[0][0]] = ', '.join(substvals) + included = set() + excluded = set() + for (col, startpos, endpos) in parseresults: + if col.column_number: + idx = int(col.column_number) + if idx > 0: + idx -= 1 + colname = columns_available[idx] + if col.exclude: + included.discard(colname) + include_here = columns_available[:] + include_here.remove(colname) + replacers[arg[startpos:endpos]] = include_here + excluded.add(colname) + else: + included.add(colname) + excluded.discard(colname) + replacers[arg[startpos:endpos]] = colname + replacers = sorted(replacers.items(), key=len, reverse=True) - replacers.reverse() result = columnlist.columns - for (k, v) in replacers: - if v: - result = result.replace(k, v) # could be confused by wildcards inside comments, strings - else: - result = result.replace(k, '') # no good - adjacent columns result + for (target, replacement) in replacers: + if isinstance(replacement, list): + cols = [r for r in replacement if r not in excluded and r not in included] + replacement = ', '.join(cols) + included.update(cols) + result = result.replace(target, replacement) + # some column names could get wiped out completely - fix their dangling commas + result = self.emptyCommaRegex.sub(',', result) + result = self.deadStarterCommaRegex.sub('', result) + result = self.deadEnderCommaRegex.sub('', result) return result + columnlist.remainder rowlimitPattern = pyparsing.Word(pyparsing.nums)('rowlimit')