sqlalchemy-commits Mailing List for SQLAlchemy (Page 378)
Brought to you by:
zzzeek
You can subscribe to this list here.
2006 |
Jan
|
Feb
(74) |
Mar
(167) |
Apr
(127) |
May
(190) |
Jun
(119) |
Jul
(77) |
Aug
(82) |
Sep
(84) |
Oct
(153) |
Nov
(45) |
Dec
(54) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
(109) |
Feb
(80) |
Mar
(110) |
Apr
(106) |
May
(92) |
Jun
(147) |
Jul
(288) |
Aug
(307) |
Sep
(108) |
Oct
(156) |
Nov
(147) |
Dec
(134) |
2008 |
Jan
(126) |
Feb
(91) |
Mar
(184) |
Apr
(208) |
May
(212) |
Jun
(54) |
Jul
(106) |
Aug
(80) |
Sep
(58) |
Oct
(80) |
Nov
(119) |
Dec
(220) |
2009 |
Jan
(202) |
Feb
(50) |
Mar
(70) |
Apr
(46) |
May
(80) |
Jun
(61) |
Jul
(146) |
Aug
(81) |
Sep
(71) |
Oct
(74) |
Nov
(66) |
Dec
(82) |
2010 |
Jan
(112) |
Feb
(169) |
Mar
(235) |
Apr
(77) |
May
(22) |
Jun
(31) |
Jul
(46) |
Aug
(46) |
Sep
(70) |
Oct
(36) |
Nov
(37) |
Dec
(79) |
2011 |
Jan
(46) |
Feb
(54) |
Mar
(65) |
Apr
(73) |
May
(31) |
Jun
(46) |
Jul
(40) |
Aug
(36) |
Sep
(44) |
Oct
(33) |
Nov
(19) |
Dec
(10) |
2012 |
Jan
(60) |
Feb
(37) |
Mar
(35) |
Apr
(28) |
May
(27) |
Jun
(50) |
Jul
(33) |
Aug
(88) |
Sep
(64) |
Oct
(74) |
Nov
(62) |
Dec
(41) |
2013 |
Jan
(30) |
Feb
(37) |
Mar
(39) |
Apr
(52) |
May
(40) |
Jun
(85) |
Jul
(74) |
Aug
(76) |
Sep
(26) |
Oct
(76) |
Nov
(63) |
Dec
(65) |
2014 |
Jan
(68) |
Feb
(82) |
Mar
(87) |
Apr
(24) |
May
(66) |
Jun
(34) |
Jul
(86) |
Aug
(75) |
Sep
(70) |
Oct
(41) |
Nov
(23) |
Dec
(53) |
2015 |
Jan
(40) |
Feb
(39) |
Mar
(69) |
Apr
(64) |
May
(40) |
Jun
(43) |
Jul
(20) |
Aug
(48) |
Sep
(38) |
Oct
(28) |
Nov
(34) |
Dec
(44) |
2016 |
Jan
(82) |
Feb
(49) |
Mar
(25) |
Apr
(21) |
May
(19) |
Jun
(46) |
Jul
(38) |
Aug
(21) |
Sep
(33) |
Oct
(44) |
Nov
(26) |
Dec
(10) |
2017 |
Jan
(52) |
Feb
(18) |
Mar
(61) |
Apr
(43) |
May
(57) |
Jun
(36) |
Jul
(37) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <co...@sq...> - 2006-02-22 08:13:04
|
<!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>[1017] sqlalchemy/trunk/test/alltests.py: one more test commit</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1017</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-02-22 01:47:58 -0600 (Wed, 22 Feb 2006)</dd> </dl> <h3>Log Message</h3> <pre>one more test commit</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunktestalltestspy">sqlalchemy/trunk/test/alltests.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunktestalltestspy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/alltests.py (1016 => 1017)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/alltests.py 2006-02-22 06:40:14 UTC (rev 1016) +++ sqlalchemy/trunk/test/alltests.py 2006-02-22 07:47:58 UTC (rev 1017) </span><span class="lines">@@ -3,8 +3,6 @@ </span><span class="cx"> </span><span class="cx"> testbase.echo = False </span><span class="cx"> </span><del>-# test - </del><span class="cx"> def suite(): </span><span class="cx"> modules_to_test = ( </span><span class="cx"> # core utilities </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-02-22 08:11:59
|
<!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>[1016] sqlalchemy/trunk/test/alltests.py: this is a test commit</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1016</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-02-22 00:40:14 -0600 (Wed, 22 Feb 2006)</dd> </dl> <h3>Log Message</h3> <pre>this is a test commit</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunktestalltestspy">sqlalchemy/trunk/test/alltests.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunktestalltestspy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/alltests.py (1015 => 1016)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/alltests.py 2006-02-22 06:29:05 UTC (rev 1015) +++ sqlalchemy/trunk/test/alltests.py 2006-02-22 06:40:14 UTC (rev 1016) </span><span class="lines">@@ -3,6 +3,8 @@ </span><span class="cx"> </span><span class="cx"> testbase.echo = False </span><span class="cx"> </span><ins>+# test + </ins><span class="cx"> def suite(): </span><span class="cx"> modules_to_test = ( </span><span class="cx"> # core utilities </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-02-22 08:10:44
|
<!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>[1016] sqlalchemy/trunk/test/alltests.py: this is a test commit</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1016</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-02-22 00:40:14 -0600 (Wed, 22 Feb 2006)</dd> </dl> <h3>Log Message</h3> <pre>this is a test commit</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunktestalltestspy">sqlalchemy/trunk/test/alltests.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunktestalltestspy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/alltests.py (1015 => 1016)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/alltests.py 2006-02-22 06:29:05 UTC (rev 1015) +++ sqlalchemy/trunk/test/alltests.py 2006-02-22 06:40:14 UTC (rev 1016) </span><span class="lines">@@ -3,6 +3,8 @@ </span><span class="cx"> </span><span class="cx"> testbase.echo = False </span><span class="cx"> </span><ins>+# test + </ins><span class="cx"> def suite(): </span><span class="cx"> modules_to_test = ( </span><span class="cx"> # core utilities </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-02-22 07:46:38
|
<!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>[1016] sqlalchemy/trunk/test/alltests.py: this is a test commit</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1016</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-02-22 00:40:14 -0600 (Wed, 22 Feb 2006)</dd> </dl> <h3>Log Message</h3> <pre>this is a test commit</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunktestalltestspy">sqlalchemy/trunk/test/alltests.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunktestalltestspy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/alltests.py (1015 => 1016)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/alltests.py 2006-02-22 06:29:05 UTC (rev 1015) +++ sqlalchemy/trunk/test/alltests.py 2006-02-22 06:40:14 UTC (rev 1016) </span><span class="lines">@@ -3,6 +3,8 @@ </span><span class="cx"> </span><span class="cx"> testbase.echo = False </span><span class="cx"> </span><ins>+# test + </ins><span class="cx"> def suite(): </span><span class="cx"> modules_to_test = ( </span><span class="cx"> # core utilities </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-02-22 07:46:36
|
<!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>[1015] sqlalchemy/trunk/test: more fix to one-to-one: 'unchanged_items' can be [None] also with one to one so check for this</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1015</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-02-22 00:29:05 -0600 (Wed, 22 Feb 2006)</dd> </dl> <h3>Log Message</h3> <pre>more fix to one-to-one: 'unchanged_items' can be [None] also with one to one so check for this during delete</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemymappingpropertiespy">sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py</a></li> <li><a href="#sqlalchemytrunktestonetoonepy">sqlalchemy/trunk/test/onetoone.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemymappingpropertiespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py (1014 => 1015)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py 2006-02-22 00:33:38 UTC (rev 1014) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py 2006-02-22 06:29:05 UTC (rev 1015) </span><span class="lines">@@ -455,8 +455,9 @@ </span><span class="cx"> for obj in deplist: </span><span class="cx"> childlist = getlist(obj, False) </span><span class="cx"> for child in childlist.deleted_items() + childlist.unchanged_items(): </span><del>- self._synchronize(obj, child, None, True) - uowcommit.register_object(child, postupdate=self.post_update) </del><ins>+ if child is not None: + self._synchronize(obj, child, None, True) + uowcommit.register_object(child, postupdate=self.post_update) </ins><span class="cx"> elif self.association is not None: </span><span class="cx"> # manage association objects. </span><span class="cx"> for obj in deplist: </span></span></pre></div> <a id="sqlalchemytrunktestonetoonepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/onetoone.py (1014 => 1015)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/onetoone.py 2006-02-22 00:33:38 UTC (rev 1014) +++ sqlalchemy/trunk/test/onetoone.py 2006-02-22 06:29:05 UTC (rev 1015) </span><span class="lines">@@ -79,5 +79,8 @@ </span><span class="cx"> self.assert_(p.jack is None) </span><span class="cx"> objectstore.commit() </span><span class="cx"> </span><ins>+ j.delete() + objectstore.commit() + </ins><span class="cx"> if __name__ == "__main__": </span><span class="cx"> testbase.main() </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-02-22 07:46:34
|
<!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>[1014] sqlalchemy/trunk/lib/sqlalchemy/mapping/objectstore.py: when begin/commit, an exception should still reset the transactional state</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1014</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-02-21 18:33:38 -0600 (Tue, 21 Feb 2006)</dd> </dl> <h3>Log Message</h3> <pre>when begin/commit, an exception should still reset the transactional state</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemymappingobjectstorepy">sqlalchemy/trunk/lib/sqlalchemy/mapping/objectstore.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemymappingobjectstorepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/objectstore.py (1013 => 1014)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/objectstore.py 2006-02-22 00:28:59 UTC (rev 1013) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/objectstore.py 2006-02-22 00:33:38 UTC (rev 1014) </span><span class="lines">@@ -119,9 +119,11 @@ </span><span class="cx"> </span><span class="cx"> def _trans_commit(self, trans): </span><span class="cx"> if trans.uow is self.uow and trans.isactive: </span><del>- self.uow.commit() - self.uow = self.parent_uow - self.parent_uow = None </del><ins>+ try: + self.uow.commit() + finally: + self.uow = self.parent_uow + self.parent_uow = None </ins><span class="cx"> def _trans_rollback(self, trans): </span><span class="cx"> if trans.uow is self.uow: </span><span class="cx"> self.uow = self.parent_uow </span></span></pre> </div> </div> </body> </html> |
<!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>[1013] sqlalchemy/trunk/test: fix to EagerLoad where it late-initializes its eager chain, thereby not getting messed up by late add_property() calls</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1013</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-02-21 18:28:59 -0600 (Tue, 21 Feb 2006)</dd> </dl> <h3>Log Message</h3> <pre>fix to EagerLoad where it late-initializes its eager chain, thereby not getting messed up by late add_property() calls</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemymappingpropertiespy">sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyschemapy">sqlalchemy/trunk/lib/sqlalchemy/schema.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemysqlpy">sqlalchemy/trunk/lib/sqlalchemy/sql.py</a></li> </ul> <h3>Added Paths</h3> <ul> <li><a href="#sqlalchemytrunktesteagertest1py">sqlalchemy/trunk/test/eagertest1.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemymappingpropertiespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py (1012 => 1013)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py 2006-02-21 03:01:43 UTC (rev 1012) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py 2006-02-22 00:28:59 UTC (rev 1013) </span><span class="lines">@@ -740,9 +740,6 @@ </span><span class="cx"> def do_init_subclass(self, key, parent, recursion_stack=None): </span><span class="cx"> parent._has_eager = True </span><span class="cx"> </span><del>- if recursion_stack is None: - recursion_stack = {} - </del><span class="cx"> self.eagertarget = self.target.alias() </span><span class="cx"> if self.secondary: </span><span class="cx"> self.eagersecondary = self.secondary.alias() </span><span class="lines">@@ -764,6 +761,14 @@ </span><span class="cx"> else: </span><span class="cx"> self.eager_order_by = None </span><span class="cx"> </span><ins>+ + def _create_eager_chain(self, in_chain=False, recursion_stack=None): + if not in_chain and getattr(self, '_eager_chained', False): + return + + if recursion_stack is None: + recursion_stack = {} + </ins><span class="cx"> eagerprops = [] </span><span class="cx"> # create a new "eager chain", starting from this eager loader and descending downwards </span><span class="cx"> # through all sub-eagerloaders. this will copy all those eagerloaders and have them set up </span><span class="lines">@@ -783,15 +788,17 @@ </span><span class="cx"> continue </span><span class="cx"> p = prop.copy() </span><span class="cx"> self.mapper.props[prop.key] = p </span><del>- #print "we are:", id(self), self.target.name, (self.secondary and self.secondary.name or "None"), self.parent.table.name - #print "prop is",id(prop), prop.target.name, (prop.secondary and prop.secondary.name or "None"), prop.parent.table.name </del><ins>+# print "we are:", id(self), self.target.name, (self.secondary and self.secondary.name or "None"), self.parent.table.name +# print "prop is",id(prop), prop.target.name, (prop.secondary and prop.secondary.name or "None"), prop.parent.table.name </ins><span class="cx"> p.do_init_subclass(prop.key, prop.parent, recursion_stack) </span><ins>+ p._create_eager_chain(in_chain=True, recursion_stack=recursion_stack) </ins><span class="cx"> p.eagerprimary = p.eagerprimary.copy_container() </span><del>- aliasizer = Aliasizer(p.parent.table, aliases={p.parent.table:self.eagertarget}) - p.eagerprimary.accept_visitor(aliasizer) </del><ins>+# aliasizer = Aliasizer(p.parent.table, aliases={p.parent.table:self.eagertarget}) + p.eagerprimary.accept_visitor(self.aliasizer) </ins><span class="cx"> #print "new eagertqarget", p.eagertarget.name, (p.secondary and p.secondary.name or "none"), p.parent.table.name </span><span class="cx"> finally: </span><span class="cx"> del recursion_stack[self.parent.table] </span><ins>+ self._eager_chained = True </ins><span class="cx"> </span><span class="cx"> def _aliasize_orderby(self, orderby, copy=True): </span><span class="cx"> if copy: </span><span class="lines">@@ -808,11 +815,15 @@ </span><span class="cx"> def setup(self, key, statement, eagertable=None, **options): </span><span class="cx"> """add a left outer join to the statement thats being constructed""" </span><span class="cx"> </span><ins>+ # initialize the eager chains late in the game + self._create_eager_chain() + </ins><span class="cx"> if hasattr(statement, '_outerjoin'): </span><span class="cx"> towrap = statement._outerjoin </span><span class="cx"> else: </span><span class="cx"> towrap = self.parent.table </span><span class="cx"> </span><ins>+ # print "hello, towrap", str(towrap) </ins><span class="cx"> if self.secondaryjoin is not None: </span><span class="cx"> statement._outerjoin = sql.outerjoin(towrap, self.eagersecondary, self.eagerprimary).outerjoin(self.eagertarget, self.eagersecondaryjoin) </span><span class="cx"> if self.order_by is False and self.secondary.default_order_by() is not None: </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyschemapy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/schema.py (1012 => 1013)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/schema.py 2006-02-21 03:01:43 UTC (rev 1012) +++ sqlalchemy/trunk/lib/sqlalchemy/schema.py 2006-02-22 00:28:59 UTC (rev 1013) </span><span class="lines">@@ -154,6 +154,12 @@ </span><span class="cx"> ["%s=%s" % (k, repr(getattr(self, k))) for k in ['schema']] </span><span class="cx"> , ',\n') </span><span class="cx"> </span><ins>+ def __str__(self): + if self.schema is None: + return self.name + else: + return self.schema + "." + self.name + </ins><span class="cx"> def hash_key(self): </span><span class="cx"> return "Table(%s)" % string.join( </span><span class="cx"> [repr(self.name)] + [self.engine.hash_key()] + </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemysqlpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/sql.py (1012 => 1013)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/sql.py 2006-02-21 03:01:43 UTC (rev 1012) +++ sqlalchemy/trunk/lib/sqlalchemy/sql.py 2006-02-22 00:28:59 UTC (rev 1013) </span><span class="lines">@@ -870,7 +870,7 @@ </span><span class="cx"> crit.append(secondary._get_col_by_original(fk.column) == fk.parent) </span><span class="cx"> self.foreignkey = fk.parent </span><span class="cx"> if len(crit) == 0: </span><del>- raise ArgumentError("Cant find any foreign key relationships between '%s' (%s) and '%s' (%s)" % (primary.name, repr(primary), secondary.name, repr(secondary))) </del><ins>+ raise ArgumentError("Cant find any foreign key relationships between '%s' and '%s'" % (primary.name, secondary.name)) </ins><span class="cx"> elif len(crit) == 1: </span><span class="cx"> return (crit[0]) </span><span class="cx"> else: </span></span></pre></div> <a id="sqlalchemytrunktesteagertest1py"></a> <div class="addfile"><h4>Added: sqlalchemy/trunk/test/eagertest1.py (1012 => 1013)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/eagertest1.py 2006-02-21 03:01:43 UTC (rev 1012) +++ sqlalchemy/trunk/test/eagertest1.py 2006-02-22 00:28:59 UTC (rev 1013) </span><span class="lines">@@ -0,0 +1,60 @@ </span><ins>+from sqlalchemy import * + +class Part(object):pass +class Design(object):pass +class DesignType(object):pass +class InheritedPart(object):pass + +engine = create_engine('sqlite://', echo=True) + +designType = Table('design_types', engine, + Column('design_type_id', Integer, primary_key=True), + ) + +design =Table('design', engine, + Column('design_id', Integer, primary_key=True), + Column('design_type_id', Integer, ForeignKey('design_types.design_type_id'))) + +part = Table('parts', engine, + Column('part_id', Integer, primary_key=True), + Column('design_id', Integer, ForeignKey('design.design_id')), + Column('design_type_id', Integer, ForeignKey('design_types.design_type_id'))) + +inheritedPart = Table('inherited_part', engine, + Column('ip_id', Integer, primary_key=True), + Column('part_id', Integer, ForeignKey('parts.part_id')), + Column('design_id', Integer, ForeignKey('design.design_id')), + ) + +designType.create() +design.create() +part.create() +inheritedPart.create() + +assign_mapper(Part, part) + +assign_mapper(InheritedPart, inheritedPart, properties=dict( + part=relation(Part, lazy=False) +)) + +assign_mapper(Design, design, properties=dict( + parts=relation(Part, private=True, backref="design"), + inheritedParts=relation(InheritedPart, private=True, backref="design"), +)) + +assign_mapper(DesignType, designType, properties=dict( +# designs=relation(Design, private=True, backref="type"), +)) + +Design.mapper.add_property("type", relation(DesignType, lazy=False, backref="designs")) +Part.mapper.add_property("design", relation(Design, lazy=False, backref="parts")) +#Part.mapper.add_property("designType", relation(DesignType)) + +d = Design() +objectstore.commit() +objectstore.clear() +print "lets go !\n\n\n" +x = Design.get(1) +x.inheritedParts + + </ins></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-02-22 07:46:32
|
<!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>[1011] sqlalchemy/trunk/test: working on postupdate idea, refactoring to dependency processing</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1011</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-02-20 20:57:38 -0600 (Mon, 20 Feb 2006)</dd> </dl> <h3>Log Message</h3> <pre>working on postupdate idea, refactoring to dependency processing</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemymapping__init__py">sqlalchemy/trunk/lib/sqlalchemy/mapping/__init__.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemymappingmapperpy">sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemymappingobjectstorepy">sqlalchemy/trunk/lib/sqlalchemy/mapping/objectstore.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemymappingpropertiespy">sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py</a></li> <li><a href="#sqlalchemytrunktestcyclespy">sqlalchemy/trunk/test/cycles.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemymapping__init__py"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/__init__.py (1010 => 1011)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/__init__.py 2006-02-20 19:45:08 UTC (rev 1010) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/__init__.py 2006-02-21 02:57:38 UTC (rev 1011) </span><span class="lines">@@ -88,23 +88,8 @@ </span><span class="cx"> name into a non-deferred (regular column) load. Used with mapper.options.""" </span><span class="cx"> return DeferredOption(name, defer=False) </span><span class="cx"> </span><del>-def object_mapper(object): - """given an object, returns the primary Mapper associated with the object - or the object's class.""" - return class_mapper(object.__class__) </del><span class="cx"> </span><del>-def class_mapper(class_): - """given a class, returns the primary Mapper associated with the class.""" - return mapper_registry[class_] - try: - return mapper_registry[class_] - except KeyError: - pass - except AttributeError: - pass - raise InvalidRequestError("Class '%s' has no mapper associated with it" % class_.__name__) </del><span class="cx"> </span><del>- </del><span class="cx"> def assign_mapper(class_, *args, **params): </span><span class="cx"> params.setdefault("is_primary", True) </span><span class="cx"> if not isinstance(getattr(class_, '__init__'), types.MethodType): </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymappingmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py (1010 => 1011)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-02-20 19:45:08 UTC (rev 1010) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-02-21 02:57:38 UTC (rev 1011) </span><span class="lines">@@ -893,6 +893,22 @@ </span><span class="cx"> return obj.hash_key() </span><span class="cx"> else: </span><span class="cx"> return repr(obj) </span><ins>+ +def object_mapper(object): + """given an object, returns the primary Mapper associated with the object + or the object's class.""" + return class_mapper(object.__class__) + +def class_mapper(class_): + """given a class, returns the primary Mapper associated with the class.""" + return mapper_registry[class_] + try: + return mapper_registry[class_] + except KeyError: + pass + except AttributeError: + pass + raise InvalidRequestError("Class '%s' has no mapper associated with it" % class_.__name__) </ins><span class="cx"> </span><span class="cx"> </span><span class="cx"> </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymappingobjectstorepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/objectstore.py (1010 => 1011)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/objectstore.py 2006-02-20 19:45:08 UTC (rev 1010) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/objectstore.py 2006-02-21 02:57:38 UTC (rev 1011) </span><span class="lines">@@ -454,8 +454,9 @@ </span><span class="cx"> self.dependencies = {} </span><span class="cx"> self.tasks = {} </span><span class="cx"> self.saved_histories = util.HashSet() </span><del>- - def register_object(self, obj, isdelete = False, listonly = False, **kwargs): </del><ins>+ self.__modified = False + + def register_object(self, obj, isdelete = False, listonly = False, postupdate=False, **kwargs): </ins><span class="cx"> """adds an object to this UOWTransaction to be updated in the database. </span><span class="cx"> </span><span class="cx"> 'isdelete' indicates whether the object is to be deleted or saved (update/inserted). </span><span class="lines">@@ -474,15 +475,19 @@ </span><span class="cx"> self.mappers.append(mapper) </span><span class="cx"> task = self.get_task_by_mapper(mapper) </span><span class="cx"> </span><ins>+ if postupdate: + mod = task.append_postupdate(obj) + self.__modified = self.__modified or mod + return + </ins><span class="cx"> # for a cyclical task, things need to be sorted out already, </span><span class="cx"> # so this object should have already been added to the appropriate sub-task </span><span class="cx"> # can put an assertion here to make sure.... </span><span class="cx"> if task.circular: </span><span class="cx"> return </span><span class="cx"> </span><del>- if obj not in task.objects: - self.__modified = True - task.append(obj, listonly, isdelete=isdelete, **kwargs) </del><ins>+ mod = task.append(obj, listonly, isdelete=isdelete, **kwargs) + self.__modified = self.__modified or mod </ins><span class="cx"> </span><span class="cx"> def unregister_object(self, obj): </span><span class="cx"> mapper = object_mapper(obj) </span><span class="lines">@@ -665,16 +670,24 @@ </span><span class="cx"> dependent operations at the per-object instead of per-task level. """ </span><span class="cx"> try: </span><span class="cx"> rec = self.objects[obj] </span><ins>+ retval = False </ins><span class="cx"> except KeyError: </span><span class="cx"> rec = UOWTaskElement(obj) </span><span class="cx"> self.objects[obj] = rec </span><ins>+ retval = True </ins><span class="cx"> if not listonly: </span><span class="cx"> rec.listonly = False </span><span class="cx"> if childtask: </span><span class="cx"> rec.childtasks.append(childtask) </span><span class="cx"> if isdelete: </span><span class="cx"> rec.isdelete = True </span><del>- </del><ins>+ return retval + + def append_postupdate(self, obj): + # postupdates are UPDATED immeditely (for now) + self.mapper.save_obj([obj], self.uowtransaction, postupdate=True) + return True + </ins><span class="cx"> def delete(self, obj): </span><span class="cx"> try: </span><span class="cx"> del self.objects[obj] </span><span class="lines">@@ -974,6 +987,9 @@ </span><span class="cx"> for child in self.childtasks: </span><span class="cx"> header(buf, _indent() + " |- Child tasks\n") </span><span class="cx"> child._dump(buf, indent + 1) </span><ins>+# for obj in self.postupdate: +# header(buf, _indent() + " |- Post Update objects\n") +# buf.write(_repr(obj) + "\n") </ins><span class="cx"> for element in self.todelete_elements(): </span><span class="cx"> for task in element.childtasks: </span><span class="cx"> header(buf, _indent() + " |- Delete subelements of UOWTaskElement(%s)\n" % id(element)) </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymappingpropertiespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py (1010 => 1011)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py 2006-02-20 19:45:08 UTC (rev 1010) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py 2006-02-21 02:57:38 UTC (rev 1011) </span><span class="lines">@@ -358,14 +358,20 @@ </span><span class="cx"> uowcommit.register_processor(stub, self, self.parent, True) </span><span class="cx"> elif self.direction == PropertyLoader.ONETOMANY: </span><span class="cx"> if self.post_update: </span><del>- raise InvalidRequestError("post_update not yet supported with one-to-many relation") - uowcommit.register_dependency(self.parent, self.mapper) - uowcommit.register_processor(self.parent, self, self.parent, False) - uowcommit.register_processor(self.parent, self, self.parent, True) </del><ins>+ stub = PropertyLoader.MapperStub(self.mapper) + uowcommit.register_dependency(self.mapper, stub) + uowcommit.register_dependency(self.parent, stub) + uowcommit.register_processor(stub, self, self.parent, False) + uowcommit.register_processor(stub, self, self.parent, True) + else: + uowcommit.register_dependency(self.parent, self.mapper) + uowcommit.register_processor(self.parent, self, self.parent, False) + uowcommit.register_processor(self.parent, self, self.parent, True) </ins><span class="cx"> elif self.direction == PropertyLoader.MANYTOONE: </span><span class="cx"> if self.post_update: </span><span class="cx"> stub = PropertyLoader.MapperStub(self.mapper) </span><span class="cx"> uowcommit.register_dependency(self.mapper, stub) </span><ins>+ uowcommit.register_dependency(self.parent, stub) </ins><span class="cx"> uowcommit.register_processor(stub, self, self.parent, False) </span><span class="cx"> uowcommit.register_processor(stub, self, self.parent, True) </span><span class="cx"> else: </span><span class="lines">@@ -433,12 +439,12 @@ </span><span class="cx"> statement = self.secondary.insert() </span><span class="cx"> statement.execute(*secondary_insert) </span><span class="cx"> elif self.direction == PropertyLoader.MANYTOONE and delete: </span><del>- # head object is being deleted, and we manage a foreign key object. - # dont have to do anything to it. </del><span class="cx"> if self.post_update: </span><ins>+ # post_update means we have to update our row to not reference the child object + # before we can DELETE the row </ins><span class="cx"> for obj in deplist: </span><span class="cx"> self._synchronize(obj, None, None, True) </span><del>- task.mapper.save_obj([obj], uowcommit, postupdate=True) </del><ins>+ uowcommit.register_object(obj, postupdate=True) </ins><span class="cx"> elif self.direction == PropertyLoader.ONETOMANY and delete: </span><span class="cx"> # head object is being deleted, and we manage its list of child objects </span><span class="cx"> # the child objects have to have their foreign key to the parent set to NULL </span><span class="lines">@@ -450,7 +456,7 @@ </span><span class="cx"> childlist = getlist(obj, False) </span><span class="cx"> for child in childlist.deleted_items() + childlist.unchanged_items(): </span><span class="cx"> self._synchronize(obj, child, None, True) </span><del>- uowcommit.register_object(child) </del><ins>+ uowcommit.register_object(child, postupdate=self.post_update) </ins><span class="cx"> elif self.association is not None: </span><span class="cx"> # manage association objects. </span><span class="cx"> for obj in deplist: </span><span class="lines">@@ -488,21 +494,16 @@ </span><span class="cx"> #print "DELETE ASSOC OBJ", repr(child) </span><span class="cx"> uowcommit.register_object(child, isdelete=True) </span><span class="cx"> else: </span><del>- for obj in deplist: </del><ins>+ for obj in deplist: + childlist = getlist(obj, passive=True) + if childlist is not None: + for child in childlist.added_items(): + self._synchronize(obj, child, None, False) + if self.direction == PropertyLoader.ONETOMANY and child is not None: + uowcommit.register_object(child, postupdate=self.post_update) </ins><span class="cx"> if self.direction == PropertyLoader.MANYTOONE: </span><del>- uowcommit.register_object(obj) - childlist = getlist(obj, passive=True) - if childlist is None: continue - for child in childlist.added_items(): - self._synchronize(obj, child, None, False) - if self.direction == PropertyLoader.ONETOMANY and child is not None: - if self.post_update: - task.mapper.save_obj([child],uowcommit, postupdate=True) - else: - uowcommit.register_object(child) - if self.post_update: - task.mapper.save_obj([obj], uowcommit, postupdate=True) - if self.direction != PropertyLoader.MANYTOONE or len(childlist.added_items()) == 0: </del><ins>+ uowcommit.register_object(obj, postupdate=self.post_update) + if self.direction != PropertyLoader.MANYTOONE: </ins><span class="cx"> for child in childlist.deleted_items(): </span><span class="cx"> if not self.private: </span><span class="cx"> self._synchronize(obj, child, None, True) </span></span></pre></div> <a id="sqlalchemytrunktestcyclespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/cycles.py (1010 => 1011)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/cycles.py 2006-02-20 19:45:08 UTC (rev 1010) +++ sqlalchemy/trunk/test/cycles.py 2006-02-21 02:57:38 UTC (rev 1011) </span><span class="lines">@@ -238,8 +238,8 @@ </span><span class="cx"> </span><span class="cx"> Ball.mapper = mapper(Ball, ball) </span><span class="cx"> Person.mapper = mapper(Person, person, properties= dict( </span><del>- balls = relation(Ball.mapper, primaryjoin=ball.c.person_id==person.c.id, foreignkey=ball.c.person_id), - favorateBall = relation(Ball.mapper, primaryjoin=person.c.favoriteBall_id==ball.c.id, foreignkey=person.c.favoriteBall_id), </del><ins>+ balls = relation(Ball.mapper, primaryjoin=ball.c.person_id==person.c.id, foreignkey=ball.c.person_id, post_update=False, private=True), + favorateBall = relation(Ball.mapper, primaryjoin=person.c.favoriteBall_id==ball.c.id, foreignkey=person.c.favoriteBall_id, post_update=True), </ins><span class="cx"> ) </span><span class="cx"> ) </span><span class="cx"> </span><span class="lines">@@ -248,8 +248,14 @@ </span><span class="cx"> b = Ball() </span><span class="cx"> p = Person() </span><span class="cx"> p.balls.append(b) </span><ins>+ p.balls.append(Ball()) + p.balls.append(Ball()) + p.balls.append(Ball()) </ins><span class="cx"> p.favorateBall = b </span><span class="cx"> objectstore.commit() </span><ins>+ + objectstore.delete(p) + objectstore.commit() </ins><span class="cx"> </span><span class="cx"> </span><span class="cx"> if __name__ == "__main__": </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-02-22 07:46:28
|
<!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>[1010] sqlalchemy/trunk/test: merged eager loading overhaul rev 1001:1009</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1010</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-02-20 13:45:08 -0600 (Mon, 20 Feb 2006)</dd> </dl> <h3>Log Message</h3> <pre>merged eager loading overhaul rev 1001:1009 this includes: sql.Alias object keeps track of the immediate thing it aliased as well as the ultimate non-aliased (usually a Table) object, so that proxied columns can have a "parent" attribute some cleanup to SelectBaseMixin.order_by_clause to allow easier access, needs more cleanup engine has been making two ResultProxies all this time, added "return_raw" quickie flag to disable that some cleanup to _get_col_by_original so that it also works for oid columns, new eager load stuff more aggressively aliaseses orderby's so this was needed EagerLoader now makes "chains" of unique aliased eager loaders in all cases. no need for use_alias/selectalias anymore since it aliases every time. properly detects recursive eager loads and terminates them with a lazyloader, instead of raising an exception. totally simplified setup() and init() is more straightforward and has a single codepath now instead of two or three.</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyansisqlpy">sqlalchemy/trunk/lib/sqlalchemy/ansisql.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyenginepy">sqlalchemy/trunk/lib/sqlalchemy/engine.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemymappingpropertiespy">sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyschemapy">sqlalchemy/trunk/lib/sqlalchemy/schema.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemysqlpy">sqlalchemy/trunk/lib/sqlalchemy/sql.py</a></li> <li><a href="#sqlalchemytrunktestmapperpy">sqlalchemy/trunk/test/mapper.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemyansisqlpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/ansisql.py (1009 => 1010)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/ansisql.py 2006-02-20 19:31:49 UTC (rev 1009) +++ sqlalchemy/trunk/lib/sqlalchemy/ansisql.py 2006-02-20 19:45:08 UTC (rev 1010) </span><span class="lines">@@ -239,8 +239,8 @@ </span><span class="cx"> return self.engine.bindtemplate % name </span><span class="cx"> </span><span class="cx"> def visit_alias(self, alias): </span><del>- self.froms[alias] = self.get_from_text(alias.selectable) + " AS " + alias.name - self.strings[alias] = self.get_str(alias.selectable) </del><ins>+ self.froms[alias] = self.get_from_text(alias.original) + " AS " + alias.name + self.strings[alias] = self.get_str(alias.original) </ins><span class="cx"> </span><span class="cx"> def visit_select(self, select): </span><span class="cx"> </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyenginepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/engine.py (1009 => 1010)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine.py 2006-02-20 19:31:49 UTC (rev 1009) +++ sqlalchemy/trunk/lib/sqlalchemy/engine.py 2006-02-20 19:45:08 UTC (rev 1010) </span><span class="lines">@@ -546,7 +546,7 @@ </span><span class="cx"> else: </span><span class="cx"> parameters = parameters.values() </span><span class="cx"> </span><del>- self.execute(statement, parameters, connection=connection, cursor=cursor) </del><ins>+ self.execute(statement, parameters, connection=connection, cursor=cursor, return_raw=True) </ins><span class="cx"> return cursor </span><span class="cx"> </span><span class="cx"> self.pre_exec(proxy, compiled, parameters, **kwargs) </span><span class="lines">@@ -555,7 +555,7 @@ </span><span class="cx"> self.post_exec(proxy, compiled, parameters, **kwargs) </span><span class="cx"> return ResultProxy(cursor, self, typemap=compiled.typemap) </span><span class="cx"> </span><del>- def execute(self, statement, parameters, connection=None, cursor=None, echo=None, typemap=None, commit=False, **kwargs): </del><ins>+ def execute(self, statement, parameters, connection=None, cursor=None, echo=None, typemap=None, commit=False, return_raw=False, **kwargs): </ins><span class="cx"> """executes the given string-based SQL statement with the given parameters. </span><span class="cx"> </span><span class="cx"> The parameters can be a dictionary or a list, or a list of dictionaries or lists, depending </span><span class="lines">@@ -606,7 +606,10 @@ </span><span class="cx"> except: </span><span class="cx"> self.do_rollback(connection) </span><span class="cx"> raise </span><del>- return ResultProxy(cursor, self, typemap=typemap) </del><ins>+ if return_raw: + return cursor + else: + return ResultProxy(cursor, self, typemap=typemap) </ins><span class="cx"> </span><span class="cx"> def _execute(self, c, statement, parameters): </span><span class="cx"> try: </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymappingpropertiespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py (1009 => 1010)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py 2006-02-20 19:31:49 UTC (rev 1009) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py 2006-02-20 19:45:08 UTC (rev 1010) </span><span class="lines">@@ -107,7 +107,7 @@ </span><span class="cx"> </span><span class="cx"> """describes an object property that holds a single item or list of items that correspond </span><span class="cx"> to a related database table.""" </span><del>- def __init__(self, argument, secondary, primaryjoin, secondaryjoin, foreignkey=None, uselist=None, private=False, association=None, use_alias=False, selectalias=None, order_by=False, attributeext=None, backref=None, is_backref=False, post_update=False): </del><ins>+ def __init__(self, argument, secondary, primaryjoin, secondaryjoin, foreignkey=None, uselist=None, private=False, association=None, use_alias=None, selectalias=None, order_by=False, attributeext=None, backref=None, is_backref=False, post_update=False): </ins><span class="cx"> self.uselist = uselist </span><span class="cx"> self.argument = argument </span><span class="cx"> self.secondary = secondary </span><span class="lines">@@ -127,11 +127,10 @@ </span><span class="cx"> </span><span class="cx"> self.private = private </span><span class="cx"> self.association = association </span><del>- if isinstance(selectalias, str): - print "'selectalias' argument to property is deprecated. please use 'use_alias=True'" - self.use_alias = True - else: - self.use_alias = use_alias </del><ins>+ if selectalias is not None: + print "'selectalias' argument to relation() is deprecated. eager loads automatically alias-ize tables now." + if use_alias is not None: + print "'use_alias' argument to relation() is deprecated. eager loads automatically alias-ize tables now." </ins><span class="cx"> self.order_by = order_by </span><span class="cx"> self.attributeext=attributeext </span><span class="cx"> self.backref = backref </span><span class="lines">@@ -289,7 +288,6 @@ </span><span class="cx"> elif self.association is not None: </span><span class="cx"> c = self.mapper._get_criterion(key, value) & self.primaryjoin </span><span class="cx"> return c.copy_container() </span><del>- </del><span class="cx"> return None </span><span class="cx"> </span><span class="cx"> def register_deleted(self, obj, uow): </span><span class="lines">@@ -743,107 +741,81 @@ </span><span class="cx"> </span><span class="cx"> if recursion_stack is None: </span><span class="cx"> recursion_stack = {} </span><del>- - if self.use_alias: - pass - - # figure out tables in the various join clauses we have, because user-defined - # whereclauses that reference the same tables will be converted to use - # aliases of those tables - self.to_alias = util.HashSet() - [self.to_alias.append(f) for f in self.primaryjoin._get_from_objects()] - if self.secondaryjoin is not None: - [self.to_alias.append(f) for f in self.secondaryjoin._get_from_objects()] - try: - del self.to_alias[parent.table] - except KeyError: - pass </del><span class="cx"> </span><del>- # if this eagermapper is to select using an "alias" to isolate it from other - # eager mappers against the same table, we have to redefine our secondary - # or primary join condition to reference the aliased table (and the order_by). - # else we set up the target clause objects as what they are defined in the - # superclass. - if self.use_alias: - self.eagertarget = self.target.alias() - aliasizer = Aliasizer(self.target, aliases={self.target:self.eagertarget}) - if self.secondaryjoin is not None: - self.eagersecondary = self.secondaryjoin.copy_container() - self.eagersecondary.accept_visitor(aliasizer) - self.eagerprimary = self.primaryjoin.copy_container() - self.eagerprimary.accept_visitor(aliasizer) - else: - self.eagerprimary = self.primaryjoin.copy_container() - self.eagerprimary.accept_visitor(aliasizer) - if self.order_by: - self.eager_order_by = [o.copy_container() for o in util.to_list(self.order_by)] - for i in range(0, len(self.eager_order_by)): - if isinstance(self.eager_order_by[i], schema.Column): - self.eager_order_by[i] = self.eagertarget._get_col_by_original(self.eager_order_by[i]) - else: - self.eager_order_by[i].accept_visitor(aliasizer) - else: - self.eager_order_by = self.order_by </del><ins>+ self.eagertarget = self.target.alias() + if self.secondary: + self.eagersecondary = self.secondary.alias() + self.aliasizer = Aliasizer(self.target, self.secondary, aliases={ + self.target:self.eagertarget, + self.secondary:self.eagersecondary + }) + self.eagersecondaryjoin = self.secondaryjoin.copy_container() + self.eagersecondaryjoin.accept_visitor(self.aliasizer) + self.eagerprimary = self.primaryjoin.copy_container() + self.eagerprimary.accept_visitor(self.aliasizer) + else: + self.aliasizer = Aliasizer(self.target, aliases={self.target:self.eagertarget}) + self.eagerprimary = self.primaryjoin.copy_container() + self.eagerprimary.accept_visitor(self.aliasizer) + + if self.order_by: + self.eager_order_by = self._aliasize_orderby(self.order_by) + else: + self.eager_order_by = None </ins><span class="cx"> </span><del>- # we have to propigate the "use_alias" fact into - # any sub-mappers that are also eagerloading so that they create a unique tablename - # as well. this copies our child mapper and replaces any eager properties on the - # new mapper with an equivalent eager property, just containing use_alias=True - eagerprops = [] - for key, prop in self.mapper.props.iteritems(): - if isinstance(prop, EagerLoader) and not prop.use_alias: - eagerprops.append(prop) - if len(eagerprops): - recursion_stack[self] = True - self.mapper = self.mapper.copy() - try: - for prop in eagerprops: - p = prop.copy() - p.use_alias=True - - self.mapper.props[prop.key] = p - - if recursion_stack.has_key(prop): - raise ArgumentError("Circular eager load relationship detected on " + str(self.mapper) + " " + key + repr(self.mapper.props)) - - p.do_init_subclass(prop.key, prop.parent, recursion_stack) - - p.eagerprimary = p.eagerprimary.copy_container() - aliasizer = Aliasizer(p.parent.table, aliases={p.parent.table:self.eagertarget}) - p.eagerprimary.accept_visitor(aliasizer) - finally: - del recursion_stack[self] - </del><ins>+ eagerprops = [] + # create a new "eager chain", starting from this eager loader and descending downwards + # through all sub-eagerloaders. this will copy all those eagerloaders and have them set up + # aliases distinct to this eager chain. if a recursive relationship to any of the tables is detected, + # the chain will terminate by copying that eager loader into a lazy loader. + for key, prop in self.mapper.props.iteritems(): + if isinstance(prop, EagerLoader): + eagerprops.append(prop) + if len(eagerprops): + recursion_stack[self.parent.table] = True + self.mapper = self.mapper.copy() + try: + for prop in eagerprops: + if recursion_stack.has_key(prop.target): + # recursion - set the relationship as a LazyLoader + p = EagerLazyOption(None, False).create_prop(self.mapper, prop.key) + continue + p = prop.copy() + self.mapper.props[prop.key] = p + #print "we are:", id(self), self.target.name, (self.secondary and self.secondary.name or "None"), self.parent.table.name + #print "prop is",id(prop), prop.target.name, (prop.secondary and prop.secondary.name or "None"), prop.parent.table.name + p.do_init_subclass(prop.key, prop.parent, recursion_stack) + p.eagerprimary = p.eagerprimary.copy_container() + aliasizer = Aliasizer(p.parent.table, aliases={p.parent.table:self.eagertarget}) + p.eagerprimary.accept_visitor(aliasizer) + #print "new eagertqarget", p.eagertarget.name, (p.secondary and p.secondary.name or "none"), p.parent.table.name + finally: + del recursion_stack[self.parent.table] + + def _aliasize_orderby(self, orderby, copy=True): + if copy: + orderby = [o.copy_container() for o in util.to_list(orderby)] </ins><span class="cx"> else: </span><del>- self.eagertarget = self.target - self.eagerprimary = self.primaryjoin - self.eagersecondary = self.secondaryjoin - self.eager_order_by = self.order_by - - def setup(self, key, statement, recursion_stack = None, eagertable=None, **options): </del><ins>+ orderby = util.to_list(orderby) + for i in range(0, len(orderby)): + if isinstance(orderby[i], schema.Column): + orderby[i] = self.eagertarget._get_col_by_original(orderby[i]) + else: + orderby[i].accept_visitor(self.aliasizer) + return orderby + + def setup(self, key, statement, eagertable=None, **options): </ins><span class="cx"> """add a left outer join to the statement thats being constructed""" </span><span class="cx"> </span><del>- if recursion_stack is None: - recursion_stack = {} - - if statement.whereclause is not None: - # "aliasize" the tables referenced in the user-defined whereclause to not - # collide with the tables used by the eager load - # note that we arent affecting the mapper's table, nor our own primary or secondary joins - aliasizer = Aliasizer(*self.to_alias) - statement.whereclause.accept_visitor(aliasizer) - for alias in aliasizer.aliases.values(): - statement.append_from(alias) - </del><span class="cx"> if hasattr(statement, '_outerjoin'): </span><span class="cx"> towrap = statement._outerjoin </span><span class="cx"> else: </span><span class="cx"> towrap = self.parent.table </span><span class="cx"> </span><span class="cx"> if self.secondaryjoin is not None: </span><del>- statement._outerjoin = sql.outerjoin(towrap, self.secondary, self.eagerprimary).outerjoin(self.eagertarget, self.eagersecondary) </del><ins>+ statement._outerjoin = sql.outerjoin(towrap, self.eagersecondary, self.eagerprimary).outerjoin(self.eagertarget, self.eagersecondaryjoin) </ins><span class="cx"> if self.order_by is False and self.secondary.default_order_by() is not None: </span><del>- statement.order_by(*self.secondary.default_order_by()) </del><ins>+ statement.order_by(*self.eagersecondary.default_order_by()) </ins><span class="cx"> else: </span><span class="cx"> statement._outerjoin = towrap.outerjoin(self.eagertarget, self.eagerprimary) </span><span class="cx"> if self.order_by is False and self.eagertarget.default_order_by() is not None: </span><span class="lines">@@ -851,16 +823,12 @@ </span><span class="cx"> </span><span class="cx"> if self.eager_order_by: </span><span class="cx"> statement.order_by(*util.to_list(self.eager_order_by)) </span><del>- </del><ins>+ elif getattr(statement, 'order_by_clause', None): + self._aliasize_orderby(statement.order_by_clause, False) + </ins><span class="cx"> statement.append_from(statement._outerjoin) </span><del>- recursion_stack[self] = True - try: - for key, value in self.mapper.props.iteritems(): - if recursion_stack.has_key(value): - raise InvalidRequestError("Circular eager load relationship detected on " + str(self.mapper) + " " + key + repr(self.mapper.props)) - value.setup(key, statement, recursion_stack=recursion_stack, eagertable=self.eagertarget) - finally: - del recursion_stack[self] </del><ins>+ for key, value in self.mapper.props.iteritems(): + value.setup(key, statement, eagertable=self.eagertarget) </ins><span class="cx"> </span><span class="cx"> def execute(self, instance, row, identitykey, imap, isnew): </span><span class="cx"> """receive a row. tell our mapper to look for a new object instance in the row, and attach </span><span class="lines">@@ -884,16 +852,10 @@ </span><span class="cx"> </span><span class="cx"> def _instance(self, row, imap, result_list=None): </span><span class="cx"> """gets an instance from a row, via this EagerLoader's mapper.""" </span><del>- # if we have an alias for our mapper's table via the use_alias - # parameter, we need to translate the - # aliased columns from the incoming row into a new row that maps - # the values against the columns of the mapper's original non-aliased table. - if self.use_alias: - fakerow = {} - fakerow = util.DictDecorator(row) - for c in self.eagertarget.c: - fakerow[c.original] = row[c] - row = fakerow </del><ins>+ fakerow = util.DictDecorator(row) + for c in self.eagertarget.c: + fakerow[c.parent] = row[c] + row = fakerow </ins><span class="cx"> return self.mapper._instance(row, imap, result_list) </span><span class="cx"> </span><span class="cx"> class GenericOption(MapperOption): </span><span class="lines">@@ -918,6 +880,7 @@ </span><span class="cx"> def create_prop(self, mapper, key): </span><span class="cx"> kwargs = util.constructor_args(oldprop) </span><span class="cx"> mapper.set_property(key, class_(**kwargs )) </span><ins>+ </ins><span class="cx"> </span><span class="cx"> class EagerLazyOption(GenericOption): </span><span class="cx"> """an option that switches a PropertyLoader to be an EagerLoader or LazyLoader""" </span><span class="lines">@@ -941,10 +904,6 @@ </span><span class="cx"> newprop = class_.__new__(class_) </span><span class="cx"> newprop.__dict__.update(oldprop.__dict__) </span><span class="cx"> newprop.do_init_subclass(key, mapper) </span><del>- if self.kwargs.get('selectalias', None): - newprop.use_alias = True - elif self.kwargs.get('use_alias', None) is not None: - newprop.use_alias = self.kwargs['use_alias'] </del><span class="cx"> mapper.set_property(key, newprop) </span><span class="cx"> </span><span class="cx"> class DeferredOption(GenericOption): </span><span class="lines">@@ -969,28 +928,26 @@ </span><span class="cx"> for t in tables: </span><span class="cx"> self.tables[t] = t </span><span class="cx"> self.binary = None </span><del>- self.match = False </del><span class="cx"> self.aliases = kwargs.get('aliases', {}) </span><del>- </del><span class="cx"> def get_alias(self, table): </span><span class="cx"> try: </span><span class="cx"> return self.aliases[table] </span><span class="cx"> except: </span><span class="cx"> return self.aliases.setdefault(table, sql.alias(table)) </span><del>- </del><span class="cx"> def visit_compound(self, compound): </span><del>- for i in range(0, len(compound.clauses)): - if isinstance(compound.clauses[i], schema.Column) and self.tables.has_key(compound.clauses[i].table): - compound.clauses[i] = self.get_alias(compound.clauses[i].table)._get_col_by_original(compound.clauses[i]) - self.match = True - </del><ins>+ self.visit_clauselist(compound) + def visit_clauselist(self, clist): + for i in range(0, len(clist.clauses)): + if isinstance(clist.clauses[i], schema.Column) and self.tables.has_key(clist.clauses[i].table): + orig = clist.clauses[i] + clist.clauses[i] = self.get_alias(clist.clauses[i].table)._get_col_by_original(clist.clauses[i]) + if clist.clauses[i] is None: + raise "cant get orig for " + str(orig) + " against table " + orig.table.name + " " + self.get_alias(orig.table).name </ins><span class="cx"> def visit_binary(self, binary): </span><span class="cx"> if isinstance(binary.left, schema.Column) and self.tables.has_key(binary.left.table): </span><span class="cx"> binary.left = self.get_alias(binary.left.table)._get_col_by_original(binary.left) </span><del>- self.match = True </del><span class="cx"> if isinstance(binary.right, schema.Column) and self.tables.has_key(binary.right.table): </span><span class="cx"> binary.right = self.get_alias(binary.right.table)._get_col_by_original(binary.right) </span><del>- self.match = True </del><span class="cx"> </span><span class="cx"> class BinaryVisitor(sql.ClauseVisitor): </span><span class="cx"> def __init__(self, func): </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyschemapy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/schema.py (1009 => 1010)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/schema.py 2006-02-20 19:31:49 UTC (rev 1009) +++ sqlalchemy/trunk/lib/sqlalchemy/schema.py 2006-02-20 19:45:08 UTC (rev 1010) </span><span class="lines">@@ -248,10 +248,12 @@ </span><span class="cx"> self.default = kwargs.pop('default', None) </span><span class="cx"> self.foreign_key = None </span><span class="cx"> self._orig = None </span><ins>+ self._parent = None </ins><span class="cx"> if len(kwargs): </span><span class="cx"> raise ArgumentError("Unknown arguments passed to Column: " + repr(kwargs.keys())) </span><span class="cx"> </span><span class="cx"> original = property(lambda s: s._orig or s) </span><ins>+ parent = property(lambda s:s._parent or s) </ins><span class="cx"> engine = property(lambda s: s.table.engine) </span><span class="cx"> </span><span class="cx"> def __repr__(self): </span><span class="lines">@@ -307,6 +309,7 @@ </span><span class="cx"> c = Column(name or self.name, self.type, fk, self.default, key = name or self.key, primary_key = self.primary_key, nullable = self.nullable, hidden = self.hidden) </span><span class="cx"> c.table = selectable </span><span class="cx"> c._orig = self.original </span><ins>+ c._parent = self </ins><span class="cx"> if not c.hidden: </span><span class="cx"> selectable.columns[c.key] = c </span><span class="cx"> if self.primary_key: </span><span class="lines">@@ -369,7 +372,7 @@ </span><span class="cx"> </span><span class="cx"> def references(self, table): </span><span class="cx"> """returns True if the given table is referenced by this ForeignKey.""" </span><del>- return table._get_col_by_original(self.column) is not None </del><ins>+ return table._get_col_by_original(self.column, False) is not None </ins><span class="cx"> </span><span class="cx"> def _init_column(self): </span><span class="cx"> # ForeignKey inits its remote column as late as possible, so tables can </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemysqlpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/sql.py (1009 => 1010)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/sql.py 2006-02-20 19:31:49 UTC (rev 1009) +++ sqlalchemy/trunk/lib/sqlalchemy/sql.py 2006-02-20 19:45:08 UTC (rev 1010) </span><span class="lines">@@ -522,6 +522,7 @@ </span><span class="cx"> primary_key = property(lambda self:getattr(self, '_primary_key', False)) </span><span class="cx"> foreign_key = property(lambda self:getattr(self, '_foreign_key', False)) </span><span class="cx"> original = property(lambda self:getattr(self, '_original', self)) </span><ins>+ parent = property(lambda self:getattr(self, '_parent', self)) </ins><span class="cx"> columns = property(lambda self:[self]) </span><span class="cx"> def _make_proxy(self, selectable, name=None): </span><span class="cx"> """creates a new ColumnElement representing this ColumnElement as it appears in the select list </span><span class="lines">@@ -563,12 +564,19 @@ </span><span class="cx"> return Join(self, right, isouter = True, *args, **kwargs) </span><span class="cx"> def alias(self, name=None): </span><span class="cx"> return Alias(self, name) </span><del>- def _get_col_by_original(self, column): </del><ins>+ def _get_col_by_original(self, column, raiseerr=True): </ins><span class="cx"> """given a column which is a schema.Column object attached to a schema.Table object </span><span class="cx"> (i.e. an "original" column), return the Column object from this </span><span class="cx"> Selectable which corresponds to that original Column, or None if this Selectable </span><span class="cx"> does not contain the column.""" </span><del>- return self.original_columns.get(column.original, None) </del><ins>+ try: + return self.original_columns[column.original] + except KeyError: + if not raiseerr: + return None + else: + raise InvalidRequestError("cant get orig for " + str(column) + " with table " + column.table.id + " from table " + self.id) + </ins><span class="cx"> def _get_exported_attribute(self, name): </span><span class="cx"> try: </span><span class="cx"> return getattr(self, name) </span><span class="lines">@@ -595,6 +603,8 @@ </span><span class="cx"> for co in column.columns: </span><span class="cx"> cp = self._proxy_column(co) </span><span class="cx"> self._orig_cols[co.original] = cp </span><ins>+ if getattr(self, 'oid_column', None): + self._orig_cols[self.oid_column.original] = self.oid_column </ins><span class="cx"> def _exportable_columns(self): </span><span class="cx"> return [] </span><span class="cx"> def _proxy_column(self, column): </span><span class="lines">@@ -699,6 +709,8 @@ </span><span class="cx"> self.clauses.append(clause) </span><span class="cx"> def accept_visitor(self, visitor): </span><span class="cx"> for c in self.clauses: </span><ins>+ if c is None: + raise "oh weird" + repr(self.clauses) </ins><span class="cx"> c.accept_visitor(visitor) </span><span class="cx"> visitor.visit_clauselist(self) </span><span class="cx"> def _get_from_objects(self): </span><span class="lines">@@ -904,13 +916,17 @@ </span><span class="cx"> </span><span class="cx"> class Alias(FromClause): </span><span class="cx"> def __init__(self, selectable, alias = None): </span><del>- while isinstance(selectable, Alias): - selectable = selectable.selectable </del><ins>+ baseselectable = selectable + while isinstance(baseselectable, Alias): + baseselectable = baseselectable.selectable + self.original = baseselectable </ins><span class="cx"> self.selectable = selectable </span><span class="cx"> if alias is None: </span><del>- n = getattr(selectable, 'name') </del><ins>+ n = getattr(self.original, 'name') </ins><span class="cx"> if n is None: </span><span class="cx"> n = 'anon' </span><ins>+ elif len(n) > 15: + n = n[0:15] </ins><span class="cx"> alias = n + "_" + hex(random.randint(0, 65535))[2:] </span><span class="cx"> self.name = alias </span><span class="cx"> self.id = self.name </span><span class="lines">@@ -949,6 +965,7 @@ </span><span class="cx"> key = property(lambda s: s.name) </span><span class="cx"> _label = property(lambda s: s.name) </span><span class="cx"> original = property(lambda s:s.obj.original) </span><ins>+ parent = property(lambda s:s.obj.parent) </ins><span class="cx"> def accept_visitor(self, visitor): </span><span class="cx"> self.obj.accept_visitor(visitor) </span><span class="cx"> visitor.visit_label(self) </span><span class="lines">@@ -1009,7 +1026,8 @@ </span><span class="cx"> </span><span class="cx"> engine = property(lambda s: s.column.engine) </span><span class="cx"> default_label = property(lambda s:s._label) </span><del>- original = property(lambda self:self.column) </del><ins>+ original = property(lambda self:self.column.original) + parent = property(lambda self:self.column.parent) </ins><span class="cx"> columns = property(lambda self:[self.column]) </span><span class="cx"> </span><span class="cx"> def label(self, name): </span><span class="lines">@@ -1073,6 +1091,9 @@ </span><span class="cx"> self._orig_cols= {} </span><span class="cx"> for c in self.columns: </span><span class="cx"> self._orig_cols[c.original] = c </span><ins>+ oid = self.oid_column + if oid is not None: + self._orig_cols[oid.original] = oid </ins><span class="cx"> return self._orig_cols </span><span class="cx"> </span><span class="cx"> oid_column = property(_oid_col) </span><span class="lines">@@ -1132,13 +1153,18 @@ </span><span class="cx"> if not hasattr(self, attribute): </span><span class="cx"> l = ClauseList(*clauses) </span><span class="cx"> setattr(self, attribute, l) </span><del>- self.append_clause(prefix, l) </del><span class="cx"> else: </span><span class="cx"> getattr(self, attribute).clauses += clauses </span><del>- def append_clause(self, keyword, clause): - if type(clause) == str: - clause = TextClause(clause) - self.clauses.append((keyword, clause)) </del><ins>+ def _get_clauses(self): + # TODO: this is a little stupid. make ORDER BY/GROUP BY keywords handled by + # the compiler, make group_by_clause/order_by_clause regular attributes + x =[] + if getattr(self, 'group_by_clause', None): + x.append(("GROUP BY", self.group_by_clause)) + if getattr(self, 'order_by_clause', None): + x.append(("ORDER BY", self.order_by_clause)) + return x + clauses = property(_get_clauses) </ins><span class="cx"> def select(self, whereclauses = None, **params): </span><span class="cx"> return select([self], whereclauses, **params) </span><span class="cx"> def _get_from_objects(self): </span><span class="lines">@@ -1157,7 +1183,6 @@ </span><span class="cx"> for s in self.selects: </span><span class="cx"> s.group_by(None) </span><span class="cx"> s.order_by(None) </span><del>- self.clauses = [] </del><span class="cx"> group_by = kwargs.get('group_by', None) </span><span class="cx"> if group_by: </span><span class="cx"> self.group_by(*group_by) </span><span class="lines">@@ -1211,7 +1236,6 @@ </span><span class="cx"> # indicates if this select statement is a subquery as a criterion </span><span class="cx"> # inside of a WHERE clause </span><span class="cx"> self.is_where = False </span><del>- self.clauses = [] </del><span class="cx"> </span><span class="cx"> self.distinct = distinct </span><span class="cx"> self._text = None </span></span></pre></div> <a id="sqlalchemytrunktestmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/mapper.py (1009 => 1010)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/mapper.py 2006-02-20 19:31:49 UTC (rev 1009) +++ sqlalchemy/trunk/test/mapper.py 2006-02-20 19:45:08 UTC (rev 1010) </span><span class="lines">@@ -538,7 +538,7 @@ </span><span class="cx"> self.assert_result(l, User, *user_all_result) </span><span class="cx"> objectstore.clear() </span><span class="cx"> m = mapper(Item, orderitems, is_primary=True, properties = dict( </span><del>- keywords = relation(mapper(Keyword, keywords), itemkeywords, lazy = False), </del><ins>+ keywords = relation(mapper(Keyword, keywords), itemkeywords, lazy = False, order_by=[keywords.c.keyword_id]), </ins><span class="cx"> )) </span><span class="cx"> l = m.select((Item.c.item_name=='item 2') | (Item.c.item_name=='item 5') | (Item.c.item_name=='item 3'), order_by=[Item.c.item_id], limit=2) </span><span class="cx"> self.assert_result(l, Item, *[item_keyword_result[1], item_keyword_result[2]]) </span><span class="lines">@@ -617,6 +617,7 @@ </span><span class="cx"> """tests eager loading with two relations simulatneously, from the same table. """ </span><span class="cx"> openorders = alias(orders, 'openorders') </span><span class="cx"> closedorders = alias(orders, 'closedorders') </span><ins>+ ordermapper = mapper(Order, orders) </ins><span class="cx"> m = mapper(User, users, properties = dict( </span><span class="cx"> addresses = relation(mapper(Address, addresses), lazy = False), </span><span class="cx"> open_orders = relation(mapper(Order, openorders), primaryjoin = and_(openorders.c.isopen == 1, users.c.user_id==openorders.c.user_id), lazy = False), </span><span class="lines">@@ -659,7 +660,7 @@ </span><span class="cx"> items = orderitems </span><span class="cx"> </span><span class="cx"> m = mapper(Item, items, properties = dict( </span><del>- keywords = relation(mapper(Keyword, keywords), itemkeywords, lazy=False), </del><ins>+ keywords = relation(mapper(Keyword, keywords), itemkeywords, lazy=False, order_by=[keywords.c.keyword_id]), </ins><span class="cx"> )) </span><span class="cx"> l = m.select() </span><span class="cx"> self.assert_result(l, Item, *item_keyword_result) </span><span class="lines">@@ -678,7 +679,7 @@ </span><span class="cx"> </span><span class="cx"> m = mapper(Item, items, </span><span class="cx"> properties = dict( </span><del>- keywords = relation(mapper(Keyword, keywords), itemkeywords, lazy = False), </del><ins>+ keywords = relation(mapper(Keyword, keywords), itemkeywords, lazy = False, order_by=[keywords.c.keyword_id]), </ins><span class="cx"> )) </span><span class="cx"> </span><span class="cx"> m = mapper(Order, orders, properties = dict( </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-02-22 07:46:25
|
<!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>[1009] sqlalchemy/branches/new_eagerload/lib/sqlalchemy: deprecated use_alias</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1009</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-02-20 13:31:49 -0600 (Mon, 20 Feb 2006)</dd> </dl> <h3>Log Message</h3> <pre>deprecated use_alias orderby/groupby should be cleaned up</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemybranchesnew_eagerloadlibsqlalchemymappingpropertiespy">sqlalchemy/branches/new_eagerload/lib/sqlalchemy/mapping/properties.py</a></li> <li><a href="#sqlalchemybranchesnew_eagerloadlibsqlalchemysqlpy">sqlalchemy/branches/new_eagerload/lib/sqlalchemy/sql.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemybranchesnew_eagerloadlibsqlalchemymappingpropertiespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/new_eagerload/lib/sqlalchemy/mapping/properties.py (1008 => 1009)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/new_eagerload/lib/sqlalchemy/mapping/properties.py 2006-02-20 19:25:17 UTC (rev 1008) +++ sqlalchemy/branches/new_eagerload/lib/sqlalchemy/mapping/properties.py 2006-02-20 19:31:49 UTC (rev 1009) </span><span class="lines">@@ -107,7 +107,7 @@ </span><span class="cx"> </span><span class="cx"> """describes an object property that holds a single item or list of items that correspond </span><span class="cx"> to a related database table.""" </span><del>- def __init__(self, argument, secondary, primaryjoin, secondaryjoin, foreignkey=None, uselist=None, private=False, association=None, use_alias=False, selectalias=None, order_by=False, attributeext=None, backref=None, is_backref=False, post_update=False): </del><ins>+ def __init__(self, argument, secondary, primaryjoin, secondaryjoin, foreignkey=None, uselist=None, private=False, association=None, use_alias=None, selectalias=None, order_by=False, attributeext=None, backref=None, is_backref=False, post_update=False): </ins><span class="cx"> self.uselist = uselist </span><span class="cx"> self.argument = argument </span><span class="cx"> self.secondary = secondary </span><span class="lines">@@ -127,11 +127,10 @@ </span><span class="cx"> </span><span class="cx"> self.private = private </span><span class="cx"> self.association = association </span><del>- if isinstance(selectalias, str): - print "'selectalias' argument to property is deprecated. please use 'use_alias=True'" - self.use_alias = True - else: - self.use_alias = use_alias </del><ins>+ if selectalias is not None: + print "'selectalias' argument to relation() is deprecated. eager loads automatically alias-ize tables now." + if use_alias is not None: + print "'use_alias' argument to relation() is deprecated. eager loads automatically alias-ize tables now." </ins><span class="cx"> self.order_by = order_by </span><span class="cx"> self.attributeext=attributeext </span><span class="cx"> self.backref = backref </span><span class="lines">@@ -289,7 +288,6 @@ </span><span class="cx"> elif self.association is not None: </span><span class="cx"> c = self.mapper._get_criterion(key, value) & self.primaryjoin </span><span class="cx"> return c.copy_container() </span><del>- </del><span class="cx"> return None </span><span class="cx"> </span><span class="cx"> def register_deleted(self, obj, uow): </span><span class="lines">@@ -783,7 +781,6 @@ </span><span class="cx"> p = EagerLazyOption(None, False).create_prop(self.mapper, prop.key) </span><span class="cx"> continue </span><span class="cx"> p = prop.copy() </span><del>- p.use_alias=True </del><span class="cx"> self.mapper.props[prop.key] = p </span><span class="cx"> #print "we are:", id(self), self.target.name, (self.secondary and self.secondary.name or "None"), self.parent.table.name </span><span class="cx"> #print "prop is",id(prop), prop.target.name, (prop.secondary and prop.secondary.name or "None"), prop.parent.table.name </span><span class="lines">@@ -907,10 +904,6 @@ </span><span class="cx"> newprop = class_.__new__(class_) </span><span class="cx"> newprop.__dict__.update(oldprop.__dict__) </span><span class="cx"> newprop.do_init_subclass(key, mapper) </span><del>- if self.kwargs.get('selectalias', None): - newprop.use_alias = True - elif self.kwargs.get('use_alias', None) is not None: - newprop.use_alias = self.kwargs['use_alias'] </del><span class="cx"> mapper.set_property(key, newprop) </span><span class="cx"> </span><span class="cx"> class DeferredOption(GenericOption): </span></span></pre></div> <a id="sqlalchemybranchesnew_eagerloadlibsqlalchemysqlpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/new_eagerload/lib/sqlalchemy/sql.py (1008 => 1009)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/new_eagerload/lib/sqlalchemy/sql.py 2006-02-20 19:25:17 UTC (rev 1008) +++ sqlalchemy/branches/new_eagerload/lib/sqlalchemy/sql.py 2006-02-20 19:31:49 UTC (rev 1009) </span><span class="lines">@@ -1153,10 +1153,11 @@ </span><span class="cx"> if not hasattr(self, attribute): </span><span class="cx"> l = ClauseList(*clauses) </span><span class="cx"> setattr(self, attribute, l) </span><del>- #self.append_clause(prefix, l) </del><span class="cx"> else: </span><span class="cx"> getattr(self, attribute).clauses += clauses </span><span class="cx"> def _get_clauses(self): </span><ins>+ # TODO: this is a little stupid. make ORDER BY/GROUP BY keywords handled by + # the compiler, make group_by_clause/order_by_clause regular attributes </ins><span class="cx"> x =[] </span><span class="cx"> if getattr(self, 'group_by_clause', None): </span><span class="cx"> x.append(("GROUP BY", self.group_by_clause)) </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-02-22 07:46:21
|
<!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>[1008] sqlalchemy/branches/new_eagerload/lib/sqlalchemy/mapping/properties.py: got the petrinet workin (j.yang's test)</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1008</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-02-20 13:25:17 -0600 (Mon, 20 Feb 2006)</dd> </dl> <h3>Log Message</h3> <pre>got the petrinet workin (j.yang's test)</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemybranchesnew_eagerloadlibsqlalchemymappingpropertiespy">sqlalchemy/branches/new_eagerload/lib/sqlalchemy/mapping/properties.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemybranchesnew_eagerloadlibsqlalchemymappingpropertiespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/new_eagerload/lib/sqlalchemy/mapping/properties.py (1007 => 1008)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/new_eagerload/lib/sqlalchemy/mapping/properties.py 2006-02-20 19:05:11 UTC (rev 1007) +++ sqlalchemy/branches/new_eagerload/lib/sqlalchemy/mapping/properties.py 2006-02-20 19:25:17 UTC (rev 1008) </span><span class="lines">@@ -766,32 +766,34 @@ </span><span class="cx"> self.eager_order_by = None </span><span class="cx"> </span><span class="cx"> eagerprops = [] </span><ins>+ # create a new "eager chain", starting from this eager loader and descending downwards + # through all sub-eagerloaders. this will copy all those eagerloaders and have them set up + # aliases distinct to this eager chain. if a recursive relationship to any of the tables is detected, + # the chain will terminate by copying that eager loader into a lazy loader. </ins><span class="cx"> for key, prop in self.mapper.props.iteritems(): </span><span class="cx"> if isinstance(prop, EagerLoader): </span><span class="cx"> eagerprops.append(prop) </span><span class="cx"> if len(eagerprops): </span><del>- recursion_stack[self.target] = True </del><ins>+ recursion_stack[self.parent.table] = True </ins><span class="cx"> self.mapper = self.mapper.copy() </span><span class="cx"> try: </span><span class="cx"> for prop in eagerprops: </span><ins>+ if recursion_stack.has_key(prop.target): + # recursion - set the relationship as a LazyLoader + p = EagerLazyOption(None, False).create_prop(self.mapper, prop.key) + continue </ins><span class="cx"> p = prop.copy() </span><span class="cx"> p.use_alias=True </span><del>- </del><span class="cx"> self.mapper.props[prop.key] = p </span><del>- - print "we are:", id(self), self.target.name, (self.secondary and self.secondary.name or "None"), self.parent.table.name - print "prop is",id(prop), prop.target.name, (prop.secondary and prop.secondary.name or "None"), prop.parent.table.name - if recursion_stack.has_key(prop.target): - raise ArgumentError("Circular eager load relationship detected on " + str(self.mapper) + " " + key + repr(self.mapper.props)) - </del><ins>+ #print "we are:", id(self), self.target.name, (self.secondary and self.secondary.name or "None"), self.parent.table.name + #print "prop is",id(prop), prop.target.name, (prop.secondary and prop.secondary.name or "None"), prop.parent.table.name </ins><span class="cx"> p.do_init_subclass(prop.key, prop.parent, recursion_stack) </span><del>- </del><span class="cx"> p.eagerprimary = p.eagerprimary.copy_container() </span><span class="cx"> aliasizer = Aliasizer(p.parent.table, aliases={p.parent.table:self.eagertarget}) </span><span class="cx"> p.eagerprimary.accept_visitor(aliasizer) </span><del>- print "new eagertqarget", p.eagertarget.name, (p.secondary and p.secondary.name or "none"), p.parent.table.name </del><ins>+ #print "new eagertqarget", p.eagertarget.name, (p.secondary and p.secondary.name or "none"), p.parent.table.name </ins><span class="cx"> finally: </span><del>- del recursion_stack[self.target] </del><ins>+ del recursion_stack[self.parent.table] </ins><span class="cx"> </span><span class="cx"> def _aliasize_orderby(self, orderby, copy=True): </span><span class="cx"> if copy: </span><span class="lines">@@ -881,6 +883,7 @@ </span><span class="cx"> def create_prop(self, mapper, key): </span><span class="cx"> kwargs = util.constructor_args(oldprop) </span><span class="cx"> mapper.set_property(key, class_(**kwargs )) </span><ins>+ </ins><span class="cx"> </span><span class="cx"> class EagerLazyOption(GenericOption): </span><span class="cx"> """an option that switches a PropertyLoader to be an EagerLoader or LazyLoader""" </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-02-22 07:44:02
|
<!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>[1007] sqlalchemy/branches/new_eagerload/test: almost there</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1007</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-02-20 13:05:11 -0600 (Mon, 20 Feb 2006)</dd> </dl> <h3>Log Message</h3> <pre>almost there</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemybranchesnew_eagerloadlibsqlalchemymappingpropertiespy">sqlalchemy/branches/new_eagerload/lib/sqlalchemy/mapping/properties.py</a></li> <li><a href="#sqlalchemybranchesnew_eagerloadlibsqlalchemyschemapy">sqlalchemy/branches/new_eagerload/lib/sqlalchemy/schema.py</a></li> <li><a href="#sqlalchemybranchesnew_eagerloadlibsqlalchemysqlpy">sqlalchemy/branches/new_eagerload/lib/sqlalchemy/sql.py</a></li> <li><a href="#sqlalchemybranchesnew_eagerloadtestmapperpy">sqlalchemy/branches/new_eagerload/test/mapper.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemybranchesnew_eagerloadlibsqlalchemymappingpropertiespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/new_eagerload/lib/sqlalchemy/mapping/properties.py (1006 => 1007)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/new_eagerload/lib/sqlalchemy/mapping/properties.py 2006-02-20 16:34:02 UTC (rev 1006) +++ sqlalchemy/branches/new_eagerload/lib/sqlalchemy/mapping/properties.py 2006-02-20 19:05:11 UTC (rev 1007) </span><span class="lines">@@ -747,31 +747,23 @@ </span><span class="cx"> self.eagertarget = self.target.alias() </span><span class="cx"> if self.secondary: </span><span class="cx"> self.eagersecondary = self.secondary.alias() </span><del>- aliasizer = Aliasizer(self.target, aliases={ </del><ins>+ self.aliasizer = Aliasizer(self.target, self.secondary, aliases={ </ins><span class="cx"> self.target:self.eagertarget, </span><span class="cx"> self.secondary:self.eagersecondary </span><span class="cx"> }) </span><del>- self.eagersecondary = self.secondaryjoin.copy_container() - self.eagersecondary.accept_visitor(aliasizer) </del><ins>+ self.eagersecondaryjoin = self.secondaryjoin.copy_container() + self.eagersecondaryjoin.accept_visitor(self.aliasizer) </ins><span class="cx"> self.eagerprimary = self.primaryjoin.copy_container() </span><del>- self.eagerprimary.accept_visitor(aliasizer) </del><ins>+ self.eagerprimary.accept_visitor(self.aliasizer) </ins><span class="cx"> else: </span><del>- aliasizer = Aliasizer(self.target, aliases={self.target:self.eagertarget}) </del><ins>+ self.aliasizer = Aliasizer(self.target, aliases={self.target:self.eagertarget}) </ins><span class="cx"> self.eagerprimary = self.primaryjoin.copy_container() </span><del>- self.eagerprimary.accept_visitor(aliasizer) </del><ins>+ self.eagerprimary.accept_visitor(self.aliasizer) </ins><span class="cx"> </span><span class="cx"> if self.order_by: </span><del>- print "LALA" - self.eager_order_by = [o.copy_container() for o in util.to_list(self.order_by)] - for i in range(0, len(self.eager_order_by)): - if isinstance(self.eager_order_by[i], schema.Column): - self.eager_order_by[i] = self.eagertarget._get_col_by_original(self.eager_order_by[i]) - print "derp", self.eager_order_by[i] - else: - self.eager_order_by[i].accept_visitor(aliasizer) </del><ins>+ self.eager_order_by = self._aliasize_orderby(self.order_by) </ins><span class="cx"> else: </span><del>- print "HOHO" - self.eager_order_by = self.order_by </del><ins>+ self.eager_order_by = None </ins><span class="cx"> </span><span class="cx"> eagerprops = [] </span><span class="cx"> for key, prop in self.mapper.props.iteritems(): </span><span class="lines">@@ -800,8 +792,19 @@ </span><span class="cx"> print "new eagertqarget", p.eagertarget.name, (p.secondary and p.secondary.name or "none"), p.parent.table.name </span><span class="cx"> finally: </span><span class="cx"> del recursion_stack[self.target] </span><del>- - </del><ins>+ + def _aliasize_orderby(self, orderby, copy=True): + if copy: + orderby = [o.copy_container() for o in util.to_list(orderby)] + else: + orderby = util.to_list(orderby) + for i in range(0, len(orderby)): + if isinstance(orderby[i], schema.Column): + orderby[i] = self.eagertarget._get_col_by_original(orderby[i]) + else: + orderby[i].accept_visitor(self.aliasizer) + return orderby + </ins><span class="cx"> def setup(self, key, statement, eagertable=None, **options): </span><span class="cx"> """add a left outer join to the statement thats being constructed""" </span><span class="cx"> </span><span class="lines">@@ -811,9 +814,9 @@ </span><span class="cx"> towrap = self.parent.table </span><span class="cx"> </span><span class="cx"> if self.secondaryjoin is not None: </span><del>- statement._outerjoin = sql.outerjoin(towrap, self.secondary, self.eagerprimary).outerjoin(self.eagertarget, self.eagersecondary) </del><ins>+ statement._outerjoin = sql.outerjoin(towrap, self.eagersecondary, self.eagerprimary).outerjoin(self.eagertarget, self.eagersecondaryjoin) </ins><span class="cx"> if self.order_by is False and self.secondary.default_order_by() is not None: </span><del>- statement.order_by(*self.secondary.default_order_by()) </del><ins>+ statement.order_by(*self.eagersecondary.default_order_by()) </ins><span class="cx"> else: </span><span class="cx"> statement._outerjoin = towrap.outerjoin(self.eagertarget, self.eagerprimary) </span><span class="cx"> if self.order_by is False and self.eagertarget.default_order_by() is not None: </span><span class="lines">@@ -821,14 +824,8 @@ </span><span class="cx"> </span><span class="cx"> if self.eager_order_by: </span><span class="cx"> statement.order_by(*util.to_list(self.eager_order_by)) </span><del>- elif statement.order_by: - # for i in range(0, len(statement.order_by)): - # if isinstance(statement.order_by[i], schema.Column): - # statement.order_by[i] = self.eagertarget._get_col_by_original(statement.order_by[i]) - # else: - # pass -# statement.order_by[i].accept_visitor(aliasizer) - print "YUP OB", statement.order_by </del><ins>+ elif getattr(statement, 'order_by_clause', None): + self._aliasize_orderby(statement.order_by_clause, False) </ins><span class="cx"> </span><span class="cx"> statement.append_from(statement._outerjoin) </span><span class="cx"> for key, value in self.mapper.props.iteritems(): </span><span class="lines">@@ -935,28 +932,26 @@ </span><span class="cx"> for t in tables: </span><span class="cx"> self.tables[t] = t </span><span class="cx"> self.binary = None </span><del>- self.match = False </del><span class="cx"> self.aliases = kwargs.get('aliases', {}) </span><del>- </del><span class="cx"> def get_alias(self, table): </span><span class="cx"> try: </span><span class="cx"> return self.aliases[table] </span><span class="cx"> except: </span><span class="cx"> return self.aliases.setdefault(table, sql.alias(table)) </span><del>- </del><span class="cx"> def visit_compound(self, compound): </span><del>- for i in range(0, len(compound.clauses)): - if isinstance(compound.clauses[i], schema.Column) and self.tables.has_key(compound.clauses[i].table): - compound.clauses[i] = self.get_alias(compound.clauses[i].table)._get_col_by_original(compound.clauses[i]) - self.match = True - </del><ins>+ self.visit_clauselist(compound) + def visit_clauselist(self, clist): + for i in range(0, len(clist.clauses)): + if isinstance(clist.clauses[i], schema.Column) and self.tables.has_key(clist.clauses[i].table): + orig = clist.clauses[i] + clist.clauses[i] = self.get_alias(clist.clauses[i].table)._get_col_by_original(clist.clauses[i]) + if clist.clauses[i] is None: + raise "cant get orig for " + str(orig) + " against table " + orig.table.name + " " + self.get_alias(orig.table).name </ins><span class="cx"> def visit_binary(self, binary): </span><span class="cx"> if isinstance(binary.left, schema.Column) and self.tables.has_key(binary.left.table): </span><span class="cx"> binary.left = self.get_alias(binary.left.table)._get_col_by_original(binary.left) </span><del>- self.match = True </del><span class="cx"> if isinstance(binary.right, schema.Column) and self.tables.has_key(binary.right.table): </span><span class="cx"> binary.right = self.get_alias(binary.right.table)._get_col_by_original(binary.right) </span><del>- self.match = True </del><span class="cx"> </span><span class="cx"> class BinaryVisitor(sql.ClauseVisitor): </span><span class="cx"> def __init__(self, func): </span></span></pre></div> <a id="sqlalchemybranchesnew_eagerloadlibsqlalchemyschemapy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/new_eagerload/lib/sqlalchemy/schema.py (1006 => 1007)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/new_eagerload/lib/sqlalchemy/schema.py 2006-02-20 16:34:02 UTC (rev 1006) +++ sqlalchemy/branches/new_eagerload/lib/sqlalchemy/schema.py 2006-02-20 19:05:11 UTC (rev 1007) </span><span class="lines">@@ -372,7 +372,7 @@ </span><span class="cx"> </span><span class="cx"> def references(self, table): </span><span class="cx"> """returns True if the given table is referenced by this ForeignKey.""" </span><del>- return table._get_col_by_original(self.column) is not None </del><ins>+ return table._get_col_by_original(self.column, False) is not None </ins><span class="cx"> </span><span class="cx"> def _init_column(self): </span><span class="cx"> # ForeignKey inits its remote column as late as possible, so tables can </span></span></pre></div> <a id="sqlalchemybranchesnew_eagerloadlibsqlalchemysqlpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/new_eagerload/lib/sqlalchemy/sql.py (1006 => 1007)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/new_eagerload/lib/sqlalchemy/sql.py 2006-02-20 16:34:02 UTC (rev 1006) +++ sqlalchemy/branches/new_eagerload/lib/sqlalchemy/sql.py 2006-02-20 19:05:11 UTC (rev 1007) </span><span class="lines">@@ -564,12 +564,19 @@ </span><span class="cx"> return Join(self, right, isouter = True, *args, **kwargs) </span><span class="cx"> def alias(self, name=None): </span><span class="cx"> return Alias(self, name) </span><del>- def _get_col_by_original(self, column): </del><ins>+ def _get_col_by_original(self, column, raiseerr=True): </ins><span class="cx"> """given a column which is a schema.Column object attached to a schema.Table object </span><span class="cx"> (i.e. an "original" column), return the Column object from this </span><span class="cx"> Selectable which corresponds to that original Column, or None if this Selectable </span><span class="cx"> does not contain the column.""" </span><del>- return self.original_columns.get(column.original, None) </del><ins>+ try: + return self.original_columns[column.original] + except KeyError: + if not raiseerr: + return None + else: + raise InvalidRequestError("cant get orig for " + str(column) + " with table " + column.table.id + " from table " + self.id) + </ins><span class="cx"> def _get_exported_attribute(self, name): </span><span class="cx"> try: </span><span class="cx"> return getattr(self, name) </span><span class="lines">@@ -596,6 +603,8 @@ </span><span class="cx"> for co in column.columns: </span><span class="cx"> cp = self._proxy_column(co) </span><span class="cx"> self._orig_cols[co.original] = cp </span><ins>+ if getattr(self, 'oid_column', None): + self._orig_cols[self.oid_column.original] = self.oid_column </ins><span class="cx"> def _exportable_columns(self): </span><span class="cx"> return [] </span><span class="cx"> def _proxy_column(self, column): </span><span class="lines">@@ -700,6 +709,8 @@ </span><span class="cx"> self.clauses.append(clause) </span><span class="cx"> def accept_visitor(self, visitor): </span><span class="cx"> for c in self.clauses: </span><ins>+ if c is None: + raise "oh weird" + repr(self.clauses) </ins><span class="cx"> c.accept_visitor(visitor) </span><span class="cx"> visitor.visit_clauselist(self) </span><span class="cx"> def _get_from_objects(self): </span><span class="lines">@@ -1080,6 +1091,9 @@ </span><span class="cx"> self._orig_cols= {} </span><span class="cx"> for c in self.columns: </span><span class="cx"> self._orig_cols[c.original] = c </span><ins>+ oid = self.oid_column + if oid is not None: + self._orig_cols[oid.original] = oid </ins><span class="cx"> return self._orig_cols </span><span class="cx"> </span><span class="cx"> oid_column = property(_oid_col) </span><span class="lines">@@ -1139,13 +1153,17 @@ </span><span class="cx"> if not hasattr(self, attribute): </span><span class="cx"> l = ClauseList(*clauses) </span><span class="cx"> setattr(self, attribute, l) </span><del>- self.append_clause(prefix, l) </del><ins>+ #self.append_clause(prefix, l) </ins><span class="cx"> else: </span><span class="cx"> getattr(self, attribute).clauses += clauses </span><del>- def append_clause(self, keyword, clause): - if type(clause) == str: - clause = TextClause(clause) - self.clauses.append((keyword, clause)) </del><ins>+ def _get_clauses(self): + x =[] + if getattr(self, 'group_by_clause', None): + x.append(("GROUP BY", self.group_by_clause)) + if getattr(self, 'order_by_clause', None): + x.append(("ORDER BY", self.order_by_clause)) + return x + clauses = property(_get_clauses) </ins><span class="cx"> def select(self, whereclauses = None, **params): </span><span class="cx"> return select([self], whereclauses, **params) </span><span class="cx"> def _get_from_objects(self): </span><span class="lines">@@ -1164,7 +1182,6 @@ </span><span class="cx"> for s in self.selects: </span><span class="cx"> s.group_by(None) </span><span class="cx"> s.order_by(None) </span><del>- self.clauses = [] </del><span class="cx"> group_by = kwargs.get('group_by', None) </span><span class="cx"> if group_by: </span><span class="cx"> self.group_by(*group_by) </span><span class="lines">@@ -1218,7 +1235,6 @@ </span><span class="cx"> # indicates if this select statement is a subquery as a criterion </span><span class="cx"> # inside of a WHERE clause </span><span class="cx"> self.is_where = False </span><del>- self.clauses = [] </del><span class="cx"> </span><span class="cx"> self.distinct = distinct </span><span class="cx"> self._text = None </span></span></pre></div> <a id="sqlalchemybranchesnew_eagerloadtestmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/new_eagerload/test/mapper.py (1006 => 1007)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/new_eagerload/test/mapper.py 2006-02-20 16:34:02 UTC (rev 1006) +++ sqlalchemy/branches/new_eagerload/test/mapper.py 2006-02-20 19:05:11 UTC (rev 1007) </span><span class="lines">@@ -538,7 +538,7 @@ </span><span class="cx"> self.assert_result(l, User, *user_all_result) </span><span class="cx"> objectstore.clear() </span><span class="cx"> m = mapper(Item, orderitems, is_primary=True, properties = dict( </span><del>- keywords = relation(mapper(Keyword, keywords), itemkeywords, lazy = False), </del><ins>+ keywords = relation(mapper(Keyword, keywords), itemkeywords, lazy = False, order_by=[keywords.c.keyword_id]), </ins><span class="cx"> )) </span><span class="cx"> l = m.select((Item.c.item_name=='item 2') | (Item.c.item_name=='item 5') | (Item.c.item_name=='item 3'), order_by=[Item.c.item_id], limit=2) </span><span class="cx"> self.assert_result(l, Item, *[item_keyword_result[1], item_keyword_result[2]]) </span><span class="lines">@@ -660,7 +660,7 @@ </span><span class="cx"> items = orderitems </span><span class="cx"> </span><span class="cx"> m = mapper(Item, items, properties = dict( </span><del>- keywords = relation(mapper(Keyword, keywords), itemkeywords, lazy=False), </del><ins>+ keywords = relation(mapper(Keyword, keywords), itemkeywords, lazy=False, order_by=[keywords.c.keyword_id]), </ins><span class="cx"> )) </span><span class="cx"> l = m.select() </span><span class="cx"> self.assert_result(l, Item, *item_keyword_result) </span><span class="lines">@@ -679,7 +679,7 @@ </span><span class="cx"> </span><span class="cx"> m = mapper(Item, items, </span><span class="cx"> properties = dict( </span><del>- keywords = relation(mapper(Keyword, keywords), itemkeywords, lazy = False), </del><ins>+ keywords = relation(mapper(Keyword, keywords), itemkeywords, lazy = False, order_by=[keywords.c.keyword_id]), </ins><span class="cx"> )) </span><span class="cx"> </span><span class="cx"> m = mapper(Order, orders, properties = dict( </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-02-22 07:39:11
|
<!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>[1006] sqlalchemy/trunk/doc/build/content/datamapping.myt: made 'assign_mapper' doc more explicit</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1006</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-02-20 10:34:02 -0600 (Mon, 20 Feb 2006)</dd> </dl> <h3>Log Message</h3> <pre>made 'assign_mapper' doc more explicit added doc for overriding properties</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunkdocbuildcontentdatamappingmyt">sqlalchemy/trunk/doc/build/content/datamapping.myt</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunkdocbuildcontentdatamappingmyt"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/doc/build/content/datamapping.myt (1005 => 1006)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/doc/build/content/datamapping.myt 2006-02-20 16:13:54 UTC (rev 1005) +++ sqlalchemy/trunk/doc/build/content/datamapping.myt 2006-02-20 16:34:02 UTC (rev 1006) </span><span class="lines">@@ -58,6 +58,7 @@ </span><span class="cx"> </span><span class="cx"> </span><span class="cx"> </&> </span><ins>+ <&|doclib.myt:item, name="attaching", description="Attaching Mappers to their Class"&> </ins><span class="cx"> <p>For convenience's sake, the Mapper can be attached as an attribute on the class itself as well:</p> </span><span class="cx"> <&|formatting.myt:code&> </span><span class="cx"> User.mapper = mapper(User, users) </span><span class="lines">@@ -70,6 +71,25 @@ </span><span class="cx"> userlist = User.select_by(user_id=12) </span><span class="cx"> </&> </span><span class="cx"> <p>Other methods of associating mappers and finder methods with their corresponding classes, such as via common base classes or mixins, can be devised as well. SQLAlchemy does not aim to dictate application architecture and will always allow the broadest variety of architectural patterns, but may include more helper objects and suggested architectures in the future.</p> </span><ins>+ </&> + <&|doclib.myt:item, name="overriding", description="Overriding Properties"&> + <p>A common request is the ability to create custom class properties that override the behavior of setting/getting an attribute. Currently, the easiest way to do this in SQLAlchemy is just how its done normally; define your attribute with a different name, such as "_attribute", and use a property to get/set its value. The mapper just needs to be told of the special name:</p> + <&|formatting.myt:code&> + class MyClass(object): + def _set_email(self, email): + self._email = email + def _get_email(self, email): + return self._email + email = property(_get_email, _set_email) + + m = mapper(MyClass, mytable, properties = { + # map the '_email' attribute to the "email" column + # on the table + '_email': mytable.c.email + }) + </&> + <p>In a later release, SQLAlchemy will also allow _get_email and _set_email to be attached directly to the "email" property created by the mapper, and will also allow this association to occur via decorators.</p> + </&> </ins><span class="cx"> </&> </span><span class="cx"> <&|doclib.myt:item, name="selecting", description="Selecting from a Mapper" &> </span><span class="cx"> <p>There are a variety of ways to select from a mapper. These range from minimalist to explicit. Below is a synopsis of the these methods:</p> </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-02-22 07:36:07
|
<!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>[1005] sqlalchemy/trunk/lib/sqlalchemy/databases/postgres.py: none check for pg1 date/time values</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1005</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-02-20 10:13:54 -0600 (Mon, 20 Feb 2006)</dd> </dl> <h3>Log Message</h3> <pre>none check for pg1 date/time values</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemydatabasespostgrespy">sqlalchemy/trunk/lib/sqlalchemy/databases/postgres.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemydatabasespostgrespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/databases/postgres.py (1004 => 1005)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/databases/postgres.py 2006-02-19 18:01:00 UTC (rev 1004) +++ sqlalchemy/trunk/lib/sqlalchemy/databases/postgres.py 2006-02-20 16:13:54 UTC (rev 1005) </span><span class="lines">@@ -44,7 +44,10 @@ </span><span class="cx"> def convert_bind_param(self, value, engine): </span><span class="cx"> # TODO: perform appropriate postgres1 conversion between Python DateTime/MXDateTime </span><span class="cx"> # this one doesnt seem to work with the "emulation" mode </span><del>- return psycopg.TimestampFromMx(value) </del><ins>+ if value is not None: + return psycopg.TimestampFromMx(value) + else: + return None </ins><span class="cx"> def convert_result_value(self, value, engine): </span><span class="cx"> # TODO: perform appropriate postgres1 conversion between Python DateTime/MXDateTime </span><span class="cx"> return value </span><span class="lines">@@ -57,7 +60,10 @@ </span><span class="cx"> def convert_bind_param(self, value, engine): </span><span class="cx"> # TODO: perform appropriate postgres1 conversion between Python DateTime/MXDateTime </span><span class="cx"> # this one doesnt seem to work with the "emulation" mode </span><del>- return psycopg.DateFromMx(value) </del><ins>+ if value is not None: + return psycopg.DateFromMx(value) + else: + return None </ins><span class="cx"> def convert_result_value(self, value, engine): </span><span class="cx"> # TODO: perform appropriate postgres1 conversion between Python DateTime/MXDateTime </span><span class="cx"> return value </span><span class="lines">@@ -70,7 +76,10 @@ </span><span class="cx"> def convert_bind_param(self, value, engine): </span><span class="cx"> # TODO: perform appropriate postgres1 conversion between Python DateTime/MXDateTime </span><span class="cx"> # this one doesnt seem to work with the "emulation" mode </span><del>- return psycopg.TimeFromMx(value) </del><ins>+ if value is not None: + return psycopg.TimeFromMx(value) + else: + return None </ins><span class="cx"> def convert_result_value(self, value, engine): </span><span class="cx"> # TODO: perform appropriate postgres1 conversion between Python DateTime/MXDateTime </span><span class="cx"> return value </span></span></pre> </div> </div> </body> </html> |