Mike Bayer avatar Mike Bayer committed e7174a6

Fixed bug whereby using a label_length on dialect that was smaller
than the size of actual column identifiers would fail to render
the columns correctly in a SELECT statement.
[ticket:2610]

Comments (0)

Files changed (4)

doc/build/changelog/changelog_08.rst

     :version: 0.8.0b2
 
     .. change::
+        :tags: sql, bug
+        :tickets: 2610
+
+      Fixed bug whereby using a label_length on dialect that was smaller
+      than the size of actual column identifiers would fail to render
+      the columns correctly in a SELECT statement.
+
+    .. change::
         :tags: sql, feature
         :tickets: 2623
 

lib/sqlalchemy/schema.py

         c.dispatch._update(self.dispatch)
         return c
 
-    def _make_proxy(self, selectable, name=None, key=None):
+    def _make_proxy(self, selectable, name=None, key=None,
+                            name_is_truncatable=False, **kw):
         """Create a *proxy* for this column.
 
         This is a copy of this ``Column`` referenced by a different parent
                     "been assigned.")
         try:
             c = self._constructor(
-                expression._as_truncated(name or self.name),
+                expression._as_truncated(name or self.name) if \
+                                name_is_truncatable else (name or self.name),
                 self.type,
                 key=key if key else name if name else self.key,
                 primary_key=self.primary_key,

lib/sqlalchemy/sql/expression.py

         return hasattr(other, 'name') and hasattr(self, 'name') and \
                 other.name == self.name
 
-    def _make_proxy(self, selectable, name=None, **kw):
+    def _make_proxy(self, selectable, name=None, name_is_truncatable=False, **kw):
         """Create a new :class:`.ColumnElement` representing this
         :class:`.ColumnElement` as it appears in the select list of a
         descending selectable.
             key = str(self)
         else:
             key = name
-        co = ColumnClause(_as_truncated(name),
+        co = ColumnClause(_as_truncated(name) if name_is_truncatable else name,
                             selectable,
                             type_=getattr(self,
                           'type', None))
                                 _compared_to_type=self.type,
                                 unique=True)
 
-    def _make_proxy(self, selectable, name=None, attach=True, **kw):
+    def _make_proxy(self, selectable, name=None, attach=True,
+                            name_is_truncatable=False, **kw):
         # propagate the "is_literal" flag only if we are keeping our name,
         # otherwise its considered to be a label
         is_literal = self.is_literal and (name is None or name == self.name)
         c = self._constructor(
-                    _as_truncated(name if name else self.name),
+                    _as_truncated(name or self.name) if \
+                                    name_is_truncatable else \
+                                    (name or self.name),
                     selectable=selectable,
                     type_=self.type,
                     is_literal=is_literal
             if hasattr(c, '_make_proxy'):
                 c._make_proxy(self,
                         name=c._label if self.use_labels else None,
-                        key=c._key_label if self.use_labels else None)
+                        key=c._key_label if self.use_labels else None,
+                        name_is_truncatable=True)
 
     def _refresh_for_new_column(self, column):
         for fromclause in self._froms:
                     if our_label not in self.c:
                         return col._make_proxy(self,
                             name=col._label if self.use_labels else None,
-                            key=col._key_label if self.use_labels else None)
+                            key=col._key_label if self.use_labels else None,
+                            name_is_truncatable=True)
                 return None
         return None
 

test/sql/test_labels.py

             dialect=compile_dialect)
 
 
+    def test_colnames_longer_than_labels_lowercase(self):
+        t1 = table('a', column('abcde'))
+        self._test_colnames_longer_than_labels(t1)
+
+    def test_colnames_longer_than_labels_uppercase(self):
+        m = MetaData()
+        t1 = Table('a', m, Column('abcde', Integer))
+        self._test_colnames_longer_than_labels(t1)
+
+    def _test_colnames_longer_than_labels(self, t1):
+        dialect = default.DefaultDialect(label_length=4)
+        a1 = t1.alias(name='asdf')
+
+        # 'abcde' is longer than 4, but rendered as itself
+        # needs to have all characters
+        s = select([a1])
+        self.assert_compile(
+            select([a1]),
+            "SELECT asdf.abcde FROM a AS asdf",
+            dialect=dialect
+        )
+        compiled = s.compile(dialect=dialect)
+        assert set(compiled.result_map['abcde'][1]).issuperset([
+                    'abcde',
+                    a1.c.abcde,
+                    'abcde'
+                ])
+
+        # column still there, but short label
+        s = select([a1]).apply_labels()
+        self.assert_compile(
+            s,
+            "SELECT asdf.abcde AS _1 FROM a AS asdf",
+            dialect=dialect
+        )
+        compiled = s.compile(dialect=dialect)
+        assert set(compiled.result_map['_1'][1]).issuperset([
+                    'asdf_abcde',
+                    a1.c.abcde,
+                    '_1'
+                ])
+
+
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.