sqlobject-cvs Mailing List for SQLObject (Page 176)
SQLObject is a Python ORM.
Brought to you by:
ianbicking,
phd
You can subscribe to this list here.
| 2003 |
Jan
|
Feb
|
Mar
(9) |
Apr
(74) |
May
(29) |
Jun
(16) |
Jul
(28) |
Aug
(10) |
Sep
(57) |
Oct
(9) |
Nov
(29) |
Dec
(12) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2004 |
Jan
(7) |
Feb
(14) |
Mar
(6) |
Apr
(3) |
May
(12) |
Jun
(34) |
Jul
(9) |
Aug
(29) |
Sep
(22) |
Oct
(2) |
Nov
(15) |
Dec
(52) |
| 2005 |
Jan
(47) |
Feb
(78) |
Mar
(14) |
Apr
(35) |
May
(33) |
Jun
(16) |
Jul
(26) |
Aug
(63) |
Sep
(40) |
Oct
(96) |
Nov
(96) |
Dec
(123) |
| 2006 |
Jan
(159) |
Feb
(144) |
Mar
(64) |
Apr
(31) |
May
(88) |
Jun
(48) |
Jul
(16) |
Aug
(64) |
Sep
(87) |
Oct
(92) |
Nov
(56) |
Dec
(76) |
| 2007 |
Jan
(94) |
Feb
(103) |
Mar
(126) |
Apr
(123) |
May
(85) |
Jun
(11) |
Jul
(130) |
Aug
(47) |
Sep
(65) |
Oct
(70) |
Nov
(12) |
Dec
(11) |
| 2008 |
Jan
(30) |
Feb
(55) |
Mar
(88) |
Apr
(20) |
May
(50) |
Jun
|
Jul
(38) |
Aug
(1) |
Sep
(9) |
Oct
(5) |
Nov
(6) |
Dec
(39) |
| 2009 |
Jan
(8) |
Feb
(16) |
Mar
(3) |
Apr
(33) |
May
(44) |
Jun
(1) |
Jul
(10) |
Aug
(33) |
Sep
(74) |
Oct
(22) |
Nov
|
Dec
(15) |
| 2010 |
Jan
(28) |
Feb
(22) |
Mar
(46) |
Apr
(29) |
May
(1) |
Jun
(1) |
Jul
(27) |
Aug
(8) |
Sep
(5) |
Oct
(33) |
Nov
(24) |
Dec
(41) |
| 2011 |
Jan
(4) |
Feb
(12) |
Mar
(35) |
Apr
(29) |
May
(19) |
Jun
(16) |
Jul
(32) |
Aug
(25) |
Sep
(5) |
Oct
(11) |
Nov
(21) |
Dec
(12) |
| 2012 |
Jan
(3) |
Feb
(4) |
Mar
(20) |
Apr
(4) |
May
(25) |
Jun
(13) |
Jul
|
Aug
|
Sep
(2) |
Oct
(25) |
Nov
(9) |
Dec
(1) |
| 2013 |
Jan
(6) |
Feb
(8) |
Mar
|
Apr
(10) |
May
(31) |
Jun
(7) |
Jul
(18) |
Aug
(33) |
Sep
(4) |
Oct
(16) |
Nov
|
Dec
(27) |
| 2014 |
Jan
(2) |
Feb
|
Mar
|
Apr
(11) |
May
(39) |
Jun
(8) |
Jul
(11) |
Aug
(4) |
Sep
|
Oct
(27) |
Nov
|
Dec
(71) |
| 2015 |
Jan
(17) |
Feb
(47) |
Mar
(33) |
Apr
|
May
|
Jun
(9) |
Jul
(7) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(8) |
| 2016 |
Jan
(4) |
Feb
(4) |
Mar
|
Apr
|
May
(12) |
Jun
(7) |
Jul
(9) |
Aug
(31) |
Sep
(8) |
Oct
(3) |
Nov
(15) |
Dec
(1) |
| 2017 |
Jan
(13) |
Feb
(7) |
Mar
(14) |
Apr
(8) |
May
(10) |
Jun
(4) |
Jul
(2) |
Aug
(1) |
Sep
|
Oct
(8) |
Nov
(4) |
Dec
(5) |
| 2018 |
Jan
(2) |
Feb
(8) |
Mar
|
Apr
(4) |
May
|
Jun
(6) |
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
(1) |
Dec
|
| 2019 |
Jan
(1) |
Feb
(16) |
Mar
(1) |
Apr
(3) |
May
(5) |
Jun
(1) |
Jul
|
Aug
|
Sep
(2) |
Oct
|
Nov
(1) |
Dec
(3) |
| 2020 |
Jan
|
Feb
|
Mar
|
Apr
(1) |
May
(1) |
Jun
|
Jul
|
Aug
(1) |
Sep
|
Oct
(2) |
Nov
|
Dec
(2) |
| 2021 |
Jan
|
Feb
(2) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
(1) |
Dec
|
| 2022 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(6) |
Oct
(1) |
Nov
(1) |
Dec
(4) |
| 2023 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
(3) |
Sep
(2) |
Oct
(2) |
Nov
(4) |
Dec
|
| 2024 |
Jan
|
Feb
(2) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
(9) |
| 2025 |
Jan
|
Feb
(4) |
Mar
(2) |
Apr
|
May
|
Jun
|
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
(2) |
Dec
(2) |
|
From: <sub...@co...> - 2004-11-12 04:47:12
|
Author: ianb Date: 2004-11-11 13:57:53 -0500 (Thu, 11 Nov 2004) New Revision: 364 Modified: trunk/SQLObject/docs/presentation-2004-11/sqlobject-and-database-progr= amming.html trunk/SQLObject/docs/presentation-2004-11/ui/custom.css trunk/SQLObject/docs/presentation-2004-11/ui/framing.css trunk/SQLObject/docs/presentation-2004-11/ui/pretty.css Log: Edits and visual updates Modified: trunk/SQLObject/docs/presentation-2004-11/sqlobject-and-databas= e-programming.html =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/SQLObject/docs/presentation-2004-11/sqlobject-and-database-prog= ramming.html 2004-11-11 18:38:24 UTC (rev 363) +++ trunk/SQLObject/docs/presentation-2004-11/sqlobject-and-database-prog= ramming.html 2004-11-11 18:57:53 UTC (rev 364) @@ -11,7 +11,7 @@ <link rel=3D"stylesheet" href=3D"ui/print.css" type=3D"text/css" media=3D"print" id=3D"slidePrint" /> <link rel=3D"stylesheet" href=3D"ui/custom.css" type=3D"text/css"/> -<sc ript src=3D"ui/slides.js" type=3D"text/javascript"></script> +<script src=3D"ui/slides.js" type=3D"text/javascript"></script> </head> <body> =20 @@ -62,7 +62,7 @@ <!-- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --> =20 <div class=3D"slide"> -<h1>Database Programming in Python</h1> +<h1>The DB API</h1> =20 <p>Database programming in Python is based on the <b><a href=3D"http://www.python.org/peps/pep-0249.html">DB-API</a></b>. @@ -72,11 +72,9 @@ <li>MySQL</li> <li>PostgreSQL (multiple drivers)</li> <li>SQLite</li> -<li>Oracle</li> -<li>Sybase</li> <li>Firebird (Interbase)</li> <li>MAXDB (SAP DB)</li> -<li>MS SQL Server</li> +<li>Oracle, Sybase, MS SQL Server</li> </p> </div> =20 @@ -109,7 +107,7 @@ <h1>DB API</h1> =20 <ul> -<li> Import the databse module (<code>MySQLdb</code>, +<li> Import the database module (<code>MySQLdb</code>, <code>psycopg</code>, <code>sqlite</code>, etc) </li> <li> Use <code>module.connect(...)</code> to create a connection. </li> @@ -194,12 +192,14 @@ =20 <div class=3D"slide"> =20 -<h1>Object-Relational Mappers: Classes</h1> +<h1>ORMs: Classes</h1> =20 <p> =20 The class: =20 +<table width=3D"100%"> +<tr><td> <table border=3D1> =20 <tr class=3D"code-accent"><th colspan=3D3>person</th></tr> @@ -225,14 +225,16 @@ </tr> =20 </table> -<p> +</td> =20 +<td> <pre> class Person(SQLObject): <span class=3D"comment"># id is implicit</span> first_name =3D StringCol() last_name =3D StringCol() </pre> +</td></tr></table> =20 </div> =20 @@ -241,12 +243,15 @@ =20 <div class=3D"slide"> =20 -<h1>Object-Relational Mappers: Instances</h1> +<h1>ORMs: Instances</h1> =20 <p> =20 An instance: =20 +<table width=3D"100%"> +<tr><td> + <table border=3D1> =20 <tr><th colspan=3D3>person</th></tr> @@ -272,13 +277,17 @@ </tr> =20 </table> -<p> =20 +</td><td> + <pre> -john =3D Person.get(1) -assert john.first_name =3D=3D <span class=3D"string">'John'</span> +<span class=3D"prompt">>>></span> john =3D Person.get(1) +<span class=3D"prompt">>>></span> john.first_name +<span class=3D"output">'John'</span> </pre> =20 +</td></tr></table> +</p> =20 </div> =20 @@ -286,7 +295,7 @@ =20 =20 <div class=3D"slide"> -<h1>Object-Relational Mapping: summary</h1> +<h1>ORM: summary</h1> =20 <ul> <li>Every table is a class</li> @@ -308,10 +317,32 @@ first_name =3D StringCol() last_name =3D StringCol() emails =3D MultipleJoin('Email') +</pre> + +</div> + +<!-- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --> + + +<div class=3D"slide"> +<h1>Usage (classes)</h1> + +<pre> class Email(SQLObject): person =3D ForeignKey(<span class=3D"string">'Person'</span>) type =3D EnumCol(['home', 'work']) address =3D StringCol() +</pre> + +</div> + +<!-- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --> + + +<div class=3D"slide"> +<h1>Usage (creating tables)</h1> + +<pre> def createTables(): for table in (Person, Email): table.createTable(ifNotExists=3DTrue) @@ -322,7 +353,7 @@ <!-- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --> =20 <div class=3D"slide"> -<h1>More use...</h1> +<h1>Usage (instances)</h1> =20 Using your classes: =20 @@ -332,6 +363,17 @@ <span class=3D"prompt">...</span> address=3D<span class=3D"string">'= jo...@wo...'</span>) <span class=3D"prompt">>>></span> john.emails <span class=3D"output">[]</span> +</pre> + +</div> + +<!-- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --> + + +<div class=3D"slide"> +<h1>Usage (instances)</h1> + +<pre> <span class=3D"prompt">>>></span> tom =3D Person(first_name=3D<= span class=3D"string">'Tom'</span>, last_name=3D<span class=3D"string">'J= ones'</span>) <span class=3D"prompt">>>></span> tom is Person.get(tom.id) <span class=3D"output">True</span> @@ -342,8 +384,6 @@ </div> =20 =20 - - <!-- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --> =20 =20 @@ -373,13 +413,17 @@ return self.first_name + ' ' + self.last_name </pre> =20 +<pre> +<span class=3D"prompt">>>></span> tom.name +<span class=3D"output">'Tom Jones'</span> +</pre> =20 </div> =20 <!-- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --> =20 <div class=3D"slide"> -<h1></h1> +<h1>Automatic properties</h1> =20 <ul> <li> <code>_get_attr()</code> methods are called whenever the @@ -487,36 +531,38 @@ <!-- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --> =20 <div class=3D"slide"> -<h1>Lazy classes</h1> +<h1>Many-to-many...</h1> =20 <p> -SQLObject can use reflection to figure out what columns your table -has: +The intermediate table created: =20 <pre> -class Person(SQLObject): - _fromDatabase =3D True +CREATE TABLE address_person ( + address_id INT NOT NULL, + person_id INT NOT NULL +); </pre> - </p> =20 </div> =20 <!-- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --> =20 - <div class=3D"slide"> -<h1>Many-to-many...</h1> +<h1>Lazy classes</h1> =20 <p> -The intermediate table created: +SQLObject can use reflection to figure out what columns your table +has: =20 <pre> -CREATE TABLE address_person ( - address_id INT NOT NULL, - person_id INT NOT NULL -); +class Person(SQLObject): + _fromDatabase =3D True </pre> + +You can start with <code>_fromDatabase =3D True</code> and add=20 +in explicit columns, overriding defaults. + </p> =20 </div> @@ -524,6 +570,7 @@ <!-- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --> =20 =20 + <div class=3D"slide"> <h1>Instances</h1> =20 @@ -542,12 +589,13 @@ <h1>Updating</h1> =20 <ul> -<li>Use <code>aPerson.first_name =3D <span -class=3D"string">"new_name"</span></code></li> -<li>Use <code>aPerson.set(first_name=3D<span +<li><code>aPerson.first_name =3D <span +class=3D"string">"new_name"</span></code><br> + <code class=3D"sql">UPDATE</code> is executed immediately </li> +<li> Update multiple columns at once: <br> +<code>aPerson.set(first_name=3D<span class=3D"string">"new_fname"</span>, last_name=3D<span -class=3D"string">"new_lname"</span>)</code> for multiple simultaneous -updates. </li> +class=3D"string">"new_lname"</span>)</code> </li> </ul> =20 </div> @@ -580,7 +628,7 @@ <p> =20 <ul> -<li><code>Class.<b>q</b>.<i>column_name</i></code> creates a magical +<li><code>Class.<b style=3D"color: #990000">q</b>.column_name</code> cre= ates a magical object that creates queries.</li> <li><code>sqlrepr()</code> turns these query objects into SQL (mostly hidden)</li> @@ -625,13 +673,13 @@ <div class=3D"slide"> <h1>SelectResult</h1> =20 -Select results are fancy. +Select results are more than just lists: =20 <ul> <li> You can slice them, and <code class=3D"sql">LIMIT</code> and <code class=3D"sql">OFFSET</code> statements are added to your query</li> <li> You can iterate through them, and avoid loading all objects into -memory</li> +memory </li> <li> You can do things like <code>select_result.count()</code> to run aggregate functions </li> <li> To get a real list, you must do <code>list(select_result)</code></l= i> @@ -673,16 +721,14 @@ =20 <!-- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --> =20 - <div class=3D"slide"> -<h1>Solving the question by avoidance</h1> +<h1>The problem with ORMs</h1> =20 -<ul> - <li> SQLObject doesn't let you forget SQL </li> - <li> You still have to think relationally </li> - <li> But many relational concepts don't work either </li> - <li> Advantage: it's easy </li> -</ul> +<p> +ORMs live in the world between Object Oriented programmers (and +programs) and Relational programmers (and programs). Neither will be +happy. +</p> =20 </div> =20 @@ -695,8 +741,6 @@ <ul> <li> Python classes aren't tables</li> <li> Python instances aren't rows</li> - <li> Primitive values (like <code class=3D"string">"John"</code>) - aren't part of the ORM at all </li> <ul> =20 </div> @@ -711,7 +755,7 @@ <li> Databases don't have inheritance </li> <li> Even when they do, no one uses it </li> <li> Some tables are too boring (e.g., intermediate tables for - many-to-many relationships) </li> + many-to-many relationships), or don't warrant the overhead </li> </ul> =20 </div> @@ -723,7 +767,8 @@ =20 <ul> <li> Instances get garbage collected, rows are forever </li> - <li> Instances can't be pre-allocated </li> + <li> Rows exist even when instances don't </li> + <li> Instances may still exist when the row is gone </li> <li> In the relational calculus, rows don't have real identity </li> =20 </div> @@ -738,13 +783,29 @@ <li> Things like joins don't make sense for objects, but are central to relations </li> <li> Views and stored procedures also don't make sense </li> + <li> Aggregate functions and set operations aren't natural in Python=20 + (the <code>for</code> loop is natural) </li> </ul> =20 </div> =20 <!-- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --> =20 +<div class=3D"slide"> +<h1>Solving the question by avoidance</h1> =20 +<ul> + <li> SQLObject doesn't let you forget SQL </li> + <li> You still have to think relationally </li> + <li> But many relational concepts don't work either </li> + <li> Advantage: it's easy </li> +</ul> + +</div> + +<!-- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --> + + <div class=3D"slide"> <h1>Solving the Mismatch</h1> =20 @@ -753,17 +814,50 @@ <ul> <li> There exist database restrictions; not every database schema maps well. (But most are fine) </li> + <li> Sometimes you have to do things more slowly or more imperatively, + compared to a purely relational technique </li> <li> There exist object restrictions; not every object-oriented - concept maps well; e.g., no inheritance. </li> + concept maps well; e.g., no inheritance </li> + <li> Inheritance isn't planned; this isn't transparent persistence </li= > </ul> =20 </div> =20 <!-- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --> =20 +<div class=3D"slide"> +<h1>Some other alternatives</h1> =20 +Several Python ORMs exist; contrasts:=20 +<ul> + <li> SQLObject doesn't try to be too OO, so it works well with normal=20 + database schemas </li> + <li> SQLObject doesn't have a compile step </li> + <li> SQLObject isn't <i>just</i> a SQL wrapper </li> + <li> SQLObject is reasonably complete </li> +</ul> =20 </div> =20 +<!-- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --> + + +<div class=3D"slide"> +<h1>Other alternatives...</h1> + +<p> + +See the Python Wiki at: <a href=3D"http://python.org/moin">python.org/mo= in</a><br> +The page is <a href=3D"http://python.org/moin/HigherLevelDatabaseProgram= ming">HigherLevelDatabaseProgramming</a>. +</p> + +</div> + +<!-- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --> + + + +</div> + </body> </html> Modified: trunk/SQLObject/docs/presentation-2004-11/ui/custom.css =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/SQLObject/docs/presentation-2004-11/ui/custom.css 2004-11-11 18= :38:24 UTC (rev 363) +++ trunk/SQLObject/docs/presentation-2004-11/ui/custom.css 2004-11-11 18= :57:53 UTC (rev 364) @@ -1,3 +1,7 @@ +td { + vertical-align: top; +} + .string {=20 color: #006600; } @@ -16,7 +20,7 @@ } =20 .sql {=20 - color: #006600; + color: #004466; font-weight: bold; } =20 Modified: trunk/SQLObject/docs/presentation-2004-11/ui/framing.css =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/SQLObject/docs/presentation-2004-11/ui/framing.css 2004-11-11 1= 8:38:24 UTC (rev 363) +++ trunk/SQLObject/docs/presentation-2004-11/ui/framing.css 2004-11-11 1= 8:57:53 UTC (rev 364) @@ -4,15 +4,15 @@ to help you with the rearrangement process. */ =20 div#header, div#footer, div.slide {width: 100%; top: 0; left: 0;} -div#header {top: 0; height: 3em; z-index: 1;} -div#footer {top: auto; bottom: 0; height: 2.5em; z-index: 5;} +div#header {top: 0; height: 2em; z-index: 1;} +div#footer {top: auto; bottom: 0; height: 1.75em; z-index: 5;} div.slide {top: 0; width: 92%; padding: 3.5em 4% 4%; z-index: 2;} div#controls {left: 50%; top: 0; width: 50%; height: 100%; z-index: 1;} #footer>div#controls {bottom: 0; top: auto; height: auto;} =20 div#controls form {position: absolute; bottom: 0; right: 0; width: 100%; margin: 0;} -#currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em; z= -index: 10;} +#currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1.5em;= z-index: 10;} html>body #currentSlide {position: fixed;} =20 /* Modified: trunk/SQLObject/docs/presentation-2004-11/ui/pretty.css =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/SQLObject/docs/presentation-2004-11/ui/pretty.css 2004-11-11 18= :38:24 UTC (rev 363) +++ trunk/SQLObject/docs/presentation-2004-11/ui/pretty.css 2004-11-11 18= :57:53 UTC (rev 364) @@ -2,7 +2,8 @@ Note that the 'body' font size may have to be changed if the resoluti= on is different than expected. */ =20 -body {background: #fff url(bodybg.gif) -16px 0 no-repeat; color: #000; f= ont-size: 2em;} +/* url(bodybg.gif) */ +body {background: #fff -16px 0 no-repeat; color: #000; font-size: 2em;} :link, :visited {text-decoration: none;} #controls :active {color: #88A !important;} #controls :focus {outline: 1px dotted #227;} @@ -31,17 +32,17 @@ ul ul li {margin: .2em; font-size: 85%; list-style: square;} img.leader {display: block; margin: 0 auto;} =20 -div#header, div#footer {background: #005; color: #AAB; +div#header, div#footer {background: #005; color: #BBC; font-family: Verdana, Helvetica, sans-serif;} -div#header {background: #005 url(bodybg.gif) -16px 0 no-repeat; +div#header {background: #005 -16px 0 no-repeat; line-height: 1px;} div#footer {font-size: 0.5em; font-weight: bold; padding: 1em 0;} #footer h1, #footer h2 {display: block; padding: 0 1em;} #footer h2 {font-style: italic;} =20 div.long {font-size: 0.75em;} -.slide h1 {position: absolute; top: 0.7em; left: 87px; z-index: 1; - margin: 0; padding: 0.3em 0 0 50px; white-space: nowrap; +.slide h1 {position: absolute; top: 0.0em; left: 0px; z-index: 1; + margin: 0; padding: 0.3em 0 0 10px; white-space: nowrap; font: bold 150%/1em Helvetica, sans-serif; text-transform: capitalize; color: #DDE; background: #005;} .slide h3 {font-size: 130%;} @@ -54,13 +55,13 @@ top: auto; height: auto;} div#controls form {position: absolute; bottom: 0; right: 0; width: 100%; margin: 0; padding: 0;} -div#controls a {font-size: 2em; padding: 0; margin: 0 0.5em;=20 +div#controls a {font-size: 1.7em; padding: 0; margin: 0 0.5em;=20 background: #005; border: none; color: #779;=20 cursor: pointer;} div#controls select {visibility: hidden; background: #DDD; color: #227;} div#controls div:hover select {visibility: visible;} =20 -#currentSlide {text-align: center; font-size: 0.5em; color: #449;} +#currentSlide {text-align: center; font-size: 0.5em; color: #77B;} =20 #slide0 {padding-top: 3.5em; font-size: 90%;} #slide0 h1 {position: static; margin: 1em 0 1.33em; padding: 0; |
|
From: <sub...@co...> - 2004-11-05 21:40:23
|
Author: ianb
Date: 2004-11-05 12:24:01 -0500 (Fri, 05 Nov 2004)
New Revision: 334
Modified:
trunk/SQLObject/sqlobject/sqlbuilder.py
Log:
The % in LIKE expressions is quoted in different ways on different
databases. This uses \% for Postgres and MySQL, %% for other databases
Modified: trunk/SQLObject/sqlobject/sqlbuilder.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/sqlbuilder.py 2004-11-05 15:08:12 UTC (rev =
333)
+++ trunk/SQLObject/sqlobject/sqlbuilder.py 2004-11-05 17:24:01 UTC (rev =
334)
@@ -546,13 +546,13 @@
return SQLOp("LIKE", expr, string)
=20
def STARTSWITH(expr, string):
- return SQLOp("LIKE", expr, _likeQuote(string) + '%')
+ return SQLOp("LIKE", expr, _LikeQuoted(string) + '%')
=20
def ENDSWITH(expr, string):
- return SQLOp("LIKE", expr, '%' + _likeQuote(string))
+ return SQLOp("LIKE", expr, '%' + _LikeQuoted(string))
=20
def CONTAINSSTRING(expr, string):
- return SQLOp("LIKE", expr, '%' + _likeQuote(string) + '%')
+ return SQLOp("LIKE", expr, '%' + _LikeQuoted(string) + '%')
=20
def ISNULL(expr):
return SQLOp("IS", expr, None)
@@ -560,9 +560,20 @@
def ISNOTNULL(expr):
return SQLOp("IS NOT", expr, None)
=20
-def _likeQuote(s):
- return s.replace('%', '%%')
+class _LikeQuoted:
+ # @@: I'm not sure what the quoting rules really are for all the
+ # databases
=20
+ def __init__(self, expr):
+ self.expr =3D expr
+
+ def __sqlrepr__(self, db):
+ s =3D sqlrepr(self.expr, db)
+ if db in ('postgres', 'mysql'):
+ return s.replace('%', '\\%')
+ else:
+ return s.replace('%', '%%')
+
########################################
## Global initializations
########################################
|
|
From: <sub...@co...> - 2004-10-07 12:10:49
|
Author: bbollenbach
Date: 2004-10-07 03:57:16 -0400 (Thu, 07 Oct 2004)
New Revision: 273
Modified:
trunk/SQLObject/sqlobject/joins.py
trunk/SQLObject/tests/test.py
Log:
Andrew Bennetts' patch to create join methods correctly, even if they're =
not
named explicitly. I've done some slight renaming to hopefully more clearl=
y
describe what's being tested.
Modified: trunk/SQLObject/sqlobject/joins.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/joins.py 2004-10-06 01:23:42 UTC (rev 272)
+++ trunk/SQLObject/sqlobject/joins.py 2004-10-07 07:57:16 UTC (rev 273)
@@ -29,6 +29,8 @@
def _get_joinMethodName(self):
return self._joinMethodName
=20
+ joinMethodName =3D property(_get_joinMethodName, _set_joinMethodName=
)
+
def withClass(self, soClass):
if self.kw.has_key('joinMethodName'):
self._joinMethodName =3D self.kw['joinMethodName']
Modified: trunk/SQLObject/tests/test.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/tests/test.py 2004-10-06 01:23:42 UTC (rev 272)
+++ trunk/SQLObject/tests/test.py 2004-10-07 07:57:16 UTC (rev 273)
@@ -38,18 +38,6 @@
else:
self.fail("should have raised an error on duplicate class de=
finition")
=20
-## class Billboard(SQLObject):
-## message =3D StringCol()
-
-## class UnicodeTest(SQLObjectTest):
-## classes =3D [Billboard]
-
-## def testUnicodeStrings(self):
-## try:
-## b =3D Billboard(message =3D u"foobar")
-## except Exception, err:
-## self.fail("shouldn't have raised an exception.")
-
########################################
## Basic operation
########################################
@@ -741,6 +729,12 @@
_columns =3D [StringCol('zip', length=3D5, alternateID=3DTrue)]
_joins =3D [RelatedJoin('PersonJoiner')]
=20
+class ImplicitJoiningSO(SQLObject):
+ foo =3D RelatedJoin('Bar')
+
+class ExplicitJoiningSO(SQLObject):
+ _joins =3D [MultipleJoin('Bar', joinMethodName=3D'foo')]
+
class JoinTest(SQLObjectTest):
=20
classes =3D [PersonJoiner, AddressJoiner]
@@ -772,6 +766,15 @@
def assertNamesEqual(self, people, dest):
self.assertEqual([p.name for p in people], dest)
=20
+ def testJoinAttributeWithUnderscores(self):
+ # Make sure that the implicit setting of joinMethodName works
+ self.failUnless(hasattr(ImplicitJoiningSO, 'foo'))
+ self.failIf(hasattr(ImplicitJoiningSO, 'bars'))
+
+ # And make sure explicit setting also works
+ self.failUnless(hasattr(ExplicitJoiningSO, 'foo'))
+ self.failIf(hasattr(ExplicitJoiningSO, 'bars'))
+
class PersonJoiner2(SQLObject):
=20
_columns =3D [StringCol('name', length=3D40, alternateID=3DTrue)]
|
|
From: <sub...@co...> - 2004-10-02 01:06:15
|
Author: bbollenbach
Date: 2004-10-01 16:53:10 -0400 (Fri, 01 Oct 2004)
New Revision: 260
Modified:
trunk/SQLObject/sqlobject/classregistry.py
trunk/SQLObject/tests/test.py
Log:
Steve Alexander's patch to raise an error when the same SQLObject
is defined more than once. I've added a test to prove that this
works.
Modified: trunk/SQLObject/sqlobject/classregistry.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/classregistry.py 2004-10-01 17:57:08 UTC (r=
ev 259)
+++ trunk/SQLObject/sqlobject/classregistry.py 2004-10-01 20:53:10 UTC (r=
ev 260)
@@ -65,6 +65,9 @@
that other classes can find it by name. We also call any
callbacks that are waiting for the class.
"""
+ if cls.__name__ in self.classes:
+ raise ValueError("class %s is already in the registry"
+ % cls.__name__)
self.classes[cls.__name__] =3D cls
if self.callbacks.has_key(cls.__name__):
for callback, args, kw in self.callbacks[cls.__name__]:
Modified: trunk/SQLObject/tests/test.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/tests/test.py 2004-10-01 17:57:08 UTC (rev 259)
+++ trunk/SQLObject/tests/test.py 2004-10-01 20:53:10 UTC (rev 260)
@@ -24,6 +24,32 @@
curr_db =3D None
from sqlobject import cache
=20
+class ClassRegistryTest(SQLObjectTest):
+ def testErrorOnDuplicateClassDefinition(self):
+ """Raise an error if a class is defined more than once."""
+ class Duplicate(SQLObject):
+ pass
+
+ try:
+ class Duplicate(SQLObject):
+ pass
+ except ValueError, err:
+ self.assertEqual(str(err), "class Duplicate is already in th=
e registry")
+ else:
+ self.fail("should have raised an error on duplicate class de=
finition")
+
+## class Billboard(SQLObject):
+## message =3D StringCol()
+
+## class UnicodeTest(SQLObjectTest):
+## classes =3D [Billboard]
+
+## def testUnicodeStrings(self):
+## try:
+## b =3D Billboard(message =3D u"foobar")
+## except Exception, err:
+## self.fail("shouldn't have raised an exception.")
+
########################################
## Basic operation
########################################
|
|
From: <sub...@co...> - 2004-09-27 22:25:15
|
Author: ianb
Date: 2004-09-27 14:12:38 -0400 (Mon, 27 Sep 2004)
New Revision: 232
Modified:
trunk/SQLObject/examples/config.py
Log:
Fixed bug [ 1030094 ] Documentation uses incorrect classname.
(typo)
Modified: trunk/SQLObject/examples/config.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/examples/config.py 2004-09-27 18:10:58 UTC (rev 231)
+++ trunk/SQLObject/examples/config.py 2004-09-27 18:12:38 UTC (rev 232)
@@ -11,7 +11,7 @@
conn =3D 'mysql://test@localhost/testdb'
conn =3D PostgresConnection('user=3Dtest dbname=3Dtestdb')
conn =3D 'postgres://test@localhost/testdb'
-conn =3D SQLiteConnect('database.db')
+conn =3D SQLiteConnection('database.db')
conn =3D 'sqlite://path/to/database.db'
conn =3D DBMConnection('database/')
conn =3D 'dbm://path/to/database/'
|
|
From: <sub...@co...> - 2004-09-27 22:23:38
|
Author: ianb
Date: 2004-09-27 14:10:58 -0400 (Mon, 27 Sep 2004)
New Revision: 231
Modified:
trunk/SQLObject/sqlobject/main.py
trunk/SQLObject/tests/test.py
Log:
Fixed bug [ 1034304 ] count() failes on selectBy result
Modified: trunk/SQLObject/sqlobject/main.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/main.py 2004-09-27 18:03:12 UTC (rev 230)
+++ trunk/SQLObject/sqlobject/main.py 2004-09-27 18:10:58 UTC (rev 231)
@@ -1314,7 +1314,7 @@
=20
def count(self):
""" Counting elements of current select results """
- assert not self.ops['distinct'], "It is not currently supported =
to count distinct objects"
+ assert not self.ops.get('distinct'), "It is not currently suppor=
ted to count distinct objects"
=20
count =3D self.accumulate('COUNT(*)')
if self.ops.get('start'):
Modified: trunk/SQLObject/tests/test.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/tests/test.py 2004-09-27 18:03:12 UTC (rev 230)
+++ trunk/SQLObject/tests/test.py 2004-09-27 18:10:58 UTC (rev 231)
@@ -62,6 +62,10 @@
bob.name =3D testString
self.failUnless(bob.name =3D=3D testString, (bob.name, testStrin=
g))
=20
+ def testCount(self):
+ self.assertEqual(self.MyClass.selectBy(name=3D'bob').count(), 1)
+ self.assertEqual(self.MyClass.select(self.MyClass.q.name =3D=3D =
'bob').count(), 1)
+ self.assertEqual(self.MyClass.select().count(), len(list(self.My=
Class.select())))
=20
class TestCaseGetSet(TestCase1):
=20
|
|
From: <sub...@co...> - 2004-09-27 22:15:54
|
Author: ianb
Date: 2004-09-27 14:03:12 -0400 (Mon, 27 Sep 2004)
New Revision: 230
Modified:
trunk/SQLObject/docs/News.txt
trunk/SQLObject/sqlobject/dbconnection.py
Log:
Applied [ 1034254 ] selectBy patch for accepting object values
Modified: trunk/SQLObject/docs/News.txt
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/docs/News.txt 2004-09-27 17:57:02 UTC (rev 229)
+++ trunk/SQLObject/docs/News.txt 2004-09-27 18:03:12 UTC (rev 230)
@@ -15,18 +15,31 @@
=20
* Added a connection parameter to all class methods (patch 974755)
=20
+* Connection objects have a ``.module`` attribute, which points to
+ the DB-API module. This is useful for getting access to the
+ exception objects.
+
+Features
+--------
+
* Added indexing (from Jeremy Fitzhardinge). See `the
documentation`__ for more.
=20
.. __: SQLObject.html#indexes
=20
-* Connection objects have a ``.module`` attribute, which points to
- the DB-API module. This is useful for getting access to the
- exception objects.
+* All connections are explicitly closed, not just garbage collected.
+ Many database drivers don't close database connections properly when
+ the connection object is garbage collected.
=20
* New ``distinct`` option to selects, like ``MyClass.select(...,
distinct=3DTrue)``
=20
+* You can now do
+ ``MyClass.selectBy(joinedTable=3DjoinedTableInstance)``, where before
+ you had to do
+ ``MyClass.selectBy(joinedTableID=3DjoinedTableInstance.id)``. (From
+ Dave Cook)
+
SQLObject 0.6
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
=20
Modified: trunk/SQLObject/sqlobject/dbconnection.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/dbconnection.py 2004-09-27 17:57:02 UTC (re=
v 229)
+++ trunk/SQLObject/sqlobject/dbconnection.py 2004-09-27 18:03:12 UTC (re=
v 230)
@@ -442,6 +442,22 @@
self.sqlrepr(value))
for key, value
in kw.items()])
+ terms =3D []
+ for key, value in kw.items():
+ if hasattr(value, '_SO_joinDict'): #handle an object value
+ # find the joinColumn=20
+ for join in value._SO_joinDict.values():
+ if join.otherClass is soClass:
+ dbName =3D join.joinColumn
+ break
+ else: #if nothing found
+ raise TypeError, "Cannot selectBy(%s=3D%r)" % (key, value)
+ value =3D value.id
+ else:
+ dbName =3D soClass._SO_columnDict[key].dbName
+ term =3D '%s =3D %s' % (dbName, self.sqlrepr(value))
+ terms.append(term)
+ return ' AND '.join(terms)
=20
def sqlrepr(self, v):
return sqlrepr(v, self.dbName)
|
|
From: <sub...@co...> - 2004-09-27 22:09:43
|
Author: ianb
Date: 2004-09-27 13:57:02 -0400 (Mon, 27 Sep 2004)
New Revision: 229
Modified:
trunk/SQLObject/sqlobject/dbconnection.py
Log:
Explicitly close all database connections (SF patch 1033807, though not
directly applied).
Modified: trunk/SQLObject/sqlobject/dbconnection.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/dbconnection.py 2004-09-27 17:34:05 UTC (re=
v 228)
+++ trunk/SQLObject/sqlobject/dbconnection.py 2004-09-27 17:57:02 UTC (re=
v 229)
@@ -14,11 +14,17 @@
from joins import sorter
from converters import sqlrepr
import urllib
+import weakref
=20
warnings.filterwarnings("ignore", "DB-API extension cursor.lastrowid use=
d")
=20
_connections =3D {}
=20
+def _closeConnection(ref):
+ conn =3D ref()
+ if conn is not None:
+ conn.close()
+
class DBConnection:
=20
def __init__(self, name=3DNone, debug=3DFalse, debugOutput=3DFalse,
@@ -35,6 +41,7 @@
self._connectionCount =3D 1
self.autoCommit =3D autoCommit
registerConnectionInstance(self)
+ atexit.register(_closeConnection, weakref.ref(self))
=20
def uri(self):
auth =3D self.user or ''
@@ -439,6 +446,17 @@
def sqlrepr(self, v):
return sqlrepr(v, self.dbName)
=20
+ def __del__(self):
+ self.close()
+
+ def close(self):
+ if self._pool:
+ for conn in self._pool:
+ try:
+ conn.close()
+ except self.module.Error:
+ pass
+
class Iteration(object):
=20
def __init__(self, dbconn, rawconn, select, keepConnection=3DFalse):
|
|
From: <sub...@co...> - 2004-09-27 21:46:46
|
Author: ianb
Date: 2004-09-27 13:34:05 -0400 (Mon, 27 Sep 2004)
New Revision: 228
Modified:
trunk/SQLObject/sqlobject/dbconnection.py
trunk/SQLObject/sqlobject/mysql/mysqlconnection.py
Log:
Some fixes for the .uri() connection function (that produces a URI).
Modified: trunk/SQLObject/sqlobject/dbconnection.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/dbconnection.py 2004-09-27 17:33:17 UTC (re=
v 227)
+++ trunk/SQLObject/sqlobject/dbconnection.py 2004-09-27 17:34:05 UTC (re=
v 228)
@@ -47,9 +47,10 @@
uri =3D '%s://%s' % (self.dbName, auth)
if self.host:
uri +=3D self.host + '/'
- if path.startswith('/'):
- path =3D path[1:]
- return uri + path
+ db =3D self.db
+ if db.startswith('/'):
+ db =3D path[1:]
+ return uri + db
=20
def isSupported(cls):
raise NotImplemented
Modified: trunk/SQLObject/sqlobject/mysql/mysqlconnection.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/mysql/mysqlconnection.py 2004-09-27 17:33:1=
7 UTC (rev 227)
+++ trunk/SQLObject/sqlobject/mysql/mysqlconnection.py 2004-09-27 17:34:0=
5 UTC (rev 228)
@@ -16,7 +16,7 @@
self.host =3D host
self.db =3D db
self.user =3D user
- self.passwd =3D passwd
+ self.password =3D passwd
DBAPI.__init__(self, **kw)
=20
def connectionFromURI(cls, uri):
@@ -27,7 +27,7 @@
=20
def makeConnection(self):
return MySQLdb.connect(host=3Dself.host, db=3Dself.db,
- user=3Dself.user, passwd=3Dself.passwd)
+ user=3Dself.user, passwd=3Dself.password)
=20
def _executeRetry(self, conn, cursor, query):
while 1:
|
|
From: <sub...@co...> - 2004-09-27 21:45:57
|
Author: ianb
Date: 2004-09-27 13:33:17 -0400 (Mon, 27 Sep 2004)
New Revision: 227
Modified:
trunk/SQLObject/sqlobject/constraints.py
Log:
Small bug fixes
Modified: trunk/SQLObject/sqlobject/constraints.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/constraints.py 2004-09-23 03:17:40 UTC (rev=
226)
+++ trunk/SQLObject/sqlobject/constraints.py 2004-09-27 17:33:17 UTC (rev=
227)
@@ -15,7 +15,7 @@
self.obj =3D repr(obj)
self.value =3D repr(value)
fullDesc =3D "%s.%s %s (you gave: %s)" \
- % (obj.__name__, col.name, desc, repr(value))
+ % (obj, col.name, desc, value)
ValueError.__init__(self, fullDesc, *args)
=20
def isString(obj, col, value):
@@ -45,7 +45,7 @@
=20
def __call__(self, obj, col, value):
if value not in self.list:
- raise BadValue("accepts only values in %s" % self.list,
+ raise BadValue("accepts only values in %s" % repr(self.list)=
,
obj, col, value)
=20
class MaxLength:
@@ -54,7 +54,12 @@
self.length =3D length
=20
def __call__(self, obj, col, value):
- if len(value) > self.length:
+ try:
+ length =3D len(value)
+ except TypeError:
+ raise BadValue("object does not have a length",
+ obj, col, value)
+ if length > self.length:
raise BadValue("must be shorter in length than %s"
% self.length,
obj, col, value)
|
|
From: <sub...@co...> - 2004-09-23 07:29:50
|
Author: ianb Date: 2004-09-22 23:17:40 -0400 (Wed, 22 Sep 2004) New Revision: 226 Added: trunk/SQLObject/docs/DeveloperGuide.txt Log: Added a developer guide for the project Added: trunk/SQLObject/docs/DeveloperGuide.txt =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/SQLObject/docs/DeveloperGuide.txt 2004-09-23 02:47:33 UTC (rev = 225) +++ trunk/SQLObject/docs/DeveloperGuide.txt 2004-09-23 03:17:40 UTC (rev = 226) @@ -0,0 +1,149 @@ ++++++++++++++++++++++++++ +SQLObject Developer Guide ++++++++++++++++++++++++++ + +.. contents:: + :backlinks: none + +.. _start: + +These are some notes on developing SQLObject. I'll try to expand them +as things come up. If you are committing to the SQLObject repository, +please also read ``/using-this-repository.txt``, which is just about +file layout and repository cooperation. + + -- Ian Bicking + +Style Guide +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Generally you should follow the recommendations in `PEP 8`_, the +Python Style Guide. Some things to take particular note of: + +.. _PEP 8: http://www.python.org/peps/pep-0008.html + +* **No tabs**. Not anywhere. Always indent with 4 spaces. + +* I don't stress too much on line length. But try to break lines up + by grouping with parenthesis instead of with backslashes (if you + can). + +* But if you are having problems with line length, maybe you should + just break the expression up into multiple statements. + +* Blank lines between methods, unless they are very small and closely + bound to each other. + +* Never use the form ``condition and trueValue or falseValue``. Break + it out and use a variable. + +* Careful of namespace pollution. SQLObject does allow for ``from + sqlobject import *`` so names should be fairly distinct, or they + shouldn't be exported in ``sqlobject.__init__``. + +* I'm very picky about whitespace. There's one and only one right way + to do it. Good examples:: + + short =3D 3 + longerVar =3D 4 + + if x =3D=3D 4: + do stuff + + func(arg1=3D'a', arg2=3D'b') + func((a + b)*10) + + **Bad** examples:: + + short =3D3 + longerVar=3D4 + + if x=3D=3D4: do stuff + + func(arg1 =3D 'a', arg2 =3D 'b') + func(a,b) + func( a, b ) + [ 1, 2, 3 ] + + To me, the poor use of whitespace seems lazy. I'll think less of + your code (justified or not) for this very trivial reason. I will + fix all your code for you if you don't do it yourself, because I + can't bear to look at sloppy whitespace. + +* Use ``@@`` to mark something that is suboptimal, or where you have a + concern that it's not right. Try to also date it and put your + username there. + +* Docstrings are good. They should look like:: + + class AClass(object): + """ + doc string... + """ + + Don't use single quotes ('''). Don't bother trying make the string + less vertically compact. + +* Comments go right before the thing they are commenting on. + +* Methods never, ever, ever start with capital letters. Generally + only classes are capitalized. But definitely never methods. + +* mixedCase is preferred. + +* Use ``cls`` to refer to a class. Use ``meta`` to refer to a + metaclass (which also happens to be a class, but calling a metaclass + ``cls`` will be confusing). + +* Use ``isinstance`` instead of comparing types. E.g.:: + + if isinstance(var, str): ... + # Bad: + if type(var) is StringType: ... + +* Never, ever use two leading underscores. This is annoyingly + private. If name clashes are a concern, use name mangling instead + (e.g., ``_SO_blahblah``). This is essentially the same thing as + double-underscore, only it's transparent where double underscore + obscures. + +* Module names should be unique in the package. Subpackages shouldn't + share module names with sibling or parent packages. Sadly this + isn't possible for ``__init__``, but it's otherwise easy enough. + +* Module names should be all lower case, and probably have no + underscores (smushedwords). + + + +Testing +=3D=3D=3D=3D=3D=3D=3D + +Tests are important. Tests keep everything from falling apart. All +new additions should have tests. + +Right now all the tests are in one big file ``tests.py``. Which is +unfortunate, but that's the way it is. They may seem complex, but +they aren't so bad really. They all subclass from ``SQLObjectTest``. + +The ``classes`` attribute is special in a test class. This is a list +of `SQLObject` subclasses that this test uses. `SQLObjectTest` will +create the tables before the tests are run, and destroy them after. + +You may also define an ``.inserts()`` method. This method sets up the +basic data. When doing verbose input (``-vv``) you won't see these +inserts, since they may be overwhelming. Use the command-line options +``--inserts`` to show them (as well as the create statement. + +When running tests, use ``-ddbname`` to test with ``dbname`` (e.g., +``-dmysql``, ``-dpostgres``, etc), or ``-dall`` to use Postgres, +MySQL, Firebird, and SQLite (all the core supported databases; +everything I have installed on my computer). Please try to test as +many databases as you can. At least SQLite and one other should be +easy, though if you can test both Postgres and MySQL that would be +much better. + +If you submit a patch or implement a feature without a test, I'll be +forced to write the test. That's no fun for me, to just be writing +tests. So please, write tests; everything at least needs to be +exercised, even if the tests are absolutely complete. |
|
From: <sub...@co...> - 2004-09-23 06:59:44
|
Author: ianb
Date: 2004-09-22 22:47:33 -0400 (Wed, 22 Sep 2004)
New Revision: 225
Modified:
trunk/SQLObject/docs/News.txt
trunk/SQLObject/docs/SQLObject.txt
trunk/SQLObject/sqlobject/dbconnection.py
trunk/SQLObject/sqlobject/main.py
trunk/SQLObject/tests/test.py
Log:
* Applied distinct patch
* .count() cannot be used with distinct currently
Modified: trunk/SQLObject/docs/News.txt
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/docs/News.txt 2004-09-23 02:21:22 UTC (rev 224)
+++ trunk/SQLObject/docs/News.txt 2004-09-23 02:47:33 UTC (rev 225)
@@ -18,12 +18,15 @@
* Added indexing (from Jeremy Fitzhardinge). See `the
documentation`__ for more.
=20
-__: SQLObject.html#indexes
+.. __: SQLObject.html#indexes
=20
* Connection objects have a ``.module`` attribute, which points to
the DB-API module. This is useful for getting access to the
exception objects.
=20
+* New ``distinct`` option to selects, like ``MyClass.select(...,
+ distinct=3DTrue)``
+
SQLObject 0.6
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
=20
Modified: trunk/SQLObject/docs/SQLObject.txt
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/docs/SQLObject.txt 2004-09-23 02:21:22 UTC (rev 224)
+++ trunk/SQLObject/docs/SQLObject.txt 2004-09-23 02:47:33 UTC (rev 225)
@@ -417,6 +417,10 @@
performed on the list of results. This will only happen when you use
negative indexes.
=20
+In certain cases, you may get a select result with an object in it
+more than once, e.g., in some joins. If you don't want this, you can
+add the keyword argument ``MyClass.select(..., distinct=3DTrue)``.
+
You can get the length of the result without fetching all the results
by calling ``count`` on the result object, like
``MyClass.select().count()``. A ``COUNT(*)`` query is used -- the
Modified: trunk/SQLObject/sqlobject/dbconnection.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/dbconnection.py 2004-09-23 02:21:22 UTC (re=
v 224)
+++ trunk/SQLObject/sqlobject/dbconnection.py 2004-09-23 02:47:33 UTC (re=
v 225)
@@ -251,16 +251,20 @@
def queryForSelect(self, select):
ops =3D select.ops
cls =3D select.sourceClass
+ if ops.get('distinct', False):
+ q =3D 'SELECT DISTINCT '
+ else:
+ q =3D 'SELECT '
if ops.get('lazyColumns', 0):
- q =3D "SELECT %s.%s FROM %s WHERE " % \
- (cls._table, cls._idName,
- ", ".join(select.tables))
+ q +=3D "%s.%s FROM %s WHERE " % \
+ (cls._table, cls._idName,
+ ", ".join(select.tables))
else:
- q =3D "SELECT %s.%s, %s FROM %s WHERE " % \
- (cls._table, cls._idName,
- ", ".join(["%s.%s" % (cls._table, col.dbName)
- for col in cls._SO_columns]),
- ", ".join(select.tables))
+ q +=3D "%s.%s, %s FROM %s WHERE " % \
+ (cls._table, cls._idName,
+ ", ".join(["%s.%s" % (cls._table, col.dbName)
+ for col in cls._SO_columns]),
+ ", ".join(select.tables))
=20
return self._addWhereClause(select, q)
=20
Modified: trunk/SQLObject/sqlobject/main.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/main.py 2004-09-23 02:21:22 UTC (rev 224)
+++ trunk/SQLObject/sqlobject/main.py 2004-09-23 02:47:33 UTC (rev 225)
@@ -978,11 +978,15 @@
def select(cls, clause=3DNone, clauseTables=3DNone,
orderBy=3DNoDefault, limit=3DNone,
lazyColumns=3DFalse, reversed=3DFalse,
+ distinct=3DFalse,
connection=3DNone):
- return SelectResults(cls, clause, clauseTables=3DclauseTables,
+ return SelectResults(cls, clause,
+ clauseTables=3DclauseTables,
orderBy=3DorderBy,
- limit=3Dlimit, lazyColumns=3DlazyColumns,
+ limit=3Dlimit,
+ lazyColumns=3DlazyColumns,
reversed=3Dreversed,
+ distinct=3Ddistinct,
connection=3Dconnection)
select =3D classmethod(select)
=20
@@ -1243,6 +1247,9 @@
def reversed(self):
return self.clone(reversed=3Dnot self.ops.get('reversed', False)=
)
=20
+ def distinct(self):
+ return self.clone(distinct=3DTrue)
+
def __getitem__(self, value):
if type(value) is type(slice(1)):
assert not value.step, "Slices do not support steps"
@@ -1307,6 +1314,8 @@
=20
def count(self):
""" Counting elements of current select results """
+ assert not self.ops['distinct'], "It is not currently supported =
to count distinct objects"
+ =20
count =3D self.accumulate('COUNT(*)')
if self.ops.get('start'):
count -=3D self.ops['start']
Modified: trunk/SQLObject/tests/test.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/tests/test.py 2004-09-23 02:21:22 UTC (rev 224)
+++ trunk/SQLObject/tests/test.py 2004-09-23 02:47:33 UTC (rev 225)
@@ -1193,6 +1193,41 @@
=20
=20
########################################
+## Distinct
+########################################
+
+class Distinct1(SQLObject):
+ n =3D IntCol()
+
+class Distinct2(SQLObject):
+ other =3D ForeignKey('Distinct1')
+
+class DistinctTest(SQLObjectTest):
+
+ classes =3D [Distinct1, Distinct2]
+
+ def inserts(self):
+ obs =3D [Distinct1(n=3Di) for i in range(3)]
+ Distinct2(other=3Dobs[0])
+ Distinct2(other=3Dobs[0])
+ Distinct2(other=3Dobs[1])
+
+ def count(self, select):
+ result =3D {}
+ for ob in select:
+ result[int(ob.n)] =3D result.get(int(ob.n), 0)+1
+ return result
+
+ def testDistinct(self):
+ query =3D (Distinct2.q.otherID=3D=3DDistinct1.q.id)
+ sel =3D Distinct1.select(query)
+ self.assertEqual(self.count(sel),
+ {0: 2, 1: 1})
+ sel =3D Distinct1.select(query, distinct=3DTrue)
+ self.assertEqual(self.count(sel),
+ {0: 1, 1:1})
+
+########################################
## Run from command-line:
########################################
=20
|
|
From: <sub...@co...> - 2004-09-23 06:33:35
|
Author: ianb
Date: 2004-09-22 22:21:22 -0400 (Wed, 22 Sep 2004)
New Revision: 224
Added:
trunk/SQLObject/sqlobject/index.py
Modified:
trunk/SQLObject/docs/News.txt
trunk/SQLObject/docs/SQLObject.txt
trunk/SQLObject/sqlobject/__init__.py
trunk/SQLObject/sqlobject/col.py
trunk/SQLObject/sqlobject/dbconnection.py
trunk/SQLObject/sqlobject/firebird/firebirdconnection.py
trunk/SQLObject/sqlobject/main.py
trunk/SQLObject/sqlobject/maxdb/maxdbconnection.py
trunk/SQLObject/sqlobject/mysql/mysqlconnection.py
trunk/SQLObject/sqlobject/postgres/pgconnection.py
trunk/SQLObject/sqlobject/sqlite/sqliteconnection.py
trunk/SQLObject/sqlobject/sybase/sybaseconnection.py
trunk/SQLObject/tests/SQLObjectTest.py
trunk/SQLObject/tests/test.py
Log:
* Added indexing
* Documentation thereof
* Maybe made ForeignKey naming more robust (keep track of the
original name in .origName)
* Added a .module attribute to connections
* Small reorganization of tests
Modified: trunk/SQLObject/docs/News.txt
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/docs/News.txt 2004-09-22 22:39:54 UTC (rev 223)
+++ trunk/SQLObject/docs/News.txt 2004-09-23 02:21:22 UTC (rev 224)
@@ -15,6 +15,15 @@
=20
* Added a connection parameter to all class methods (patch 974755)
=20
+* Added indexing (from Jeremy Fitzhardinge). See `the
+ documentation`__ for more.
+
+__: SQLObject.html#indexes
+
+* Connection objects have a ``.module`` attribute, which points to
+ the DB-API module. This is useful for getting access to the
+ exception objects.
+
SQLObject 0.6
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
=20
Modified: trunk/SQLObject/docs/SQLObject.txt
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/docs/SQLObject.txt 2004-09-22 22:39:54 UTC (rev 223)
+++ trunk/SQLObject/docs/SQLObject.txt 2004-09-23 02:21:22 UTC (rev 224)
@@ -824,6 +824,41 @@
only give the name of the foreign class that is referenced.
`ForeignKey` implies an ``INT`` column.
=20
+Indexes
+~~~~~~~
+
+You can also define indexes for your tables, which is only meaningful
+when creating your tables through SQLObject (SQLObject relies on the
+database to implement the indexes). You do this again with attribute
+assignment, like::
+
+ firstLastIndex =3D DatabaseIndex('firstName', 'lastName')
+
+This creates an index on two columns, useful if you are selecting a
+particular name. Of course, you can give a single column, and you can
+give the column object (``firstName``) instead of the string name.
+Note that if you use ``unique`` or ``alternateID`` (which implies
+``unique``) the database may make an index for you, and primary keys
+are always indexed.
+
+If you give the keyword argument ``unique`` to `DatabaseIndex` you'll
+create a unique index -- the combination of columns must be unique.
+
+You can also use dictionaries in place of the column names, to add
+extra options. E.g.::
+
+ lastNameIndex =3D DatabaseIndex({'expression': 'lower(last_name)'})
+
+In that case, the index will be on the lower-case version of the
+column. It seems that only PostgreSQL supports this. You can also
+do::
+
+ lastNameIndex =3D DatabaseIndex({'column': lastName, 'length': 10})
+
+Which asks the database to only pay attention to the first ten
+characters. Only MySQL supports this, but it is ignored in other
+databases.
+
Creating and Dropping Tables
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
=20
@@ -1051,6 +1086,12 @@
=20
.. _kinterbasdb: http://kinterbasdb.sourceforge.net/
=20
+If you are using indexes and get an error like *key size exceeds
+implementation restriction for index*, see `this page`_ to understand
+the restrictions on your indexing.
+
+.. _this page: http://www.volny.cz/iprenosil/interbase/ip_ib_indexcalcul=
ator.htm
+
DBMConnection
-------------
=20
Modified: trunk/SQLObject/sqlobject/__init__.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/__init__.py 2004-09-22 22:39:54 UTC (rev 22=
3)
+++ trunk/SQLObject/sqlobject/__init__.py 2004-09-23 02:21:22 UTC (rev 22=
4)
@@ -3,6 +3,7 @@
from sqlbuilder import AND, OR, NOT, IN, LIKE, CONTAINSSTRING, const, fu=
nc
from styles import *
from joins import *
+from index import *
from include import validators
from dbconnection import connectionForURI
=20
Modified: trunk/SQLObject/sqlobject/col.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/col.py 2004-09-22 22:39:54 UTC (rev 223)
+++ trunk/SQLObject/sqlobject/col.py 2004-09-23 02:21:22 UTC (rev 224)
@@ -40,7 +40,8 @@
cascade=3DNone,
lazy=3DFalse,
noCache=3DFalse,
- forceDBName=3DFalse):
+ forceDBName=3DFalse,
+ origName=3DNone):
=20
# This isn't strictly true, since we *could* use backquotes or
# " or something (database-specific) around column names, but
@@ -118,6 +119,9 @@
self.validator =3D validator
self.noCache =3D noCache
self.lazy =3D lazy
+ # this is in case of ForeignKey, where we rename the column
+ # and append an ID
+ self.origName =3D origName or name
=20
def _set_validator(self, value):
self._validator =3D value
@@ -439,6 +443,7 @@
if not kw.get('name'):
kw['name'] =3D style.instanceAttrToIDAttr(style.pythonClassT=
oAttr(foreignKey))
else:
+ kw['origName'] =3D kw['name']
if not kw['name'].upper().endswith('ID'):
kw['name'] =3D style.instanceAttrToIDAttr(kw['name'])
SOKeyCol.__init__(self, **kw)
Modified: trunk/SQLObject/sqlobject/dbconnection.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/dbconnection.py 2004-09-22 22:39:54 UTC (re=
v 223)
+++ trunk/SQLObject/sqlobject/dbconnection.py 2004-09-23 02:21:22 UTC (re=
v 224)
@@ -326,6 +326,12 @@
def _SO_dropJoinTable(self, join):
self.query("DROP TABLE %s" % join.intermediateTable)
=20
+ def _SO_createIndex(self, soClass, index):
+ self.query(self.createIndexSQL(soClass, index))
+
+ def createIndexSQL(self, soClass, index):
+ assert 0, 'Implement in subclasses'
+
def createTable(self, soClass):
self.query(self.createTableSQL(soClass))
=20
Modified: trunk/SQLObject/sqlobject/firebird/firebirdconnection.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/firebird/firebirdconnection.py 2004-09-22 2=
2:39:54 UTC (rev 223)
+++ trunk/SQLObject/sqlobject/firebird/firebirdconnection.py 2004-09-23 0=
2:21:22 UTC (rev 224)
@@ -15,7 +15,8 @@
global kinterbasdb
if kinterbasdb is None:
import kinterbasdb
-
+ self.module =3D kinterbasdb
+ =20
self.limit_re =3D re.compile('^\s*(select )(.*)', re.IGNORECASE)
=20
if not autoCommit and not kw.has_key('pool'):
@@ -26,7 +27,10 @@
self.db =3D db
self.user =3D user
self.passwd =3D passwd
- self.dialect =3D int(dialect)
+ if dialect:
+ self.dialect =3D int(dialect)
+ else:
+ self.dialect =3D None
self.role =3D role
self.charset =3D charset
=20
@@ -65,14 +69,17 @@
pass
=20
def makeConnection(self):
+ extra =3D {}
+ if self.dialect:
+ extra['dialect'] =3D self.dialect
return kinterbasdb.connect(
host=3Dself.host,
database=3Dself.db,
user=3Dself.user,
password=3Dself.passwd,
- dialect=3Dself.dialect,
role=3Dself.role,
charset=3Dself.charset,
+ **extra
)
=20
def _queryInsertID(self, conn, soInstance, id, names, values):
@@ -124,6 +131,9 @@
def createIDColumn(self, soClass):
return '%s INT NOT NULL PRIMARY KEY' % soClass._idName
=20
+ def createIndexSQL(self, soClass, index):
+ return index.firebirdCreateIndexSQL(soClass)
+
def joinSQLType(self, join):
return 'INT NOT NULL'
=20
Added: trunk/SQLObject/sqlobject/index.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/index.py 2004-09-22 22:39:54 UTC (rev 223)
+++ trunk/SQLObject/sqlobject/index.py 2004-09-23 02:21:22 UTC (rev 224)
@@ -0,0 +1,139 @@
+from types import *
+import col
+from converters import sqlrepr
+
+class SODatabaseIndex(object):
+
+ def __init__(self,
+ soClass,
+ name,
+ columns,
+ unique=3DFalse):
+ self.soClass =3D soClass
+ self.name =3D name
+ self.descriptions =3D self.convertColumns(columns)
+ self.unique =3D unique
+
+ def convertColumns(self, columns):
+ """
+ Converts all the columns to dictionary descriptors;
+ dereferences string column names.
+ """
+ new =3D []
+ for desc in columns:
+ if not isinstance(desc, dict):
+ desc =3D {'column': desc}
+ if desc.has_key('expression'):
+ assert not desc.has_key('column'), (
+ 'You cannot provide both an expression and a column =
'
+ '(for %s in index %s in %s)' %
+ (desc, self.name, self.soClass))
+ assert not desc.has_key('length'), (
+ 'length does not apply to expressions (for %s in '
+ 'index %s in %s)' %
+ (desc, self.name, self.soClass))
+ new.append(desc)
+ continue
+ columnName =3D desc['column']
+ if not isinstance(columnName, str):
+ columnName =3D columnName.name
+ colDict =3D self.soClass._SO_columnDict
+ if not colDict.has_key(columnName):
+ for possible in colDict.values():
+ if possible.origName =3D=3D columnName:
+ column =3D possible
+ break
+ else:
+ # None found
+ raise ValueError, "The column by the name %r was not=
found in the class %r" % (columnName, self.soClass)
+ else:
+ column =3D colDict[columnName]
+ desc['column'] =3D column
+ new.append(desc)
+ return new
+
+ def getExpression(self, desc, db):
+ if isinstance(desc['expression'], str):
+ return desc['expression']
+ else:
+ return sqlrepr(desc['expression'], db)
+
+ def sqliteCreateIndexSQL(self, soClass):
+ if self.unique:
+ uniqueOrIndex =3D 'UNIQUE INDEX'
+ else:
+ uniqueOrIndex =3D 'INDEX'
+ spec =3D []
+ for desc in self.descriptions:
+ if desc.has_key('expression'):
+ spec.append(self.getExpression(desc, 'sqlite'))
+ else:
+ spec.append(desc['column'].dbName)
+ ret =3D 'CREATE %s %s_%s ON %s (%s)' % \
+ (uniqueOrIndex,
+ self.soClass._table,
+ self.name,
+ self.soClass._table,
+ ', '.join(spec))
+ return ret
+
+ postgresCreateIndexSQL =3D maxdbCreateIndexSQL =3D sybaseCreateIndex=
SQL =3D firebirdCreateIndexSQL =3D sqliteCreateIndexSQL
+
+ def mysqlCreateIndexSQL(self, soClass):
+ if self.unique:
+ uniqueOrIndex =3D 'UNIQUE'
+ else:
+ uniqueOrIndex =3D 'INDEX'
+ spec =3D []
+ for desc in self.descriptions:
+ if desc.has_key('expression'):
+ spec.append(self.getExpression(desc, 'mysql'))
+ elif desc.has_key('length'):
+ spec.append('%s(%d)' % (desc['column'].dbName, desc['len=
gth']))
+ else:
+ spec.append(desc['column'].dbName)
+
+ return 'ALTER TABLE %s ADD %s %s (%s)' % \
+ (soClass._table, uniqueOrIndex,
+ self.name,=20
+ ', '.join(spec))
+
+
+class DatabaseIndex(object):
+ """
+ This takes a variable number of parameters, each of which is a
+ column for indexing. Each column may be a column object or the
+ string name of the column (*not* the database name). You may also
+ use dictionaries, to further customize the indexing of the column.
+ The dictionary may have certain keys:
+
+ 'column':
+ The column object or string identifier.
+ 'length':
+ MySQL will only index the first N characters if this is
+ given. For other databases this is ignored.
+ 'expression':
+ You can create an index based on an expression, e.g.,
+ 'lower(column)'. This can either be a string or a sqlbuilder
+ expression.
+
+ Further keys may be added to the column specs in the future.
+
+ The class also take the keyword argument `unique`; if true then
+ a UNIQUE index is created.
+ """
+ =20
+ baseClass =3D SODatabaseIndex
+ =20
+ def __init__(self, *columns, **kw):
+ kw['columns'] =3D columns
+ self.kw =3D kw
+
+ def setName(self, value):
+ assert self.kw.get('name') is None, "You cannot change a name af=
ter it has already been set (from %s to %s)" % (self.kw['name'], value)
+ self.kw['name'] =3D value
+
+ def withClass(self, soClass):
+ return self.baseClass(soClass=3DsoClass, **self.kw)
+
+__all__ =3D ['DatabaseIndex']
Modified: trunk/SQLObject/sqlobject/main.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/main.py 2004-09-22 22:39:54 UTC (rev 223)
+++ trunk/SQLObject/sqlobject/main.py 2004-09-23 02:21:22 UTC (rev 224)
@@ -28,6 +28,7 @@
import types
import warnings
import joins
+import index
import classregistry
=20
import sys
@@ -63,6 +64,7 @@
=20
implicitColumns =3D []
implicitJoins =3D []
+ implicitIndexes =3D []
for attr, value in d.items():
if isinstance(value, col.Col):
value.name =3D attr
@@ -74,6 +76,11 @@
implicitJoins.append(value)
del d[attr]
continue
+ if isinstance(value, index.DatabaseIndex):
+ value.setName(attr)
+ implicitIndexes.append(value)
+ del d[attr]
+ continue =20
=20
# We *don't* want to inherit _table, so we make sure it
# is defined in this class (not a superclass)
@@ -103,6 +110,9 @@
if not d.has_key('_joins'):
newClass._joins =3D newClass._joins[:]
newClass._joins.extend(implicitJoins)
+ if not d.has_key('_indexes'):
+ newClass._indexes =3D newClass._indexes[:]
+ newClass._indexes.extend(implicitIndexes)
=20
######################################################
# Set some attributes to their defaults, if necessary.
@@ -184,6 +194,10 @@
newClass._SO_finishedClassCreation =3D True
makeProperties(newClass)
=20
+ newClass._SO_indexList =3D []
+ for idx in newClass._indexes:
+ newClass.addIndex(idx)
+
classregistry.registry(newClass._registry).addClass(newClass)
=20
# And return the class
@@ -228,7 +242,12 @@
if d.has_key(var):
if isinstance(d[var], types.MethodType) \
or isinstance(d[var], types.FunctionType):
- warnings.warn("""I tried to set the property "%s", but i=
t was already set, as a method. Methods have significantly different sem=
antics than properties, and this may be a sign of a bug in your code.""" =
% var)
+ warnings.warn(
+ "I tried to set the property %r, but it was "
+ "already set, as a method (%r). Methods have "
+ "significantly different semantics than properties, =
"
+ "and this may be a sign of a bug in your code."
+ % (var, d[var]))
continue
setFunc(var,
property(setters.get('get'), setters.get('set'),
@@ -314,6 +333,8 @@
=20
_joins =3D []
=20
+ _indexes =3D []
+
_fromDatabase =3D False
=20
_style =3D None
@@ -357,6 +378,11 @@
=20
get =3D classmethod(get)
=20
+ def addIndex(cls, indexDef):
+ index =3D indexDef.withClass(cls)
+ cls._SO_indexList.append(index)
+ addIndex =3D classmethod(addIndex)
+
def addColumn(cls, columnDef, changeSchema=3DFalse, connection=3DNon=
e):
column =3D columnDef.withClass(cls)
name =3D column.name
@@ -432,7 +458,11 @@
else:
# Same non-caching version as above.
getter =3D eval('lambda self: self._SO_foreignKey(self._=
SO_getValue(%s), self._SO_class_%s)' % (repr(name), column.foreignKey))
- setattr(cls, rawGetterName(name)[:-2], getter)
+ if column.origName.upper().endswith('ID'):
+ origName =3D column.origName[:-2]
+ else:
+ origName =3D column.origName
+ setattr(cls, rawGetterName(origName), getter)
=20
# And we set the _get_columnName version
# (sans ID ending)
@@ -975,6 +1005,7 @@
dropTable =3D classmethod(dropTable)
=20
def createTable(cls, ifNotExists=3DFalse, createJoinTables=3DTrue,
+ createIndexes=3DTrue,
connection=3DNone):
conn =3D connection or cls._connection
if ifNotExists and conn.tableExists(cls._table):
@@ -983,6 +1014,9 @@
if createJoinTables:
cls.createJoinTables(ifNotExists=3DifNotExists,
connection=3Dconn)
+ if createIndexes:
+ cls.createIndexes(ifNotExists=3DifNotExists,
+ connection=3Dconn)
createTable =3D classmethod(createTable)
=20
def createTableSQL(cls, createJoinTables=3DTrue, connection=3DNone):
@@ -1010,6 +1044,14 @@
return '\n'.join(sql)
createJoinTablesSQL =3D classmethod(createJoinTablesSQL)
=20
+ def createIndexes(cls, ifNotExists=3DFalse, connection=3DNone):
+ conn =3D connection or cls._connection
+ for index in cls._SO_indexList:
+ if not index:
+ continue
+ conn._SO_createIndex(cls, index)
+ createIndexes =3D classmethod(createIndexes)
+
def _getJoinsToCreate(cls):
joins =3D []
for join in cls._SO_joinList:
Modified: trunk/SQLObject/sqlobject/maxdb/maxdbconnection.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/maxdb/maxdbconnection.py 2004-09-22 22:39:5=
4 UTC (rev 223)
+++ trunk/SQLObject/sqlobject/maxdb/maxdbconnection.py 2004-09-23 02:21:2=
2 UTC (rev 224)
@@ -65,6 +65,7 @@
global dbapi
if dbapi is None:
from sapdb import dbapi
+ self.module =3D dbapi
self.autoCommit =3D autoCommit
self.user =3D user
self.password =3D password
@@ -173,6 +174,9 @@
def createIDColumn(self, soClass):
return '%s INT PRIMARY KEY' % soClass._idName
=20
+ def createIndexSQL(self, soClass, index):
+ return index.maxdbCreateIndexSQL(soClass)
+
def dropTable(self, tableName,cascade=3DFalse):
#we drop the table in a transaction because the removal of the
#table and the sequence must be atomic=20
Modified: trunk/SQLObject/sqlobject/mysql/mysqlconnection.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/mysql/mysqlconnection.py 2004-09-22 22:39:5=
4 UTC (rev 223)
+++ trunk/SQLObject/sqlobject/mysql/mysqlconnection.py 2004-09-23 02:21:2=
2 UTC (rev 224)
@@ -12,6 +12,7 @@
global MySQLdb
if MySQLdb is None:
import MySQLdb
+ self.module =3D MySQLdb
self.host =3D host
self.db =3D db
self.user =3D user
@@ -67,6 +68,9 @@
def createColumn(self, soClass, col):
return col.mysqlCreateSQL()
=20
+ def createIndexSQL(self, soClass, index):
+ return index.mysqlCreateIndexSQL(soClass)
+
def createIDColumn(self, soClass):
return '%s INT PRIMARY KEY AUTO_INCREMENT' % soClass._idName
=20
Modified: trunk/SQLObject/sqlobject/postgres/pgconnection.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/postgres/pgconnection.py 2004-09-22 22:39:5=
4 UTC (rev 223)
+++ trunk/SQLObject/sqlobject/postgres/pgconnection.py 2004-09-23 02:21:2=
2 UTC (rev 224)
@@ -18,11 +18,11 @@
if usePygresql:
if pgdb is None:
import pgdb
- self.pgmodule =3D pgdb
+ self.module =3D pgdb
else:
if psycopg is None:
import psycopg
- self.pgmodule =3D psycopg
+ self.module =3D psycopg
=20
if dsn is None:
dsn =3D []
@@ -50,9 +50,9 @@
=20
def makeConnection(self):
try:
- conn =3D self.pgmodule.connect(self.dsn)
- except self.pgmodule.OperationalError, e:
- raise self.pgmodule.OperationalError("%s; used connection st=
ring %r" % (e, self.dsn))
+ conn =3D self.module.connect(self.dsn)
+ except self.module.OperationalError, e:
+ raise self.module.OperationalError("%s; used connection stri=
ng %r" % (e, self.dsn))
if self.autoCommit:
conn.autocommit(1)
return conn
@@ -86,6 +86,9 @@
def createColumn(self, soClass, col):
return col.postgresCreateSQL()
=20
+ def createIndexSQL(self, soClass, index):
+ return index.postgresCreateIndexSQL(soClass)
+
def createIDColumn(self, soClass):
return '%s SERIAL PRIMARY KEY' % soClass._idName
=20
Modified: trunk/SQLObject/sqlobject/sqlite/sqliteconnection.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/sqlite/sqliteconnection.py 2004-09-22 22:39=
:54 UTC (rev 223)
+++ trunk/SQLObject/sqlobject/sqlite/sqliteconnection.py 2004-09-23 02:21=
:22 UTC (rev 224)
@@ -11,6 +11,7 @@
global sqlite
if sqlite is None:
import sqlite
+ self.module =3D sqlite
self.filename =3D filename # full path to sqlite-db-file
if not autoCommit and not kw.has_key('pool'):
# Pooling doesn't work with transactions...
@@ -71,3 +72,6 @@
result =3D self.queryOne("SELECT tbl_name FROM sqlite_master WHE=
RE type=3D'table' AND tbl_name =3D '%s'" % tableName)
# turn it into a boolean:
return not not result
+
+ def createIndexSQL(self, soClass, index):
+ return index.sqliteCreateIndexSQL(soClass)
Modified: trunk/SQLObject/sqlobject/sybase/sybaseconnection.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/sybase/sybaseconnection.py 2004-09-22 22:39=
:54 UTC (rev 223)
+++ trunk/SQLObject/sqlobject/sybase/sybaseconnection.py 2004-09-23 02:21=
:22 UTC (rev 224)
@@ -17,6 +17,7 @@
from Sybase import NumericType
from sqlobject.converters import registerConverter, IntConve=
rter
registerConverter(NumericType, IntConverter)
+ self.module =3D Sybase
self.locking =3D int(locking)
self.host =3D host
self.db =3D db
@@ -104,6 +105,9 @@
def createIDColumn(self, soClass):
return '%s NUMERIC(18,0) IDENTITY UNIQUE' % soClass._idName
=20
+ def createIndexSQL(self, soClass, index):
+ return index.sybaseCreateIndexSQL(soClass)
+
def joinSQLType(self, join):
return 'NUMERIC(18,0) NOT NULL'
=20
Modified: trunk/SQLObject/tests/SQLObjectTest.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/tests/SQLObjectTest.py 2004-09-22 22:39:54 UTC (rev 2=
23)
+++ trunk/SQLObject/tests/SQLObjectTest.py 2004-09-23 02:21:22 UTC (rev 2=
24)
@@ -4,58 +4,63 @@
=20
True, False =3D 1=3D=3D1, 0=3D=3D1
=20
+def d(**kw): return kw
+
+defaultOptions =3D d(
+ # Add columns at runtime
+ supportDynamic=3DTrue,
+ # Automatically detect the columns
+ supportAuto=3DTrue,
+ # ENUM() columns that complain if you mis-assign
+ supportRestrictedEnum=3DTrue,
+ # Transcations, of course:
+ supportTransactions=3DTrue,
+ # If you can index on expressions
+ supportExpressionIndex=3DTrue,
+ )
+
def mysqlConnection():
- SQLObjectTest.supportDynamic =3D True
- SQLObjectTest.supportAuto =3D True
- # @@: MySQL *should* support this, but it appears not to
- # care when you assign incorrect to an ENUM...
- SQLObjectTest.supportRestrictedEnum =3D False
- # Technically it does, but now how we're using it:
- SQLObjectTest.supportTransactions =3D False
- return 'mysql://test@localhost/test'
+ return 'mysql://test@localhost/test', d(
+ # @@: MySQL *should* support this, but it appears not to
+ # care when you assign incorrect to an ENUM...
+ supportRestrictedEnum=3DFalse,
+ # Technically it does, but not how we're using it:
+ supportTransactions=3DFalse,
+ supportExpressionIndex=3DFalse)
=20
def dbmConnection():
- SQLObjectTest.supportDynamic =3D True
- SQLObjectTest.supportAuto =3D False
- SQLObjectTest.supportRestrictedEnum =3D False
- SQLObjectTest.supportTransactions =3D False
- return 'dbm:///data'
+ return 'dbm:///data', d(
+ supportAuto=3DFalse,
+ supportRestrictedEnum=3DFalse,
+ supportTransactions=3DFalse)
=20
def postgresConnection():
- SQLObjectTest.supportDynamic =3D True
- SQLObjectTest.supportAuto =3D True
- SQLObjectTest.supportRestrictedEnum =3D True
- SQLObjectTest.supportTransactions =3D True
- return 'postgres:///test'
+ return 'postgres:///test', d()
=20
def pygresConnection():
- SQLObjectTest.supportDynamic =3D True
- SQLObjectTest.supportAuto =3D True
- SQLObjectTest.supportRestrictedEnum =3D True
- SQLObjectTest.supportTransactions =3D True
- return 'pygresql://localhost/test'
+ return 'pygresql://localhost/test', d()
=20
def sqliteConnection():
- SQLObjectTest.supportDynamic =3D False
- SQLObjectTest.supportAuto =3D False
- SQLObjectTest.supportRestrictedEnum =3D False
SQLObjectTest.supportTransactions =3D True
- return 'sqlite:///%s/data/sqlite.data' % os.getcwd()
+ return 'sqlite:///%s/data/sqlite.data' % os.getcwd(), d(
+ supportDynamic=3DFalse,
+ supportAuto=3DFalse,
+ supportRestrictedEnum=3DFalse,
+ supportExpressionIndex=3DFalse)
=20
def sybaseConnection():
- SQLObjectTest.supportDynamic =3D False
- SQLObjectTest.supportAuto =3D False
- SQLObjectTest.supportRestrictedEnum =3D False
- SQLObjectTest.supportTransactions =3D False
- return 'sybase://test:test123@sybase/test?autoCommit=3D0'
+ return 'sybase://test:test123@sybase/test?autoCommit=3D0', d(
+ # This seems awfully pessimistic:
+ supportDynamic=3DFalse,
+ supportAuto=3DFalse,
+ supportRestrictedEnum=3DFalse)
=20
def firebirdConnection():
- SQLObjectTest.supportDynamic =3D True
- SQLObjectTest.supportAuto =3D False
- SQLObjectTest.supportRestrictedEnum =3D True
- SQLObjectTest.supportTransactions =3D True
- return 'firebird://sysdba:masterkey@localhost/var/lib/firebird/data/=
test.gdb'
+ return 'firebird://sysdba:masterkey@localhost/var/lib/firebird/data/=
test.gdb', d(
+ supportAuto=3DFalse,
+ supportExpressionIndex=3DFalse)
=20
+
_supportedDatabases =3D {
'mysql': 'MySQLdb',
'postgres': 'psycopg',
@@ -85,6 +90,14 @@
=20
databaseName =3D None
=20
+ requireSupport =3D ()
+
+ def hasSupport(self):
+ for attr in self.requireSupport:
+ if not getattr(self, attr):
+ return False
+ return True
+
def setUp(self):
global __connection__
if isinstance(__connection__, str):
@@ -93,6 +106,8 @@
print
print '#' * 70
unittest.TestCase.setUp(self)
+ if not self.hasSupport():
+ return
if self.debugInserts:
__connection__.debug =3D True
__connection__.debugOuput =3D self.debugOutput
@@ -136,6 +151,8 @@
=20
def tearDown(self):
unittest.TestCase.tearDown(self)
+ if not self.hasSupport():
+ return
__connection__.debug =3D 0
classes =3D self.classes[:]
classes.reverse()
@@ -146,7 +163,13 @@
def setDatabaseType(t):
global __connection__
try:
- conn =3D globals()[t + "Connection"]()
+ conn, ops =3D globals()[t + "Connection"]()
+ default =3D defaultOptions.copy()
+ default.update(ops)
+ ops =3D default
+ for name, value in ops.items():
+ setattr(SQLObjectTest, name, value)
+ =20
except KeyError:
raise KeyError, 'No connection by the type %s is known' % t
SQLObjectTest.databaseName =3D t
Modified: trunk/SQLObject/tests/test.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/tests/test.py 2004-09-22 22:39:54 UTC (rev 223)
+++ trunk/SQLObject/tests/test.py 2004-09-23 02:21:22 UTC (rev 224)
@@ -1137,6 +1137,62 @@
=20
=20
########################################
+## Indexes
+########################################
+
+class SOIndex1(SQLObject):
+ name =3D StringCol(length=3D100)
+ number =3D IntCol()
+
+ nameIndex =3D DatabaseIndex('name', unique=3DTrue)
+ nameIndex2 =3D DatabaseIndex(name, number)
+ nameIndex3 =3D DatabaseIndex({'column': name,
+ 'length': 3})
+
+class SOIndex2(SQLObject):
+
+ name =3D StringCol()
+
+ nameIndex =3D DatabaseIndex({'expression': 'lower(name)'})
+
+class IndexTest1(SQLObjectTest):
+
+ classes =3D [SOIndex1]
+
+ def test(self):
+ n =3D 0
+ for name in 'blah blech boring yep yort snort'.split():
+ n +=3D 1
+ SOIndex1(name=3Dname, number=3Dn)
+ mod =3D SOIndex1._connection.module
+ # Firebird doesn't throw an integrity error, unfortunately:
+ if mod.__name__.endswith('kinterbasdb'):
+ exc =3D mod.ProgrammingError
+ else:
+ exc =3D mod.IntegrityError
+ try:
+ SOIndex1(name=3D'blah', number=3D0)
+ except exc:
+ # expected
+ pass
+ else:
+ assert 0, "Exception expected."
+
+class IndexTest2(SQLObjectTest):
+
+ classes =3D [SOIndex2]
+
+ requireSupport =3D ('supportExpressionIndex',)
+ =20
+ def test(self):
+ # Not much to test, just want to make sure the table works
+ # properly
+ if not self.hasSupport():
+ return
+ SOIndex2(name=3D'')
+
+
+########################################
## Run from command-line:
########################################
=20
@@ -1254,3 +1310,4 @@
if doCoverage:
coverage.stop()
coverModules()
+
|
|
From: <sub...@co...> - 2004-09-23 02:52:03
|
Author: ianb
Date: 2004-09-22 18:39:54 -0400 (Wed, 22 Sep 2004)
New Revision: 223
Modified:
trunk/SQLObject/sqlobject/joins.py
Log:
Applied patch for joinMethodName, from Cyril Elkaim, 09/01/04
Modified: trunk/SQLObject/sqlobject/joins.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/joins.py 2004-09-22 22:39:06 UTC (rev 222)
+++ trunk/SQLObject/sqlobject/joins.py 2004-09-22 22:39:54 UTC (rev 223)
@@ -30,6 +30,9 @@
return self._joinMethodName
=20
def withClass(self, soClass):
+ if self.kw.has_key('joinMethodName'):
+ self._joinMethodName =3D self.kw['joinMethodName']
+ del self.kw['joinMethodName']=20
return self.baseClass(soClass=3DsoClass,
joinMethodName=3Dself._joinMethodName,
**self.kw)
|
|
From: <sub...@co...> - 2004-09-23 02:51:14
|
Author: ianb
Date: 2004-09-22 18:39:06 -0400 (Wed, 22 Sep 2004)
New Revision: 222
Modified:
trunk/SQLObject/sqlobject/main.py
Log:
typo
Modified: trunk/SQLObject/sqlobject/main.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/main.py 2004-09-22 22:31:47 UTC (rev 221)
+++ trunk/SQLObject/sqlobject/main.py 2004-09-22 22:39:06 UTC (rev 222)
@@ -966,7 +966,7 @@
=20
def dropTable(cls, ifExists=3DFalse, dropJoinTables=3DTrue, cascade=3D=
False,
connection=3DNone):
- conn =3D connection or conn._connection
+ conn =3D connection or cls._connection
if ifExists and not conn.tableExists(cls._table):
return
conn.dropTable(cls._table, cascade)
|
|
From: <sub...@co...> - 2004-09-23 02:43:55
|
Author: ianb
Date: 2004-09-22 18:31:47 -0400 (Wed, 22 Sep 2004)
New Revision: 221
Modified:
trunk/SQLObject/README.txt
trunk/SQLObject/docs/SQLObject.txt
trunk/SQLObject/setup.py
Log:
Updated version numbers to 0.6.1; added an announcement email template
Modified: trunk/SQLObject/README.txt
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/README.txt 2004-09-22 22:31:30 UTC (rev 220)
+++ trunk/SQLObject/README.txt 2004-09-22 22:31:47 UTC (rev 221)
@@ -1,5 +1,5 @@
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
-SQLObject 0.5.1
+SQLObject 0.6.1
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
=20
:Author: Ian Bicking
Modified: trunk/SQLObject/docs/SQLObject.txt
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/docs/SQLObject.txt 2004-09-22 22:31:30 UTC (rev 220)
+++ trunk/SQLObject/docs/SQLObject.txt 2004-09-22 22:31:47 UTC (rev 221)
@@ -1,5 +1,5 @@
```````````````
-SQLObject 0.6
+SQLObject 0.6.1
```````````````
=20
.. contents:: Contents:
Modified: trunk/SQLObject/setup.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/setup.py 2004-09-22 22:31:30 UTC (rev 220)
+++ trunk/SQLObject/setup.py 2004-09-22 22:31:47 UTC (rev 221)
@@ -13,7 +13,7 @@
DistributionMetadata.download_url =3D None
=20
setup(name=3D"SQLObject",
- version=3D"0.6",
+ version=3D"0.6.1",
description=3D"Object-Relational Manager, aka database wrapper",
long_description=3D"""\
Classes created using SQLObject wrap database rows, presenting a
@@ -34,10 +34,52 @@
url=3D"http://sqlobject.org",
license=3D"LGPL",
packages=3D["sqlobject"] + ['sqlobject.%s' % package for package i=
n subpackages],
- download_url=3D"http://prdownloads.sourceforge.net/sqlobject/SQLOb=
ject-0.6.tar.gz?download")
+ download_url=3D"http://prdownloads.sourceforge.net/sqlobject/SQLOb=
ject-0.6.1.tar.gz?download")
=20
# Send announce to:
# sql...@li...
# db...@py...
# pyt...@py...
# pyt...@py...
+
+# Email tempate:
+"""
+@@ INTRO
+
+What is SQLObject
+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
+
+SQLObject is an object-relational mapper. Your database tables are desc=
ribed as classes, and rows are instances of those classes. SQLObject is =
meant to be easy to use and quick to get started with.
+
+SQLObject supports a number of backends: MySQL, PostgreSQL, SQLite, and =
Firebird. It also has newly added support for Sybase and MaxDB (also kno=
wn as SAPDB).
+
+
+Where is SQLObject
+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
+
+Site:
+http://sqlobject.org
+
+Mailing list:
+https://lists.sourceforge.net/mailman/listinfo/sqlobject-discuss
+
+Archives:
+http://news.gmane.org/gmane.comp.python.sqlobject
+
+Download:
+http://prdownloads.sourceforge.net/sqlobject/SQLObject-@@.tar.gz?downloa=
d
+
+News and changes:
+http://sqlobject.org/docs/News.html
+
+
+What's New
+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
+
+@@ CHANGES
+
+For a more complete list, please see the news: http://sqlobject.org/docs=
/News.html
+
+--=20
+Ian Bicking / ia...@co... / http://blog.ianbicking.org
+"""
|
|
From: <sub...@co...> - 2004-09-23 02:43:39
|
Author: ianb Date: 2004-09-22 18:31:30 -0400 (Wed, 22 Sep 2004) New Revision: 220 Modified: trunk/SQLObject/docs/News.txt Log: news for last patch Modified: trunk/SQLObject/docs/News.txt =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/SQLObject/docs/News.txt 2004-09-22 22:29:26 UTC (rev 219) +++ trunk/SQLObject/docs/News.txt 2004-09-22 22:31:30 UTC (rev 220) @@ -7,6 +7,14 @@ =20 .. _start: =20 +SQLObject 0.6.1 +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Interface Changes +----------------- + +* Added a connection parameter to all class methods (patch 974755) + SQLObject 0.6 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 |
|
From: <sub...@co...> - 2004-09-23 02:41:35
|
Author: ianb
Date: 2004-09-22 18:29:26 -0400 (Wed, 22 Sep 2004)
New Revision: 219
Modified:
trunk/SQLObject/sqlobject/main.py
Log:
Applied patch [ 974755 ] add connection parameters to all class methods i=
n SQLObject
Modified: trunk/SQLObject/sqlobject/main.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/main.py 2004-09-22 22:28:41 UTC (rev 218)
+++ trunk/SQLObject/sqlobject/main.py 2004-09-22 22:29:26 UTC (rev 219)
@@ -357,7 +357,7 @@
=20
get =3D classmethod(get)
=20
- def addColumn(cls, columnDef, changeSchema=3DFalse):
+ def addColumn(cls, columnDef, changeSchema=3DFalse, connection=3DNon=
e):
column =3D columnDef.withClass(cls)
name =3D column.name
assert name !=3D 'id', "The 'id' column is implicit, and should =
not be defined as a column"
@@ -462,15 +462,17 @@
setattr(cls, column.alternateMethodName, classmethod(func))
=20
if changeSchema:
- cls._connection.addColumn(cls._table, column)
+ conn =3D connection or cls._connection
+ conn.addColumn(cls._table, column)
=20
if cls._SO_finishedClassCreation:
makeProperties(cls)
=20
addColumn =3D classmethod(addColumn)
=20
- def addColumnsFromDatabase(cls):
- for columnDef in cls._connection.columnsFromSchema(cls._table, c=
ls):
+ def addColumnsFromDatabase(cls, connection=3DNone):
+ conn =3D connection or cls._connection
+ for columnDef in conn.columnsFromSchema(cls._table, cls):
alreadyExists =3D False
for c in cls._columns:
if c.name =3D=3D columnDef.name:
@@ -481,7 +483,7 @@
=20
addColumnsFromDatabase =3D classmethod(addColumnsFromDatabase)
=20
- def delColumn(cls, column, changeSchema=3DFalse):
+ def delColumn(cls, column, changeSchema=3DFalse, connection=3DNone):
if isinstance(column, str):
column =3D cls._SO_columnDict[column]
if isinstance(column, col.Col):
@@ -510,7 +512,8 @@
delattr(cls, column.alternateMethodName)
=20
if changeSchema:
- cls._connection.delColumn(cls._table, column)
+ conn =3D connection or cls._connection
+ conn.delColumn(cls._table, column)
=20
if cls._SO_finishedClassCreation:
unmakeProperties(cls)
@@ -954,48 +957,56 @@
select =3D classmethod(select)
=20
def selectBy(cls, connection=3DNone, **kw):
+ conn =3D connection or cls._connection
return SelectResults(cls,
- cls._connection._SO_columnClause(cls, kw),
- connection=3Dconnection)
+ conn._SO_columnClause(cls, kw),
+ connection=3Dconn)
=20
selectBy =3D classmethod(selectBy)
=20
- # 3-03 @@: Should these have a connection argument?
- def dropTable(cls, ifExists=3DFalse, dropJoinTables=3DTrue, cascade=3D=
False):
- if ifExists and not cls._connection.tableExists(cls._table):
+ def dropTable(cls, ifExists=3DFalse, dropJoinTables=3DTrue, cascade=3D=
False,
+ connection=3DNone):
+ conn =3D connection or conn._connection
+ if ifExists and not conn.tableExists(cls._table):
return
- cls._connection.dropTable(cls._table, cascade)
+ conn.dropTable(cls._table, cascade)
if dropJoinTables:
- cls.dropJoinTables(ifExists=3DifExists)
+ cls.dropJoinTables(ifExists=3DifExists, connection=3Dconn)
dropTable =3D classmethod(dropTable)
=20
- def createTable(cls, ifNotExists=3DFalse, createJoinTables=3DTrue):
- if ifNotExists and cls._connection.tableExists(cls._table):
+ def createTable(cls, ifNotExists=3DFalse, createJoinTables=3DTrue,
+ connection=3DNone):
+ conn =3D connection or cls._connection
+ if ifNotExists and conn.tableExists(cls._table):
return
- cls._connection.createTable(cls)
+ conn.createTable(cls)
if createJoinTables:
- cls.createJoinTables(ifNotExists=3DifNotExists)
+ cls.createJoinTables(ifNotExists=3DifNotExists,
+ connection=3Dconn)
createTable =3D classmethod(createTable)
=20
- def createTableSQL(cls, createJoinTables=3DTrue):
- sql =3D cls._connection.createTableSQL(cls)
+ def createTableSQL(cls, createJoinTables=3DTrue, connection=3DNone):
+ conn =3D connection or cls._connection
+ sql =3D conn.createTableSQL(cls)
if createJoinTables:
- sql +=3D '\n' + cls.createJoinTablesSQL()
+ sql +=3D '\n' + cls.createJoinTablesSQL(connection=3Dconn)
return sql
createTableSQL =3D classmethod(createTableSQL)
=20
- def createJoinTables(cls, ifNotExists=3DFalse):
+ def createJoinTables(cls, ifNotExists=3DFalse, connection=3DNone):
+ conn =3D connection or cls._connection
for join in cls._getJoinsToCreate():
if ifNotExists and \
- cls._connection.tableExists(join.intermediateTable):
+ conn.tableExists(join.intermediateTable):
continue
- cls._connection._SO_createJoinTable(join)
+ conn._SO_createJoinTable(join)
createJoinTables =3D classmethod(createJoinTables)
=20
- def createJoinTablesSQL(cls):
+ def createJoinTablesSQL(cls, connection=3DNone):
+ conn =3D connection or cls._connection
sql =3D []
for join in cls._getJoinsToCreate():
- sql.append(cls._connection._SO_createJoinTableSQL(join))
+ sql.append(conn._SO_createJoinTableSQL(join))
return '\n'.join(sql)
createJoinTablesSQL =3D classmethod(createJoinTablesSQL)
=20
@@ -1012,7 +1023,8 @@
return joins
_getJoinsToCreate =3D classmethod(_getJoinsToCreate)
=20
- def dropJoinTables(cls, ifExists=3DFalse):
+ def dropJoinTables(cls, ifExists=3DFalse, connection=3DNone):
+ conn =3D connection or cls._connection
for join in cls._SO_joinList:
if not join:
continue
@@ -1021,16 +1033,17 @@
if join.soClass.__name__ > join.otherClass.__name__:
continue
if ifExists and \
- not cls._connection.tableExists(join.intermediateTable):
+ not conn.tableExists(join.intermediateTable):
continue
- cls._connection._SO_dropJoinTable(join)
+ conn._SO_dropJoinTable(join)
=20
dropJoinTables =3D classmethod(dropJoinTables)
=20
- def clearTable(cls):
+ def clearTable(cls, connection=3DNone):
# 3-03 @@: Maybe this should check the cache... but it's
# kind of crude anyway, so...
- cls._connection.clearTable(cls._table)
+ conn =3D connection or cls._connection
+ conn.clearTable(cls._table)
clearTable =3D classmethod(clearTable)
=20
def destroySelf(self):
@@ -1074,8 +1087,8 @@
self.id,
' '.join(['%s=3D%s' % (name, repr(value)) for name, va=
lue in self._reprItems()]))
=20
- def sqlrepr(cls, value):
- return cls._connection.sqlrepr(value)
+ def sqlrepr(cls, value, connection=3DNone):
+ return (connection or cls._connection).sqlrepr(value)
=20
sqlrepr =3D classmethod(sqlrepr)
=20
|
|
From: <sub...@co...> - 2004-09-23 02:40:52
|
Author: ianb
Date: 2004-09-22 18:28:41 -0400 (Wed, 22 Sep 2004)
New Revision: 218
Modified:
trunk/SQLObject/sqlobject/postgres/pgconnection.py
Log:
provide a better error message when having connection problems
Modified: trunk/SQLObject/sqlobject/postgres/pgconnection.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/postgres/pgconnection.py 2004-09-22 00:24:4=
4 UTC (rev 217)
+++ trunk/SQLObject/sqlobject/postgres/pgconnection.py 2004-09-22 22:28:4=
1 UTC (rev 218)
@@ -49,7 +49,10 @@
conn.autocommit(auto)
=20
def makeConnection(self):
- conn =3D self.pgmodule.connect(self.dsn)
+ try:
+ conn =3D self.pgmodule.connect(self.dsn)
+ except self.pgmodule.OperationalError, e:
+ raise self.pgmodule.OperationalError("%s; used connection st=
ring %r" % (e, self.dsn))
if self.autoCommit:
conn.autocommit(1)
return conn
|
|
From: <sub...@co...> - 2004-09-22 04:36:47
|
Author: ianb
Date: 2004-09-21 20:24:44 -0400 (Tue, 21 Sep 2004)
New Revision: 217
Added:
branches/SQLObject/0.6/
Modified:
branches/SQLObject/0.6/sqlobject/postgres/pgconnection.py
Log:
Created branch for 0.6
Copied: branches/SQLObject/0.6 (from rev 215, trunk/SQLObject)
Modified: branches/SQLObject/0.6/sqlobject/postgres/pgconnection.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/postgres/pgconnection.py 2004-09-03 17:05:0=
0 UTC (rev 215)
+++ branches/SQLObject/0.6/sqlobject/postgres/pgconnection.py 2004-09-22 =
00:24:44 UTC (rev 217)
@@ -49,7 +49,10 @@
conn.autocommit(auto)
=20
def makeConnection(self):
- conn =3D self.pgmodule.connect(self.dsn)
+ try:
+ conn =3D self.pgmodule.connect(self.dsn)
+ except self.pgmodule.OperationalError, e:
+ raise self.pgmodule.OperationalError("%s; used connection st=
ring %r" % (e, self.dsn))
if self.autoCommit:
conn.autocommit(1)
return conn
|
|
From: <sub...@co...> - 2004-09-22 04:36:31
|
Author: ianb
Date: 2004-09-21 20:24:26 -0400 (Tue, 21 Sep 2004)
New Revision: 216
Modified:
branches/SQLObject/0.5/README.txt
branches/SQLObject/0.5/docs/News.txt
branches/SQLObject/0.5/docs/SQLObject.txt
branches/SQLObject/0.5/setup.py
Log:
Minor changes for the release
Modified: branches/SQLObject/0.5/README.txt
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/SQLObject/0.5/README.txt 2004-09-03 17:05:00 UTC (rev 215)
+++ branches/SQLObject/0.5/README.txt 2004-09-22 00:24:26 UTC (rev 216)
@@ -1,5 +1,5 @@
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
-SQLObject 0.5.2
+SQLObject 0.5.3
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
=20
:Author: Ian Bicking
Modified: branches/SQLObject/0.5/docs/News.txt
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/SQLObject/0.5/docs/News.txt 2004-09-03 17:05:00 UTC (rev 215=
)
+++ branches/SQLObject/0.5/docs/News.txt 2004-09-22 00:24:26 UTC (rev 216=
)
@@ -7,6 +7,19 @@
=20
.. _start:
=20
+SQLObject 0.5.3
+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
+
+Bugs
+----
+
+* Python 2.2 booleans fixed (SF: 903488)
+
+* Longs (e.g., ``1L``) get converted properly (SF: 939965)
+
+* More fixes related to .select() and holding onto the connection
+ (an extension of the fix in 0.5.2)
+
SQLObject 0.5.2
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
=20
Modified: branches/SQLObject/0.5/docs/SQLObject.txt
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/SQLObject/0.5/docs/SQLObject.txt 2004-09-03 17:05:00 UTC (re=
v 215)
+++ branches/SQLObject/0.5/docs/SQLObject.txt 2004-09-22 00:24:26 UTC (re=
v 216)
@@ -1,5 +1,5 @@
````````````````
-SQLObject 0.5.2
+SQLObject 0.5.3
````````````````
=20
.. contents:: Contents:
Modified: branches/SQLObject/0.5/setup.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/SQLObject/0.5/setup.py 2004-09-03 17:05:00 UTC (rev 215)
+++ branches/SQLObject/0.5/setup.py 2004-09-22 00:24:26 UTC (rev 216)
@@ -10,7 +10,7 @@
DistributionMetadata.download_url =3D None
=20
setup(name=3D"SQLObject",
- version=3D"0.5.2",
+ version=3D"0.5.3",
description=3D"Object-Relational Manager, aka database wrapper",
long_description=3D"""\
Classes created using SQLObject wrap database rows, presenting a
@@ -31,7 +31,7 @@
url=3D"http://sqlobject.org",
license=3D"LGPL",
packages=3D["SQLObject", "SQLObject.include"],
- download_url=3D"http://prdownloads.sourceforge.net/sqlobject/SQLOb=
ject-0.5.2.tar.gz?download")
+ download_url=3D"http://prdownloads.sourceforge.net/sqlobject/SQLOb=
ject-0.5.3.tar.gz?download")
=20
# Send announce to:
# sql...@li...
|
|
From: <sub...@co...> - 2004-09-03 21:15:18
|
Author: ianb
Date: 2004-09-03 13:05:00 -0400 (Fri, 03 Sep 2004)
New Revision: 215
Modified:
trunk/SQLObject/sqlobject/firebird/firebirdconnection.py
Log:
Fixed _queryInsertID
Modified: trunk/SQLObject/sqlobject/firebird/firebirdconnection.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/firebird/firebirdconnection.py 2004-09-03 1=
7:04:14 UTC (rev 214)
+++ trunk/SQLObject/sqlobject/firebird/firebirdconnection.py 2004-09-03 1=
7:05:00 UTC (rev 215)
@@ -75,7 +75,7 @@
charset=3Dself.charset,
)
=20
- def _queryInsertID(self, conn, table, idName, id, names, values):
+ def _queryInsertID(self, conn, soInstance, id, names, values):
"""Firebird uses 'generators' to create new ids for a table.
The users needs to create a generator named GEN_<tablename>
for each table this method to work."""
|
|
From: <sub...@co...> - 2004-09-03 21:14:41
|
Author: ianb
Date: 2004-09-03 13:04:14 -0400 (Fri, 03 Sep 2004)
New Revision: 214
Modified:
trunk/SQLObject/sqlobject/firebird/firebirdconnection.py
Log:
Force firebird's dialect connection option to be an integer
Modified: trunk/SQLObject/sqlobject/firebird/firebirdconnection.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/firebird/firebirdconnection.py 2004-09-03 1=
2:47:16 UTC (rev 213)
+++ trunk/SQLObject/sqlobject/firebird/firebirdconnection.py 2004-09-03 1=
7:04:14 UTC (rev 214)
@@ -26,7 +26,7 @@
self.db =3D db
self.user =3D user
self.passwd =3D passwd
- self.dialect =3D dialect
+ self.dialect =3D int(dialect)
self.role =3D role
self.charset =3D charset
=20
|
|
From: <sub...@co...> - 2004-09-03 16:57:35
|
Author: ianb
Date: 2004-09-03 08:47:16 -0400 (Fri, 03 Sep 2004)
New Revision: 213
Modified:
trunk/SQLObject/sqlobject/main.py
Log:
Fixed problem with fromPython validators
Modified: trunk/SQLObject/sqlobject/main.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/main.py 2004-09-03 11:53:06 UTC (rev 212)
+++ trunk/SQLObject/sqlobject/main.py 2004-09-03 12:47:16 UTC (rev 213)
@@ -760,8 +760,10 @@
for name, value in kw.items():
fromPython =3D getattr(self, '_SO_fromPython_%s' % name,=
None)
if fromPython:
- value =3D fromPython(value, self._SO_validatorState)
- toUpdate[name] =3D value
+ dbValue =3D fromPython(value, self._SO_validatorStat=
e)
+ else:
+ dbValue =3D value
+ toUpdate[name] =3D dbValue
if self._cacheValues:
setattr(self, instanceName(name), value)
for name, value in extra.items():
|
|
From: <sub...@co...> - 2004-09-03 16:03:24
|
Author: ianb
Date: 2004-09-03 07:53:06 -0400 (Fri, 03 Sep 2004)
New Revision: 212
Modified:
trunk/SQLObject/sqlobject/firebird/firebirdconnection.py
Log:
Added extra arguments that get passed to firebird connections
Modified: trunk/SQLObject/sqlobject/firebird/firebirdconnection.py
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/SQLObject/sqlobject/firebird/firebirdconnection.py 2004-09-03 1=
1:50:04 UTC (rev 211)
+++ trunk/SQLObject/sqlobject/firebird/firebirdconnection.py 2004-09-03 1=
1:53:06 UTC (rev 212)
@@ -10,7 +10,8 @@
schemes =3D [dbName]
=20
def __init__(self, host, db, user=3D'sysdba',
- passwd=3D'masterkey', autoCommit=3D1, **kw):
+ passwd=3D'masterkey', autoCommit=3D1,
+ dialect=3DNone, role=3DNone, charset=3DNone, **kw):
global kinterbasdb
if kinterbasdb is None:
import kinterbasdb
@@ -25,6 +26,9 @@
self.db =3D db
self.user =3D user
self.passwd =3D passwd
+ self.dialect =3D dialect
+ self.role =3D role
+ self.charset =3D charset
=20
DBAPI.__init__(self, **kw)
=20
@@ -62,8 +66,13 @@
=20
def makeConnection(self):
return kinterbasdb.connect(
- host =3D self.host, database =3D self.db,
- user =3D self.user, password =3D self.passwd
+ host=3Dself.host,
+ database=3Dself.db,
+ user=3Dself.user,
+ password=3Dself.passwd,
+ dialect=3Dself.dialect,
+ role=3Dself.role,
+ charset=3Dself.charset,
)
=20
def _queryInsertID(self, conn, table, idName, id, names, values):
|