diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2009-01-14 19:55:20 +0000 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2009-01-14 19:55:20 +0000 |
commit | 76a7818013b1803876da7f51ec1601a25cb1e78b (patch) | |
tree | efe808502f9e9c9a4d5a35fe92c6df6bf5609ab3 /lib/sqlalchemy/sql | |
parent | 4fad095858e218c1c53de3c1ce64fc438688f826 (diff) | |
download | sqlalchemy-76a7818013b1803876da7f51ec1601a25cb1e78b.tar.gz |
- Improved the methodology to handling percent signs in column
names from [ticket:1256]. Added more tests. MySQL and
Postgres dialects still do not issue correct CREATE TABLE
statements for identifiers with percent signs in them.
Diffstat (limited to 'lib/sqlalchemy/sql')
-rw-r--r-- | lib/sqlalchemy/sql/compiler.py | 10 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/expression.py | 22 |
2 files changed, 20 insertions, 12 deletions
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index d5c85d71d..8622aeea4 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -277,7 +277,10 @@ class DefaultCompiler(engine.Compiled): schema_prefix = self.preparer.quote(column.table.schema, column.table.quote_schema) + '.' else: schema_prefix = '' - return schema_prefix + self.preparer.quote(column.table.name % self.anon_map, column.table.quote) + "." + name + tablename = column.table.name + if isinstance(tablename, sql._generated_label): + tablename = tablename % self.anon_map + return schema_prefix + self.preparer.quote(tablename, column.table.quote) + "." + name def escape_literal_column(self, text): """provide escaping for the literal_column() construct.""" @@ -410,12 +413,11 @@ class DefaultCompiler(engine.Compiled): return bind_name - _trunc_re = re.compile(r'%\((-?\d+ \w+)\)s', re.U) def _truncated_identifier(self, ident_class, name): if (ident_class, name) in self.truncated_names: return self.truncated_names[(ident_class, name)] - anonname = self._trunc_re.sub(lambda m: self.anon_map[m.group(1)], name) + anonname = name % self.anon_map if len(anonname) > self.label_length: counter = self.truncated_names.get(ident_class, 1) @@ -427,7 +429,7 @@ class DefaultCompiler(engine.Compiled): return truncname def _anonymize(self, name): - return self._trunc_re.sub(lambda m: self.anon_map[m.group(1)], name) + return name % self.anon_map def _process_anon(self, key): (ident, derived) = key.split(' ') diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py index f527c6351..48b1d0687 100644 --- a/lib/sqlalchemy/sql/expression.py +++ b/lib/sqlalchemy/sql/expression.py @@ -869,6 +869,12 @@ modifier = _FunctionGenerator(group=False) class _generated_label(unicode): """A unicode subclass used to identify dynamically generated names.""" +def _escape_for_generated(x): + if isinstance(x, _generated_label): + return x + else: + return x.replace('%', '%%') + def _clone(element): return element._clone() @@ -1637,7 +1643,7 @@ class ColumnElement(ClauseElement, _CompareMixin): expressions and function calls. """ - return _generated_label("%%(%d %s)s" % (id(self), getattr(self, 'name', 'anon'))) + return _generated_label("%%(%d %s)s" % (id(self), _escape_for_generated(getattr(self, 'name', 'anon')))) class ColumnCollection(util.OrderedProperties): """An ordered dictionary that stores a list of ColumnElement @@ -1969,7 +1975,7 @@ class _BindParamClause(ColumnElement): """ if unique: - self.key = _generated_label("%%(%d %s)s" % (id(self), key or 'param')) + self.key = _generated_label("%%(%d %s)s" % (id(self), key and _escape_for_generated(key) or 'param')) else: self.key = key or _generated_label("%%(%d param)s" % id(self)) self._orig_key = key or 'param' @@ -1988,13 +1994,13 @@ class _BindParamClause(ColumnElement): def _clone(self): c = ClauseElement._clone(self) if self.unique: - c.key = _generated_label("%%(%d %s)s" % (id(c), c._orig_key or 'param')) + c.key = _generated_label("%%(%d %s)s" % (id(c), c._orig_key and _escape_for_generated(c._orig_key) or 'param')) return c def _convert_to_unique(self): if not self.unique: self.unique = True - self.key = _generated_label("%%(%d %s)s" % (id(self), self._orig_key or 'param')) + self.key = _generated_label("%%(%d %s)s" % (id(self), self._orig_key and _escape_for_generated(self._orig_key) or 'param')) def bind_processor(self, dialect): return self.type.dialect_impl(dialect).bind_processor(dialect) @@ -2601,7 +2607,7 @@ class Alias(FromClause): if alias is None: if self.original.named_with_column: alias = getattr(self.original, 'name', None) - alias = _generated_label('%%(%d %s)s' % (id(self), alias or 'anon')) + alias = _generated_label('%%(%d %s)s' % (id(self), alias and _escape_for_generated(alias) or 'anon')) self.name = alias @property @@ -2722,7 +2728,7 @@ class _Label(ColumnElement): def __init__(self, name, element, type_=None): while isinstance(element, _Label): element = element.element - self.name = self.key = self._label = name or _generated_label("%%(%d %s)s" % (id(self), getattr(element, 'name', 'anon'))) + self.name = self.key = self._label = name or _generated_label("%%(%d %s)s" % (id(self), _escape_for_generated(getattr(element, 'name', 'anon')))) self._element = element self._type = type_ self.quote = element.quote @@ -2811,9 +2817,9 @@ class ColumnClause(_Immutable, ColumnElement): elif self.table and self.table.named_with_column: if getattr(self.table, 'schema', None): - label = self.table.schema + "_" + self.table.name + "_" + self.name + label = self.table.schema + "_" + _escape_for_generated(self.table.name) + "_" + _escape_for_generated(self.name) else: - label = self.table.name + "_" + self.name + label = _escape_for_generated(self.table.name) + "_" + _escape_for_generated(self.name) if label in self.table.c: # TODO: coverage does not seem to be present for this |