]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- use_labels flag on select() wont auto-create labels for literal text
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 1 Mar 2007 20:14:17 +0000 (20:14 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 1 Mar 2007 20:14:17 +0000 (20:14 +0000)
column elements, since we can make no assumptions about the text. to
create labels for literal columns, you can say "somecol AS somelabel",
or use literal_column("somecol").label("somelabel")
- quoting wont occur for literal columns when they are "proxied" into the
column collection for their selectable (is_literal flag is propigated)

CHANGES
lib/sqlalchemy/ansisql.py
lib/sqlalchemy/sql.py
test/orm/abc_inheritance.py
test/sql/select.py

diff --git a/CHANGES b/CHANGES
index 96d70b2cb5777ab37c82f68b5cddcb3208ce5696..9c716568c801184dd427186add206fb4eb2ea923 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -5,6 +5,12 @@
     - fixed function execution with explicit connections, when you dont 
     explicitly say "select()" off the function, i.e. 
     conn.execute(func.dosomething())
+    - use_labels flag on select() wont auto-create labels for literal text
+      column elements, since we can make no assumptions about the text. to
+      create labels for literal columns, you can say "somecol AS somelabel",
+      or use literal_column("somecol").label("somelabel")
+    - quoting wont occur for literal columns when they are "proxied" into the
+    column collection for their selectable (is_literal flag is propigated)
 - orm:
     - a full select() construct can be passed to query.select() (which
       worked anyway), but also query.selectfirst(), query.selectone() which
index 7a167f42edd830311ee1de59af5d2e5d9b259f56..f96bf7abefa093d320fcec9c1fae784cc5cbabcf 100644 (file)
@@ -392,12 +392,17 @@ class ANSICompiler(sql.Compiled):
                 continue
             for co in s.columns:
                 if select.use_labels:
-                    l = co.label(co._label)
-                    l.accept_visitor(self)
-                    inner_columns[co._label] = l
+                    labelname = co._label
+                    if labelname is not None:
+                        l = co.label(labelname)
+                        l.accept_visitor(self)
+                        inner_columns[labelname] = l
+                    else:
+                        co.accept_visitor(self)
+                        inner_columns[self.get_str(co)] = co
                 # TODO: figure this out, a ColumnClause with a select as a parent
                 # is different from any other kind of parent
-                elif select.is_subquery and isinstance(co, sql._ColumnClause) and co.table is not None and not isinstance(co.table, sql.Select):
+                elif select.is_subquery and isinstance(co, sql._ColumnClause) and not co.is_literal and co.table is not None and not isinstance(co.table, sql.Select):
                     # SQLite doesnt like selecting from a subquery where the column
                     # names look like table.colname, so add a label synonomous with
                     # the column name
index d41e16bcbf0f2faffa4fd0f762ff7d99ff5f88d6..273af5415ccd683f5c7297310c394d086dbd8e01 100644 (file)
@@ -1662,6 +1662,10 @@ class _ColumnClause(ColumnElement):
         self.is_literal = is_literal
 
     def _get_label(self):
+        # for a "literal" column, we've no idea what the text is
+        # therefore no 'label' can be automatically generated
+        if self.is_literal:
+            return None
         if self.__label is None:
             if self.table is not None and self.table.named_with_column():
                 self.__label = self.table.name + "_" + self.name
@@ -1674,6 +1678,14 @@ class _ColumnClause(ColumnElement):
 
     _label = property(_get_label)
 
+    def label(self, name):
+        # if going off the "__label" property and its None, we have
+        # no label; return self
+        if name is None:
+            return self
+        else:
+            return super(_ColumnClause, self).label(name)
+            
     def accept_visitor(self, visitor):
         visitor.visit_column(self)
 
@@ -1697,7 +1709,10 @@ class _ColumnClause(ColumnElement):
         return _BindParamClause(self._label, obj, shortname = self.name, type=self.type)
 
     def _make_proxy(self, selectable, name = None):
-        c = _ColumnClause(name or self.name, selectable, _is_oid=self._is_oid, type=self.type)
+        # propigate 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 = _ColumnClause(name or self.name, selectable, _is_oid=self._is_oid, type=self.type, is_literal=is_literal)
         c.orig_set = self.orig_set
         if not self._is_oid:
             selectable.columns[c.name] = c
@@ -1855,7 +1870,7 @@ class CompoundSelect(_SelectBaseMixin, FromClause):
         if self.use_labels:
             col = column._make_proxy(self, name=column._label)
         else:
-            col = column._make_proxy(self, name=column.name)
+            col = column._make_proxy(self)
         try:
             colset = self._col_map[col.name]
         except KeyError:
@@ -2009,7 +2024,7 @@ class Select(_SelectBaseMixin, FromClause):
         if self.use_labels:
             return column._make_proxy(self, name=column._label)
         else:
-            return column._make_proxy(self, name=column.name)
+            return column._make_proxy(self)
             
     def _process_froms(self, elem, asfrom):
         for f in elem._get_from_objects():
index 1cb51723f5041a2e7181758d7788edf9e1a391ee..2c0cfb3234a3461a5eb6b37788f2f08e5e91cee5 100644 (file)
@@ -44,7 +44,9 @@ def produce_test(parent, child, direction, fkeyinline):
             elif "c" == child and direction == ONETOMANY:
                 tc.append(Column('parent_id', Integer, ForeignKey("%s.id" % parent, use_alter=True, name="foo")))
             tc = Table(*tc)
-
+        
+        # TODO: get finicky postgres to work
+        @testbase.supported('sqlite')
         def test_basic(self):
             parent_table = {"a":ta, "b":tb, "c": tc}[parent]
             child_table = {"a":ta, "b":tb, "c": tc}[child]
index a4e863dae005e2774c5d66cb42cbe299717587be..a021bd5b99bfbbba947089ff82eabeab4a2c3dbd 100644 (file)
@@ -350,6 +350,26 @@ WHERE mytable.myid = myothertable.otherid) AS t2view WHERE t2view.mytable_myid =
             select(["column1", "column2"], from_obj=[table1]).alias('somealias').select(),
             "SELECT somealias.column1, somealias.column2 FROM (SELECT column1, column2 FROM mytable) AS somealias"
         )
+        
+        # test that use_labels doesnt interfere with literal columns
+        self.runtest(
+            select(["column1", "column2", table1.c.myid], from_obj=[table1], use_labels=True),
+            "SELECT column1, column2, mytable.myid AS mytable_myid FROM mytable"
+        )
+
+        # test that use_labels doesnt interfere with literal columns that have textual labels
+        self.runtest(
+            select(["column1 AS foobar", "column2 AS hoho", table1.c.myid], from_obj=[table1], use_labels=True),
+            "SELECT column1 AS foobar, column2 AS hoho, mytable.myid AS mytable_myid FROM mytable"
+        )
+        
+        # test that "auto-labeling of subquery columns" doesnt interfere with literal columns,
+        # exported columns dont get quoted
+        self.runtest(
+            select(["column1 AS foobar", "column2 AS hoho", table1.c.myid], from_obj=[table1]).select(),
+            "SELECT column1 AS foobar, column2 AS hoho, myid FROM (SELECT column1 AS foobar, column2 AS hoho, mytable.myid AS myid FROM mytable)"
+        )
+
     def testtextbinds(self):
         self.runtest(
             text("select * from foo where lala=:bar and hoho=:whee"),