From 072039945b23b0a76814e53698da247de334f7eb Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sun, 18 Jan 2009 17:08:28 +0000 Subject: [PATCH] - Further fixes to the "percent signs and spaces in column/table names" functionality. [ticket:1284] - Still doesn't work for PG/MySQL, which unfortunately would require post_process_text() calls all over the place. Perhaps % escaping can be assembled into IdentifierPreparer.quote() since that's where identifier names are received. --- CHANGES | 6 ++++ lib/sqlalchemy/__init__.py | 3 +- lib/sqlalchemy/sql/compiler.py | 6 ++-- lib/sqlalchemy/sql/expression.py | 12 +++---- test/sql/query.py | 57 +++++++++++++++++++++----------- 5 files changed, 54 insertions(+), 30 deletions(-) diff --git a/CHANGES b/CHANGES index 183edbdc0f..74ae62752f 100644 --- a/CHANGES +++ b/CHANGES @@ -3,7 +3,13 @@ ======= CHANGES ======= +0.5.2 +====== +- sql + - Further fixes to the "percent signs and spaces in column/table + names" functionality. [ticket:1284] + 0.5.1 ======== diff --git a/lib/sqlalchemy/__init__.py b/lib/sqlalchemy/__init__.py index cc425acb23..5ef4ff6d84 100644 --- a/lib/sqlalchemy/__init__.py +++ b/lib/sqlalchemy/__init__.py @@ -106,6 +106,7 @@ from sqlalchemy.engine import create_engine, engine_from_config __all__ = sorted(name for name, obj in locals().items() if not (name.startswith('_') or inspect.ismodule(obj))) -__version__ = '0.5.1' + +__version__ = '0.5.2' del inspect, sys diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index 8622aeea41..dd4e194fe6 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -432,8 +432,7 @@ class DefaultCompiler(engine.Compiled): return name % self.anon_map def _process_anon(self, key): - (ident, derived) = key.split(' ') - + (ident, derived) = key.split(' ', 1) anonymous_counter = self.anon_map.get(derived, 1) self.anon_map[derived] = anonymous_counter + 1 return derived + "_" + str(anonymous_counter) @@ -447,7 +446,8 @@ class DefaultCompiler(engine.Compiled): def visit_alias(self, alias, asfrom=False, **kwargs): if asfrom: - return self.process(alias.original, asfrom=True, **kwargs) + " AS " + self.preparer.format_alias(alias, alias.name % self.anon_map) + return self.process(alias.original, asfrom=True, **kwargs) + " AS " + \ + self.preparer.format_alias(alias, alias.name % self.anon_map) else: return self.process(alias.original, **kwargs) diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py index 65cc903dd0..b3a7dd8e2a 100644 --- a/lib/sqlalchemy/sql/expression.py +++ b/lib/sqlalchemy/sql/expression.py @@ -1643,7 +1643,7 @@ class ColumnElement(ClauseElement, _CompareMixin): expressions and function calls. """ - return _generated_label("%%(%d %s)s" % (id(self), _escape_for_generated(getattr(self, 'name', 'anon')))) + return _generated_label("%%(%d %s)s" % (id(self), getattr(self, 'name', 'anon'))) class ColumnCollection(util.OrderedProperties): """An ordered dictionary that stores a list of ColumnElement @@ -1975,7 +1975,7 @@ class _BindParamClause(ColumnElement): """ if unique: - self.key = _generated_label("%%(%d %s)s" % (id(self), key and _escape_for_generated(key) or 'param')) + self.key = _generated_label("%%(%d %s)s" % (id(self), key or 'param')) else: self.key = key or _generated_label("%%(%d param)s" % id(self)) self._orig_key = key or 'param' @@ -1994,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 and _escape_for_generated(c._orig_key) or 'param')) + c.key = _generated_label("%%(%d %s)s" % (id(c), 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 and _escape_for_generated(self._orig_key) or 'param')) + self.key = _generated_label("%%(%d %s)s" % (id(self), self._orig_key or 'param')) def bind_processor(self, dialect): return self.type.dialect_impl(dialect).bind_processor(dialect) @@ -2607,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 and _escape_for_generated(alias) or 'anon')) + alias = _generated_label('%%(%d %s)s' % (id(self), alias or 'anon')) self.name = alias @property @@ -2728,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), _escape_for_generated(getattr(element, 'name', 'anon')))) + self.name = self.key = self._label = name or _generated_label("%%(%d %s)s" % (id(self), getattr(element, 'name', 'anon'))) self._element = element self._type = type_ self.quote = element.quote diff --git a/test/sql/query.py b/test/sql/query.py index bf178ae8f5..a6c4196561 100644 --- a/test/sql/query.py +++ b/test/sql/query.py @@ -683,7 +683,9 @@ class PercentSchemaNamesTest(TestBase): Column("spaces % more spaces", Integer), ) metadata.create_all() - + + @testing.crashes('mysql', 'mysqldb calls name % (params)') + @testing.crashes('postgres', 'postgres calls name % (params)') def tearDownAll(self): metadata.drop_all() @@ -698,26 +700,41 @@ class PercentSchemaNamesTest(TestBase): {'percent%':9, '%(oneofthese)s':9, 'spaces % more spaces':10}, {'percent%':11, '%(oneofthese)s':10, 'spaces % more spaces':9}, ) - eq_( - percent_table.select().order_by(percent_table.c['%(oneofthese)s']).execute().fetchall(), - [ - (5, 7, 12), - (7, 8, 11), - (9, 9, 10), - (11, 10, 9) - ] - ) - result = percent_table.select().order_by(percent_table.c['%(oneofthese)s']).execute() - row = result.fetchone() - eq_(row[percent_table.c['percent%']], 5) - eq_(row[percent_table.c['%(oneofthese)s']], 7) - eq_(row[percent_table.c['spaces % more spaces']], 12) - row = result.fetchone() - eq_(row['percent%'], 7) - eq_(row['%(oneofthese)s'], 8) - eq_(row['spaces % more spaces'], 11) - result.close() + + for table in (percent_table, percent_table.alias()): + eq_( + table.select().order_by(table.c['%(oneofthese)s']).execute().fetchall(), + [ + (5, 7, 12), + (7, 8, 11), + (9, 9, 10), + (11, 10, 9) + ] + ) + + eq_( + table.select(). + where(table.c['spaces % more spaces'].in_([9, 10])). + order_by(table.c['%(oneofthese)s']).execute().fetchall(), + [ + (9, 9, 10), + (11, 10, 9) + ] + ) + + result = table.select().order_by(table.c['%(oneofthese)s']).execute() + row = result.fetchone() + eq_(row[table.c['percent%']], 5) + eq_(row[table.c['%(oneofthese)s']], 7) + eq_(row[table.c['spaces % more spaces']], 12) + row = result.fetchone() + eq_(row['percent%'], 7) + eq_(row['%(oneofthese)s'], 8) + eq_(row['spaces % more spaces'], 11) + result.close() + percent_table.update().values({percent_table.c['%(oneofthese)s']:9, percent_table.c['spaces % more spaces']:15}).execute() + eq_( percent_table.select().order_by(percent_table.c['%(oneofthese)s']).execute().fetchall(), [ -- 2.47.3