diff options
-rw-r--r-- | CHANGES | 6 | ||||
-rw-r--r-- | lib/sqlalchemy/ansisql.py | 13 | ||||
-rw-r--r-- | lib/sqlalchemy/sql.py | 21 | ||||
-rw-r--r-- | test/orm/abc_inheritance.py | 4 | ||||
-rw-r--r-- | test/sql/select.py | 20 |
5 files changed, 56 insertions, 8 deletions
@@ -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 diff --git a/lib/sqlalchemy/ansisql.py b/lib/sqlalchemy/ansisql.py index 7a167f42e..f96bf7abe 100644 --- a/lib/sqlalchemy/ansisql.py +++ b/lib/sqlalchemy/ansisql.py @@ -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 diff --git a/lib/sqlalchemy/sql.py b/lib/sqlalchemy/sql.py index d41e16bcb..273af5415 100644 --- a/lib/sqlalchemy/sql.py +++ b/lib/sqlalchemy/sql.py @@ -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(): diff --git a/test/orm/abc_inheritance.py b/test/orm/abc_inheritance.py index 1cb51723f..2c0cfb323 100644 --- a/test/orm/abc_inheritance.py +++ b/test/orm/abc_inheritance.py @@ -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] diff --git a/test/sql/select.py b/test/sql/select.py index a4e863dae..a021bd5b9 100644 --- a/test/sql/select.py +++ b/test/sql/select.py @@ -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"), |