<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><style type="text/css"><!--
#msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; }
#msg ul, pre { overflow: auto; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<title>[2368] sqlalchemy/trunk: - use_labels flag on select() wont auto-create labels for literal text</title>
</head>
<body>
<div id="msg">
<dl>
<dt>Revision</dt> <dd>2368</dd>
<dt>Author</dt> <dd>zzzeek</dd>
<dt>Date</dt> <dd>2007-03-01 14:14:17 -0600 (Thu, 01 Mar 2007)</dd>
</dl>
<h3>Log Message</h3>
<pre>- 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)</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#sqlalchemytrunkCHANGES">sqlalchemy/trunk/CHANGES</a></li>
<li><a href="#sqlalchemytrunklibsqlalchemyansisqlpy">sqlalchemy/trunk/lib/sqlalchemy/ansisql.py</a></li>
<li><a href="#sqlalchemytrunklibsqlalchemysqlpy">sqlalchemy/trunk/lib/sqlalchemy/sql.py</a></li>
<li><a href="#sqlalchemytrunktestormabc_inheritancepy">sqlalchemy/trunk/test/orm/abc_inheritance.py</a></li>
<li><a href="#sqlalchemytrunktestsqlselectpy">sqlalchemy/trunk/test/sql/select.py</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="sqlalchemytrunkCHANGES"></a>
<div class="modfile"><h4>Modified: sqlalchemy/trunk/CHANGES (2367 => 2368)</h4>
<pre class="diff"><span>
<span class="info">--- sqlalchemy/trunk/CHANGES 2007-02-28 21:42:54 UTC (rev 2367)
+++ sqlalchemy/trunk/CHANGES 2007-03-01 20:14:17 UTC (rev 2368)
</span><span class="lines">@@ -5,6 +5,12 @@
</span><span class="cx"> - fixed function execution with explicit connections, when you dont
</span><span class="cx"> explicitly say "select()" off the function, i.e.
</span><span class="cx"> conn.execute(func.dosomething())
</span><ins>+ - 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)
</ins><span class="cx"> - orm:
</span><span class="cx"> - a full select() construct can be passed to query.select() (which
</span><span class="cx"> worked anyway), but also query.selectfirst(), query.selectone() which
</span></span></pre></div>
<a id="sqlalchemytrunklibsqlalchemyansisqlpy"></a>
<div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/ansisql.py (2367 => 2368)</h4>
<pre class="diff"><span>
<span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/ansisql.py 2007-02-28 21:42:54 UTC (rev 2367)
+++ sqlalchemy/trunk/lib/sqlalchemy/ansisql.py 2007-03-01 20:14:17 UTC (rev 2368)
</span><span class="lines">@@ -392,12 +392,17 @@
</span><span class="cx"> continue
</span><span class="cx"> for co in s.columns:
</span><span class="cx"> if select.use_labels:
</span><del>- l = co.label(co._label)
- l.accept_visitor(self)
- inner_columns[co._label] = l
</del><ins>+ 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
</ins><span class="cx"> # TODO: figure this out, a ColumnClause with a select as a parent
</span><span class="cx"> # is different from any other kind of parent
</span><del>- elif select.is_subquery and isinstance(co, sql._ColumnClause) and co.table is not None and not isinstance(co.table, sql.Select):
</del><ins>+ 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):
</ins><span class="cx"> # SQLite doesnt like selecting from a subquery where the column
</span><span class="cx"> # names look like table.colname, so add a label synonomous with
</span><span class="cx"> # the column name
</span></span></pre></div>
<a id="sqlalchemytrunklibsqlalchemysqlpy"></a>
<div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/sql.py (2367 => 2368)</h4>
<pre class="diff"><span>
<span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/sql.py 2007-02-28 21:42:54 UTC (rev 2367)
+++ sqlalchemy/trunk/lib/sqlalchemy/sql.py 2007-03-01 20:14:17 UTC (rev 2368)
</span><span class="lines">@@ -1662,6 +1662,10 @@
</span><span class="cx"> self.is_literal = is_literal
</span><span class="cx">
</span><span class="cx"> def _get_label(self):
</span><ins>+ # 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
</ins><span class="cx"> if self.__label is None:
</span><span class="cx"> if self.table is not None and self.table.named_with_column():
</span><span class="cx"> self.__label = self.table.name + "_" + self.name
</span><span class="lines">@@ -1674,6 +1678,14 @@
</span><span class="cx">
</span><span class="cx"> _label = property(_get_label)
</span><span class="cx">
</span><ins>+ 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)
+
</ins><span class="cx"> def accept_visitor(self, visitor):
</span><span class="cx"> visitor.visit_column(self)
</span><span class="cx">
</span><span class="lines">@@ -1697,7 +1709,10 @@
</span><span class="cx"> return _BindParamClause(self._label, obj, shortname = self.name, type=self.type)
</span><span class="cx">
</span><span class="cx"> def _make_proxy(self, selectable, name = None):
</span><del>- c = _ColumnClause(name or self.name, selectable, _is_oid=self._is_oid, type=self.type)
</del><ins>+ # 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)
</ins><span class="cx"> c.orig_set = self.orig_set
</span><span class="cx"> if not self._is_oid:
</span><span class="cx"> selectable.columns[c.name] = c
</span><span class="lines">@@ -1855,7 +1870,7 @@
</span><span class="cx"> if self.use_labels:
</span><span class="cx"> col = column._make_proxy(self, name=column._label)
</span><span class="cx"> else:
</span><del>- col = column._make_proxy(self, name=column.name)
</del><ins>+ col = column._make_proxy(self)
</ins><span class="cx"> try:
</span><span class="cx"> colset = self._col_map[col.name]
</span><span class="cx"> except KeyError:
</span><span class="lines">@@ -2009,7 +2024,7 @@
</span><span class="cx"> if self.use_labels:
</span><span class="cx"> return column._make_proxy(self, name=column._label)
</span><span class="cx"> else:
</span><del>- return column._make_proxy(self, name=column.name)
</del><ins>+ return column._make_proxy(self)
</ins><span class="cx">
</span><span class="cx"> def _process_froms(self, elem, asfrom):
</span><span class="cx"> for f in elem._get_from_objects():
</span></span></pre></div>
<a id="sqlalchemytrunktestormabc_inheritancepy"></a>
<div class="modfile"><h4>Modified: sqlalchemy/trunk/test/orm/abc_inheritance.py (2367 => 2368)</h4>
<pre class="diff"><span>
<span class="info">--- sqlalchemy/trunk/test/orm/abc_inheritance.py 2007-02-28 21:42:54 UTC (rev 2367)
+++ sqlalchemy/trunk/test/orm/abc_inheritance.py 2007-03-01 20:14:17 UTC (rev 2368)
</span><span class="lines">@@ -44,7 +44,9 @@
</span><span class="cx"> elif "c" == child and direction == ONETOMANY:
</span><span class="cx"> tc.append(Column('parent_id', Integer, ForeignKey("%s.id" % parent, use_alter=True, name="foo")))
</span><span class="cx"> tc = Table(*tc)
</span><del>-
</del><ins>+
+ # TODO: get finicky postgres to work
+ @testbase.supported('sqlite')
</ins><span class="cx"> def test_basic(self):
</span><span class="cx"> parent_table = {"a":ta, "b":tb, "c": tc}[parent]
</span><span class="cx"> child_table = {"a":ta, "b":tb, "c": tc}[child]
</span></span></pre></div>
<a id="sqlalchemytrunktestsqlselectpy"></a>
<div class="modfile"><h4>Modified: sqlalchemy/trunk/test/sql/select.py (2367 => 2368)</h4>
<pre class="diff"><span>
<span class="info">--- sqlalchemy/trunk/test/sql/select.py 2007-02-28 21:42:54 UTC (rev 2367)
+++ sqlalchemy/trunk/test/sql/select.py 2007-03-01 20:14:17 UTC (rev 2368)
</span><span class="lines">@@ -350,6 +350,26 @@
</span><span class="cx"> select(["column1", "column2"], from_obj=[table1]).alias('somealias').select(),
</span><span class="cx"> "SELECT somealias.column1, somealias.column2 FROM (SELECT column1, column2 FROM mytable) AS somealias"
</span><span class="cx"> )
</span><ins>+
+ # 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)"
+ )
+
</ins><span class="cx"> def testtextbinds(self):
</span><span class="cx"> self.runtest(
</span><span class="cx"> text("select * from foo where lala=:bar and hoho=:whee"),
</span></span></pre>
</div>
</div>
</body>
</html>
|