Mercurial > sqlpython
changeset 490:2d1235fe1252
most oracle refactors done
author | catherine.devlin@gmail.com |
---|---|
date | Tue, 07 Sep 2010 03:01:41 -0400 |
parents | 79bb13962a15 |
children | d30471cc95ac |
files | sqlpython/connections.py sqlpython/sqlpyPlus.py |
diffstat | 2 files changed, 93 insertions(+), 106 deletions(-) [+] |
line wrap: on
line diff
--- a/sqlpython/connections.py Tue Sep 07 01:18:45 2010 -0400 +++ b/sqlpython/connections.py Tue Sep 07 03:01:41 2010 -0400 @@ -196,16 +196,19 @@ result = {'owner': '%', 'type': '%', 'name': '%'} result.update(dict(self.ls_parser.parseString(identifier))) return result + def comparison_operator(self, target): + if ('%' in target) or ('_' in target): + operator = 'LIKE' + else: + operator = '=' + return operator def objects(self, target, opts): identifier = self.parse_identifier(target) clauses = [] if (identifier['owner'] == '%') and (not opts.all): identifier['owner'] = self.username for col in ('owner', 'type', 'name'): - if ('%' in identifier[col]) or ('_' in identifier[col]): - operator = 'LIKE' - else: - operator = '=' + operator = self.comparison_operator(identifier[col]) clause = '%s %s' % (operator, self.bindSyntax(col)) clauses.append(clause) if hasattr(opts, 'reverse') and opts.reverse: @@ -214,9 +217,30 @@ sort_direction = 'ASC' clauses.append(sort_direction) qry = self.all_object_qry % tuple(clauses) - identifier = self.bindVariables(identifier) - result = self.connection.cursor().execute(qry, self.bindVariables(identifier)) + binds = (('owner', identifier['owner']), ('type', identifier['type']), ('name', identifier['name'])) + result = self.connection.cursor().execute(qry, self.bindVariables(binds)) return result + def columns(self, target, opts): + if opts.all: + owner = '%' + else: + owner = self.username + qry = self.column_qry % (self.comparison_operator(owner), self.bindSyntax('owner'), + self.comparison_operator(target), self.bindSyntax('colname')) + binds = (('owner', owner), ('colname', target)) + result = self.connection.cursor().execute(qry, self.bindVariables(binds)) + return result + def source(self, target, opts): + if opts.all: + owner = '%' + else: + owner = self.username + qry = self.source_qry % (self.comparison_operator(owner), self.bindSyntax('owner'), + self.bindSyntax('target')) + binds = (('owner', owner), ('target', target)) + result = self.connection.cursor().execute(qry, self.bindVariables(binds)) + return result + gerald_types = {'TABLE': gerald.oracle_schema.Table, 'VIEW': gerald.oracle_schema.View} def object_metadata(self, owner, object_type, name): @@ -257,12 +281,23 @@ port = self.port, sql_mode = 'ANSI') def bindSyntax(self, varname): return '%s' - def bindVariables(self, identifier): - return (identifier['owner'], identifier['type'], identifier['name']) + def bindVariables(self, binds): + 'Puts a tuple of (name, value) pairs into the bind format desired by MySQL' + return (i[1] for i in binds) + column_qry = """SELECT atc.owner, ao.object_type, atc.table_name, atc.column_name + FROM all_tab_columns atc + JOIN all_objects ao ON (atc.table_name = ao.object_name AND atc.owner = ao.owner) + WHERE owner %s %s + AND column_name %s %s """ + source_qry = """SELECT owner, type, name, line, text + FROM all_source + WHERE owner %s %s + AND UPPER(text) LIKE %s""" class PostgresInstance(DatabaseInstance): rdbms = 'postgres' default_port = 5432 + case = str.lower def set_defaults(self): self.port = os.getenv('PGPORT') or self.default_port self.database = os.getenv('ORACLE_SID') @@ -273,9 +308,10 @@ password = self.password, database = self.database, port = self.port) def bindSyntax(self, varname): - return '%%(%s)s' % varname.lower() - def bindVariables(self, identifier): - return identifier + return '%%(%s)s' % varname + def bindVariables(self, binds): + 'Puts a tuple of (name, value) pairs into the bind format desired by psycopg2' + return dict((b[0], b[1].lower()) for b in binds) all_object_qry = """SELECT table_schema, table_type, table_name FROM ( SELECT table_schema, table_type, table_name @@ -283,16 +319,25 @@ UNION ALL SELECT table_schema, 'view', table_name FROM information_schema.views ) - WHERE ( (table_schema %s) OR (table_schema = 'PUBLIC') ) + WHERE ( (table_schema %s) OR (table_schema = 'public') ) AND table_type %s AND table_name %s ORDER BY table_schema, table_type, table_name %s""" - + column_qry = """SELECT table_schema, object_type, table_name, column_name + FROM information_schema.columns + WHERE ( (table_schema %s %s) OR (table_schema = 'public')) + AND column_name %s %s """ + source_qry = """SELECT owner, type, name, line, text + FROM all_source + WHERE owner %s %s + AND UPPER(text) LIKE %s""" + class OracleInstance(DatabaseInstance): rdbms = 'oracle' default_port = 1521 connection_parser = re.compile('(?P<username>[^/\s@]*)(/(?P<password>[^/\s@]*))?(@((?P<hostname>[^/\s:]*)(:(?P<port>\d{1,4}))?/)?(?P<database>[^/\s:]*))?(\s+as\s+(?P<mode>sys(dba|oper)))?', re.IGNORECASE) + case = str.upper def uri(self): if self.hostname: uri = '%s://%s:%s@%s:%s/%s' % (self.rdbms, self.username, self.password, @@ -329,12 +374,20 @@ AND object_type %s AND object_name %s ORDER BY owner, object_type, object_name %s""" + column_qry = """SELECT atc.owner, ao.object_type, atc.table_name, atc.column_name + FROM all_tab_columns atc + JOIN all_objects ao ON (atc.table_name = ao.object_name AND atc.owner = ao.owner) + WHERE atc.owner %s %s + AND atc.column_name %s %s """ + source_qry = """SELECT owner, type, name, line, text + FROM all_source + WHERE owner %s %s + AND UPPER(text) LIKE %s""" def bindSyntax(self, varname): return ':' + varname - def bindVariables(self, identifier): - return {'owner': identifier['owner'].upper(), - 'type': identifier['type'].upper(), - 'name': identifier['name'].upper()} + def bindVariables(self, binds): + 'Puts a tuple of (name, value) pairs into the bind format desired by cx_Oracle' + return dict((b[0], b[1].upper()) for b in binds) if __name__ == '__main__': opts = OptionTestDummy(password='password')
--- a/sqlpython/sqlpyPlus.py Tue Sep 07 01:18:45 2010 -0400 +++ b/sqlpython/sqlpyPlus.py Tue Sep 07 03:01:41 2010 -0400 @@ -878,14 +878,6 @@ else: txt = 'REMARK BEGIN %s/%s/%s\n%s\nREMARK END\n' % (owner, object_type, name, txt) self.poutput(txt) - - - """if opts.full: - for dependent_type in ('constraints', 'triggers', 'indexes'): - if hasattr(description.dbobj, dependent_type): - for (depname, depobj) in getattr(description.dbobj, dependent_type).items(): - self.poutput('REMARK BEGIN\n%s\nREMARK END\n\n' % depobj.get_ddl()) - """ if opts.dump: self.stdout.close() statekeeper.restore() @@ -1018,26 +1010,13 @@ ]) def do_find(self, arg, opts): """Finds argument in source code or (with -c) in column definitions.""" - - seek = re.compile(self._regex_form_of_search_pattern(arg, exact=opts.col), - re.IGNORECASE) - qualified = opts.get('all') - for descrip in self._matching_database_objects('*', opts): - if opts.col: - if hasattr(descrip.dbobj, 'columns'): - for col in descrip.dbobj.columns: - if seek.search(col): - self.poutput('%s.%s' % (m.fullname, col)) - else: - if hasattr(descrip.dbobj, 'source'): - name_printed = False - for (line_num, line) in descrip.dbobj.source: - if seek.search(line): - if not name_printed: - self.poutput(descrip.fullname) - name_printed = True - self.poutput('%d: %s' % (line_num, line)) - + if opts.col: + for (owner, object_type, table_name, column_name) in self.current_instance.columns(arg, opts): + self.poutput('%s %s.%s.%s' % (object_type, owner, table_name, column_name)) + else: + for (owner, object_type, name, line_number, txt) in self.current_instance.source(arg, opts): + self.poutput('%s %s.%s %d: %s' % (object_type, owner, name, line_number, txt)) + def _col_type_descriptor(self, col): #if col['type'] in ('integer',): # return col['type'] @@ -1299,12 +1278,12 @@ def do__dir_(self, arg, opts, plural_name, str_function): long = opts.get('long') - reverse = opts.get('reverse') or False - for descrip in self._matching_database_objects(arg, opts): - if hasattr(descrip.dbobj, plural_name): - self.pfeedback('%s on %s' % (plural_name.title(), descrip.fullname)) - result = [str_function(depobj, long) for depobj in getattr(descrip.dbobj, plural_name).values()] - result.sort(reverse=opts.get('reverse') or False) + for (owner, object_type, name) in self.current_instance.objects(arg, opts): + obj = self.current_instance.object_metadata(owner, object_type, name) + if hasattr(obj, plural_name): + self.pfeedback('%s on %s' % (plural_name.title(), '%s %s.%s' % (object_type, owner, name))) + result = [str_function(depobj, long) for depobj in getattr(obj, plural_name).values()] + result.sort(reverse=bool(opts.reverse)) self.poutput('\n'.join(result)) @options(standard_options) @@ -1530,14 +1509,7 @@ 'WINDOW GROUP', 'XML SCHEMA') - def metadata(self): - username = self.current_instance.username - if self.rdbms == 'oracle': - username = username.upper() - elif self.rdbms == 'postgres': - username = username.lower() - return (username, self.current_instance.gerald) - + def _to_sql_wildcards(self, original): return original.replace('*','%').replace('?','_') #hmm... but these should be escape-able? @@ -1545,46 +1517,7 @@ def _to_re_wildcards(self, original): result = re.escape(original) return result.replace('\\*','.*').replace('\\?','.') - - def _regex_form_of_search_pattern(self, s, exact=False): - if not s: - return '^[^\.]*$' - s = s.replace('$','\$') # not re.escape(s) b/c ``?`` is valid in SQL and regex - if '.' in s: - seekpatt = r'[/\\]?%s[/\\]?' % ( - s.replace('*', '.*').replace('?','.').replace('%', '.*')) - else: - seekpatt = r'[/\\]?%s[/\\]?' % ( - s.replace('*', '[^\.]*').replace('?','[^\.]').replace('%', '[^\.]*')) - if exact: - seekpatt = '^%s$' % seekpatt - return seekpatt - def do_refresh(self, arg): - '''Refreshes metadata for the specified schema; only required - if table structures, etc. have changed.''' - if self.current_instance.gerald.complete and self.current_instance.gerald.current: - self.current_instance.discover_metadata() - else: - self.pfeedback('Metadata discovery is already underway.') - - def _print_gerald_status_warning(self, gerald_schema): - if not gerald_schema.complete: - self.pfeedback('Metadata is not available yet - still gathering') - elif not gerald_schema.current: - self.pfeedback('Metadata is stale - requested refresh still underway') - - def _matching_database_objects(self, arg, opts): - (username, gerald_schema) = self.metadata() - self._print_gerald_status_warning(gerald_schema) - if not gerald_schema.complete: - raise StopIteration - - seek = str(arg) and self._regex_form_of_search_pattern(arg, opts.get('exact')) - for (name, descrip) in gerald_schema.descriptions.items(): - if descrip.match_pattern(seek, specific_owner = ((not opts.all) and username)): - yield descrip - def _do_ls(self, arg, opts): 'Functional core of ``do_ls``, split out into an undecorated version to be callable from other methods' for row in self.current_instance.objects(arg, opts): @@ -1604,8 +1537,8 @@ def do_grep(self, arg, opts): """grep {target} {table} [{table2,...}] search for {target} in any of {table}'s fields""" + # TODO: permit regex arg = self.parsed(arg) - opts.exact = True args = arg.split() if len(args) < 2: self.perror(self.do_grep.__doc__) @@ -1620,18 +1553,19 @@ re_pattern = re.compile(self._to_re_wildcards(pattern), (opts.ignorecase and re.IGNORECASE) or 0) for target in targets: - for descrip in self._matching_database_objects(target, opts): - self.pfeedback(descrip.fullname) - if hasattr(descrip.dbobj, 'columns'): + for (owner, object_type, name) in self.current_instance.objects(target, opts): + obj = self.current_instance.object_metadata(owner, object_type, name) + self.pfeedback('%s %s.%s' % (object_type, owner, name)) + if hasattr(obj, 'columns'): clauses = [] - for col in descrip.dbobj.columns: + for col in obj.columns: clauses.append(comparitor % (col, sql_pattern)) - sql = "SELECT * FROM %s WHERE 1=0\n%s;" % (descrip.fullname, ' '.join(clauses)) + sql = "SELECT * FROM %s.%s WHERE 1=0\n%s;" % (owner, name, ' '.join(clauses)) sql = self.parsed(sql, terminator=arg.parsed.terminator or ';', suffix=arg.parsed.suffix) self.do_select(sql) - elif hasattr(descrip.dbobj, 'source'): - for (line_num, line) in descrip.dbobj.source: + elif hasattr(obj, 'source'): + for (line_num, line) in obj.source: if re_pattern.search(line): self.poutput('%4d: %s' % (line_num, line))