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
|
Sep
|
Oct
|
Nov
|
Dec
|
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): |
From: <sub...@co...> - 2004-09-03 16:00:23
|
Author: ianb Date: 2004-09-03 07:50:04 -0400 (Fri, 03 Sep 2004) New Revision: 211 Modified: trunk/SQLObject/sqlobject/joins.py Log: Pay attention to joinMethodName keyword argument to joins 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-08-30 17:19:22 UTC (rev 210) +++ trunk/SQLObject/sqlobject/joins.py 2004-09-03 11:50:04 UTC (rev 211) @@ -17,7 +17,10 @@ kw['otherClass'] =3D otherClass kw['joinDef'] =3D self self.kw =3D kw - self._joinMethodName =3D None + if self.kw.has_key('joinMethodName'): + self._joinMethodName =3D self.kw.pop('joinMethodName') + else: + self._joinMethodName =3D None =20 def _set_joinMethodName(self, value): assert self._joinMethodName =3D=3D value or self._joinMethodName= is None, "You have already given an explicit joinMethodName (%s), and yo= u are now setting it to %s" % (self._joinMethodName, value) |
From: <sub...@co...> - 2004-08-30 21:29:19
|
Author: ianb Date: 2004-08-30 13:19:22 -0400 (Mon, 30 Aug 2004) New Revision: 210 Modified: trunk/SQLObject/sqlobject/col.py Log: Changed contraint name generation; since you may have two columns that are both keys to the same table, you shouldn't use=20 foreign_table_name_exists as the constraint name, as it won't be unique. Instead we use col_name_exists. 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-08-30 17:15:21 UTC (rev 209) +++ trunk/SQLObject/sqlobject/col.py 2004-08-30 17:19:22 UTC (rev 210) @@ -450,7 +450,7 @@ tName =3D other._table idName =3D other._idName if self.cascade is not None: - if self.cascade.lower() =3D=3D 'null': + if self.cascade =3D=3D 'null': action =3D 'ON DELETE SET NULL' elif self.cascade: action =3D 'ON DELETE CASCADE' @@ -458,7 +458,7 @@ action =3D 'ON DELETE RESTRICT' else: action =3D '' - constraint =3D ('CONSTRAINT %(tName)s_exists ' + constraint =3D ('CONSTRAINT %(colName)s_exists ' 'FOREIGN KEY (%(colName)s) ' 'REFERENCES %(tName)s (%(idName)s) ' '%(action)s' % |
From: <sub...@co...> - 2004-08-30 21:25:18
|
Author: ianb Date: 2004-08-30 13:15:21 -0400 (Mon, 30 Aug 2004) New Revision: 209 Modified: trunk/SQLObject/docs/News.txt trunk/SQLObject/sqlobject/col.py Log: Added CASCADE SET NULL option 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-08-30 17:07:02 UTC (rev 208) +++ trunk/SQLObject/docs/News.txt 2004-08-30 17:15:21 UTC (rev 209) @@ -43,10 +43,10 @@ * ``*Col`` constructors now support cascade: ``cascade=3DNone`` (default) means no constraint; ``cascade=3DTrue`` means that if the foreign key is deleted, the object will be deleted; - ``cascade=3DFalse`` means that the delete will fail. ``SET NULL`` is - not implemented, and the constraints are only implemented in the - DBMS, not in SQLObject (i.e., they will not work in databases like - MySQL and SQLite). + ``cascade=3DFalse`` means that the delete will fail; + ``cascade=3D"null"`` means that the column will be set to NULL. The + constraints are only implemented in the DBMS, not in SQLObject + (i.e., they will not work in databases like MySQL and SQLite). =20 * New ``_create(id, **kw)`` method that can be overridden to intercept and modify attempts to insert rows in the database. 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-08-30 17:07:02 UTC (rev 208) +++ trunk/SQLObject/sqlobject/col.py 2004-08-30 17:15:21 UTC (rev 209) @@ -450,7 +450,9 @@ tName =3D other._table idName =3D other._idName if self.cascade is not None: - if self.cascade: + if self.cascade.lower() =3D=3D 'null': + action =3D 'ON DELETE SET NULL' + elif self.cascade: action =3D 'ON DELETE CASCADE' else: action =3D 'ON DELETE RESTRICT' |
From: <sub...@co...> - 2004-08-30 21:16:57
|
Author: ianb Date: 2004-08-30 13:07:02 -0400 (Mon, 30 Aug 2004) New Revision: 208 Modified: trunk/SQLObject/sqlobject/col.py Log: Use FOREIGN KEY constraints even if cascade isn't explicitly given 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-08-30 17:01:33 UTC (rev 207) +++ trunk/SQLObject/sqlobject/col.py 2004-08-30 17:07:02 UTC (rev 208) @@ -446,20 +446,25 @@ def postgresCreateSQL(self): from main import findClass sql =3D SOKeyCol.postgresCreateSQL(self) + other =3D findClass(self.foreignKey) + tName =3D other._table + idName =3D other._idName if self.cascade is not None: - other =3D findClass(self.foreignKey) - tName =3D other._table - idName =3D other._idName - action =3D self.cascade and 'CASCADE' or 'RESTRICT' - constraint =3D ('CONSTRAINT %(tName)s_exists ' - 'FOREIGN KEY(%(colName)s) ' - 'REFERENCES %(tName)s(%(idName)s) ' - 'ON DELETE %(action)s' % - {'tName':tName, - 'colName':self.dbName, - 'idName':idName, - 'action':action}) - sql =3D ', '.join([sql, constraint]) + if self.cascade: + action =3D 'ON DELETE CASCADE' + else: + action =3D 'ON DELETE RESTRICT' + else: + action =3D '' + constraint =3D ('CONSTRAINT %(tName)s_exists ' + 'FOREIGN KEY (%(colName)s) ' + 'REFERENCES %(tName)s (%(idName)s) ' + '%(action)s' % + {'tName': tName, + 'colName': self.dbName, + 'idName': idName, + 'action': action}) + sql =3D ', '.join([sql, constraint]) return sql =20 def sybaseCreateSQL(self): |
From: <sub...@co...> - 2004-08-30 21:11:38
|
Author: ianb Date: 2004-08-30 13:01:33 -0400 (Mon, 30 Aug 2004) New Revision: 207 Modified: trunk/SQLObject/docs/News.txt trunk/SQLObject/sqlobject/dbconnection.py trunk/SQLObject/sqlobject/main.py Log: New classmethod createTableSQL() =20 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-08-25 20:30:11 UTC (rev 206) +++ trunk/SQLObject/docs/News.txt 2004-08-30 17:01:33 UTC (rev 207) @@ -56,6 +56,10 @@ This is a temporary interface; a more general specifier for primary keys will be added later. =20 +* New classmethod ``createTableSQL()`` method for SQLObject classes, + which returns the SQL that can be used to create the table. Analog + to ``createTable()``. + Bugs ---- =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-08-25 20:30:11 UTC (re= v 206) +++ trunk/SQLObject/sqlobject/dbconnection.py 2004-08-30 17:01:33 UTC (re= v 207) @@ -313,20 +313,26 @@ return q =20 def _SO_createJoinTable(self, join): - self.query('CREATE TABLE %s (\n%s %s,\n%s %s\n)' % - (join.intermediateTable, - join.joinColumn, - self.joinSQLType(join), - join.otherColumn, - self.joinSQLType(join))) + self.query(self._SO_createJoinTableSQL(join)) =20 + def _SO_createJoinTableSQL(self, join): + return ('CREATE TABLE %s (\n%s %s,\n%s %s\n)' % + (join.intermediateTable, + join.joinColumn, + self.joinSQLType(join), + join.otherColumn, + self.joinSQLType(join))) + def _SO_dropJoinTable(self, join): self.query("DROP TABLE %s" % join.intermediateTable) =20 def createTable(self, soClass): - self.query('CREATE TABLE %s (\n%s\n)' % \ - (soClass._table, self.createColumns(soClass))) + self.query(self.createTableSQL(soClass)) =20 + def createTableSQL(self, soClass): + return ('CREATE TABLE %s (\n%s\n)' %=20 + (soClass._table, self.createColumns(soClass))) + def createColumns(self, soClass): columnDefs =3D [self.createIDColumn(soClass)] \ + [self.createColumn(soClass, col) 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-08-25 20:30:11 UTC (rev 206) +++ trunk/SQLObject/sqlobject/main.py 2004-08-30 17:01:33 UTC (rev 207) @@ -975,25 +975,41 @@ cls.createJoinTables(ifNotExists=3DifNotExists) createTable =3D classmethod(createTable) =20 + def createTableSQL(cls, createJoinTables=3DTrue): + sql =3D cls._connection.createTableSQL(cls) + if createJoinTables: + sql +=3D '\n' + cls.createJoinTablesSQL() + return sql + createTableSQL =3D classmethod(createTableSQL) + def createJoinTables(cls, ifNotExists=3DFalse): + for join in cls._getJoinsToCreate(): + if ifNotExists and \ + cls._connection.tableExists(join.intermediateTable): + continue + cls._connection._SO_createJoinTable(join) + createJoinTables =3D classmethod(createJoinTables) + + def createJoinTablesSQL(cls): + sql =3D [] + for join in cls._getJoinsToCreate(): + sql.append(cls._connection._SO_createJoinTableSQL(join)) + return '\n'.join(sql) + createJoinTablesSQL =3D classmethod(createJoinTablesSQL) + + def _getJoinsToCreate(cls): + joins =3D [] for join in cls._SO_joinList: if not join: continue if not join.hasIntermediateTable(): continue - # This join will show up twice, in each of the - # classes, but we only create the table once. We - # arbitrarily create it while we're creating the - # alphabetically earlier class. if join.soClass.__name__ > join.otherClass.__name__: continue - if ifNotExists and \ - cls._connection.tableExists(join.intermediateTable): - continue - cls._connection._SO_createJoinTable(join) + joins.append(join) + return joins + _getJoinsToCreate =3D classmethod(_getJoinsToCreate) =20 - createJoinTables =3D classmethod(createJoinTables) - def dropJoinTables(cls, ifExists=3DFalse): for join in cls._SO_joinList: if not join: |