sqlobject-cvs Mailing List for SQLObject (Page 94)
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: SourceForge.net <no...@so...> - 2007-04-20 20:56:53
|
Bugs item #1592786, was opened at 2006-11-08 09:20 Message generated for change (Comment added) made by nobody You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=540672&aid=1592786&group_id=74338 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: SQLite Group: None Status: Open Resolution: Invalid Priority: 5 Private: No Submitted By: Jayhem (jayhem) Assigned to: Nobody/Anonymous (nobody) Summary: so-sqlite data corruption during updates Initial Comment: I'm hitting a bug when using SO with turbogears 1.1b with an sqlite database. When I do several successive updates to a table (which are very slow btw), data gets corrupted in the interface, select() returns invalid objects, as if objects were pulled from a cache that was out of synch with the db. >From this point, successive select() without any updates in-between can return different values, randomly selecting one of the previsouly set values. I have created a simple test-case (on turbogears) Just launch it and change some values. Usually after 10-20 changes, the corruption appears. I have tried this same testcase with MySQL and do not hit this problem. Note that dev.cfg declares sqlobject.dburi="notrans_sqlite:///..." file: model.py ====================================================== from sqlobject import * from turbogears.database import PackageHub hub = PackageHub("bug") __connection__ = hub class Item(SQLObject): data = UnicodeCol(length=40) def loaddb(): hub.begin() Item.dropTable(ifExists=True, cascade=True) hub.commit() Item.createTable(ifNotExists=True) for i in range(20): Item(data = str(i)) hub.commit() loaddb() file: controllers.py ====================================================== import turbogears from turbogears.controllers import RootController, expose from model import Item class Root(RootController): @expose(template="bug.templates.index") def index(self): items = Item.select() return dict(items = items) @expose(template="bug.templates.index") def change(self, id): item = Item.get(id) item.data += str(id) items = Item.select() return dict(items = items) file: index.kid ====================================================== <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#" py:extends="'master.kid'"> <head> <meta content="text/html; charset=UTF-8" http-equiv="content-type" py:replace="''"/> <title>Items</title> </head> <body> <ul py:for="i in items"> <li>${i.data} <a href="/change/${i.id}">[edit]</a></li> </ul> </body> </html> ---------------------------------------------------------------------- Comment By: Nobody/Anonymous (nobody) Date: 2007-04-20 13:56 Message: Logged In: NO from: he...@en... Bug: so-sqlite data corruption during updates In relation to this, I am running an aplication using only sqlobject, sqlite and python, currently I am not using TG. I have a similar error. I had created quite a few tables using three versions of sqlobject (0.8.2 0.8.1 and the development version 0.10 fron svn) in the three versions it had come with the following error: Traceback (most recent call last): File "<pyshell#16>", line 1, in -toplevel- ventas.get(3) File "/usr/lib/python2.4/site-packages/SQLObject-0.10dev_r2553-py2.4.egg/sqlobject/main.py", line 919, in get val._init(id, connection, selectResults) TypeError: _init() takes exactly 2 arguments (4 given) Currently I am using Debian testing version and sqlite-3-3-14, I am able to isolate the error to the following I create a small table called "ventas" with 24 records in it then I do in python: for x in range(1,25): print x, ventas.get(x) this print: 1 <ventas 1 producto_idID=1 fecha_idID=1 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=4000 precio=5.0> 2 <ventas 2 producto_idID=1 fecha_idID=2 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=5000 precio=5.0> 3 <ventas 3 producto_idID=1 fecha_idID=3 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=6000 precio=5.0> 4 <ventas 4 producto_idID=1 fecha_idID=4 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=7000 precio=5.0> 5 <ventas 5 producto_idID=2 fecha_idID=1 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=4000 precio=5.0> 6 <ventas 6 producto_idID=2 fecha_idID=2 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=5000 precio=5.0> 7 <ventas 7 producto_idID=2 fecha_idID=3 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=6000 precio=5.0> 8 <ventas 8 producto_idID=2 fecha_idID=4 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=7000 precio=5.0> 9 <ventas 9 producto_idID=3 fecha_idID=1 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=4000 precio=6.0> 10 <ventas 10 producto_idID=3 fecha_idID=2 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=5000 precio=6.0> 11 <ventas 11 producto_idID=3 fecha_idID=3 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=6000 precio=6.0> 12 <ventas 12 producto_idID=3 fecha_idID=4 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=7000 precio=6.0> 13 <ventas 13 producto_idID=4 fecha_idID=1 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=4000 precio=7.0> 14 <ventas 14 producto_idID=4 fecha_idID=2 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=5000 precio=7.0> 15 <ventas 15 producto_idID=4 fecha_idID=3 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=6000 precio=7.0> 16 <ventas 16 producto_idID=4 fecha_idID=4 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=7000 precio=7.0> 17 <ventas 17 producto_idID=5 fecha_idID=1 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=4000 precio=5.0> 18 <ventas 18 producto_idID=5 fecha_idID=2 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=5000 precio=5.0> 19 <ventas 19 producto_idID=5 fecha_idID=3 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=6000 precio=5.0> 20 <ventas 20 producto_idID=5 fecha_idID=4 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=7000 precio=5.0> 21 <ventas 21 producto_idID=6 fecha_idID=1 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=4000 precio=5.5> 22 <ventas 22 producto_idID=6 fecha_idID=2 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=5000 precio=5.5> 23 <ventas 23 producto_idID=6 fecha_idID=3 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=6000 precio=5.5> 24 <ventas 24 producto_idID=6 fecha_idID=4 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=7000 precio=5.5> Then I do: for x in ventas.select(): print x <ventas 1 producto_idID=1 fecha_idID=1 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=4000 precio=5.0> <ventas 2 producto_idID=1 fecha_idID=2 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=5000 precio=5.0> <ventas 3 producto_idID=1 fecha_idID=3 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=6000 precio=5.0> <ventas 4 producto_idID=1 fecha_idID=4 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=7000 precio=5.0> <ventas 5 producto_idID=2 fecha_idID=1 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=4000 precio=5.0> <ventas 6 producto_idID=2 fecha_idID=2 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=5000 precio=5.0> <ventas 7 producto_idID=2 fecha_idID=3 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=6000 precio=5.0> <ventas 8 producto_idID=2 fecha_idID=4 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=7000 precio=5.0> <ventas 9 producto_idID=3 fecha_idID=1 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=4000 precio=6.0> <ventas 10 producto_idID=3 fecha_idID=2 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=5000 precio=6.0> <ventas 11 producto_idID=3 fecha_idID=3 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=6000 precio=6.0> <ventas 12 producto_idID=3 fecha_idID=4 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=7000 precio=6.0> <ventas 13 producto_idID=4 fecha_idID=1 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=4000 precio=7.0> <ventas 14 producto_idID=4 fecha_idID=2 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=5000 precio=7.0> <ventas 15 producto_idID=4 fecha_idID=3 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=6000 precio=7.0> <ventas 16 producto_idID=4 fecha_idID=4 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=7000 precio=7.0> <ventas 17 producto_idID=5 fecha_idID=1 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=4000 precio=5.0> <ventas 18 producto_idID=5 fecha_idID=2 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=5000 precio=5.0> <ventas 19 producto_idID=5 fecha_idID=3 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=6000 precio=5.0> <ventas 20 producto_idID=5 fecha_idID=4 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=7000 precio=5.0> <ventas 21 producto_idID=6 fecha_idID=1 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=4000 precio=5.5> <ventas 22 producto_idID=6 fecha_idID=2 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=5000 precio=5.5> <ventas 23 producto_idID=6 fecha_idID=3 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=6000 precio=5.5> <ventas 24 producto_idID=6 fecha_idID=4 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=7000 precio=5.5> Then I do: for x in range(1,25): print x, ventas.get(x) 1 <ventas 1 producto_idID=1 fecha_idID=1 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=4000 precio=5.0> 2 <ventas 2 producto_idID=1 fecha_idID=2 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=5000 precio=5.0> 3 <ventas 3 producto_idID=1 fecha_idID=3 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=6000 precio=5.0> 4 <ventas 4 producto_idID=1 fecha_idID=4 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=7000 precio=5.0> 5 <ventas 5 producto_idID=2 fecha_idID=1 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=4000 precio=5.0> 6 <ventas 6 producto_idID=2 fecha_idID=2 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=5000 precio=5.0> 7 <ventas 7 producto_idID=2 fecha_idID=3 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=6000 precio=5.0> 8 <ventas 8 producto_idID=2 fecha_idID=4 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=7000 precio=5.0> 9 <ventas 9 producto_idID=3 fecha_idID=1 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=4000 precio=6.0> 10 <ventas 10 producto_idID=3 fecha_idID=2 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=5000 precio=6.0> 11 <ventas 11 producto_idID=3 fecha_idID=3 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=6000 precio=6.0> 12 <ventas 12 producto_idID=3 fecha_idID=4 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=7000 precio=6.0> 13 <ventas 13 producto_idID=4 fecha_idID=1 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=4000 precio=7.0> 14 <ventas 14 producto_idID=4 fecha_idID=2 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=5000 precio=7.0> 15 <ventas 15 producto_idID=4 fecha_idID=3 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=6000 precio=7.0> 16 <ventas 16 producto_idID=4 fecha_idID=4 status_idID=2 region_idID=1 pais_idID=1 moneda_idID=2 volumen=7000 precio=7.0> 17 <ventas 17 producto_idID=5 fecha_idID=1 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=4000 precio=5.0> 18 <ventas 18 producto_idID=5 fecha_idID=2 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=5000 precio=5.0> 19 <ventas 19 producto_idID=5 fecha_idID=3 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=6000 precio=5.0> 20 <ventas 20 producto_idID=5 fecha_idID=4 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=7000 precio=5.0> 21 <ventas 21 producto_idID=6 fecha_idID=1 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=4000 precio=5.5> 22 <ventas 22 producto_idID=6 fecha_idID=2 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=5000 precio=5.5> 23 <ventas 23 producto_idID=6 fecha_idID=3 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=6000 precio=5.5> 24 <ventas 24 producto_idID=6 fecha_idID=4 status_idID=3 region_idID=1 pais_idID=1 moneda_idID=2 volumen=7000 precio=5.5> The I do: ventas.get(1) <ventas 1 producto_idID=1 fecha_idID=1 status_idID=1 region_idID=1 pais_idID=1 moneda_idID=2 volumen=4000 precio=5.0> Then I do this one: for x in ventas.select(): print x And I obtain this error: Traceback (most recent call last): File "<pyshell#39>", line 1, in -toplevel- for x in ventas.select(): File "/usr/lib/python2.4/site-packages/SQLObject-0.10dev_r2553-py2.4.egg/sqlobject/sresults.py", line 165, in __iter__ return iter(list(self.lazyIter())) File "/usr/lib/python2.4/site-packages/SQLObject-0.10dev_r2553-py2.4.egg/sqlobject/dbconnection.py", line 814, in next obj = self.select.sourceClass.get(result[0], selectResults=result[1:], connection=self.dbconn) File "/usr/lib/python2.4/site-packages/SQLObject-0.10dev_r2553-py2.4.egg/sqlobject/main.py", line 919, in get val._init(id, connection, selectResults) TypeError: _init() takes exactly 2 arguments (4 given) Is important to note that to get the error I had to run the commands in this sequence. Also the database is only corrupted in memory, the file in the hard disk is ok. Also, it is only corrupted in odd registry id record numbers, even records are ok. I am using python2.4.4 I am sorry for the great amount of data posted. ---------------------------------------------------------------------- Comment By: Jayhem (jayhem) Date: 2006-11-14 04:04 Message: Logged In: YES user_id=1640652 You are right. the bug does not seem to cause data corruption in the database (i.e it's not a db related issue), it just causes random results to be returned from queries. Simply switching the database to MySQL solves the problem, which confirms the bug is not in the db. An even more annoying issue, which I think is related, is the extremely slow inserts/updates into sqlite, and frequent error messages telling me the db is locked. I am new to turbogears, sqlobject, sqlite and python, so I'm sorry I won't have time to work on a SqlObject-only testcase. Let me know if I can do anything to help fix this. ---------------------------------------------------------------------- Comment By: Oleg Broytmann (phd) Date: 2006-11-13 08:59 Message: Logged In: YES user_id=4799 Our company has been using SQLObject with SQLite for three rather large commercial programs. Neither of our developers, testers or users ever experienced data loss. Are you sure the problem is not TG-related? Please write an SQLObject-only test. In any case I cannot run your program - I don't have TG and not going to install it. ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=540672&aid=1592786&group_id=74338 |
|
From: SourceForge.net <no...@so...> - 2007-04-20 17:19:55
|
Patches item #1704429, was opened at 2007-04-20 17:37 Message generated for change (Comment added) made by markus_gritsch You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=540674&aid=1704429&group_id=74338 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None Status: Open Resolution: None Priority: 5 Private: No Submitted By: Leandro Lucarella (llucax) Assigned to: Nobody/Anonymous (nobody) Summary: Add how to change MySQL engine to FAQ Initial Comment: Just add the proposed way to change MySQL engine submitted by Markus Gritsch to the mailing list[1] to the FAQ. [1] http://permalink.gmane.org/gmane.comp.python.sqlobject/8050 ---------------------------------------------------------------------- Comment By: Markus Gritsch (markus_gritsch) Date: 2007-04-20 19:19 Message: Logged In: YES user_id=553904 Originator: NO Correction: * The table is not altered just before creation, as stated. The table is created, and the alter statements are executed immediately afterwards. * Multiple statements are specified as a list of strings as the value of the dict. ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=540674&aid=1704429&group_id=74338 |
|
From: SourceForge.net <no...@so...> - 2007-04-20 15:37:02
|
Patches item #1704429, was opened at 2007-04-20 12:37 Message generated for change (Tracker Item Submitted) made by Item Submitter You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=540674&aid=1704429&group_id=74338 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None Status: Open Resolution: None Priority: 5 Private: No Submitted By: Leandro Lucarella (llucax) Assigned to: Nobody/Anonymous (nobody) Summary: Add how to change MySQL engine to FAQ Initial Comment: Just add the proposed way to change MySQL engine submitted by Markus Gritsch to the mailing list[1] to the FAQ. [1] http://permalink.gmane.org/gmane.comp.python.sqlobject/8050 ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=540674&aid=1704429&group_id=74338 |
|
From: <sub...@co...> - 2007-04-20 14:23:38
|
Author: phd
Date: 2007-04-20 08:23:33 -0600 (Fri, 20 Apr 2007)
New Revision: 2578
Modified:
home/phd/SQLObject/paramstyles/sqlobject/dbconnection.py
home/phd/SQLObject/paramstyles/sqlobject/main.py
Log:
Merged patches from the revisions 2575:2577 from the trunk
Modified: home/phd/SQLObject/paramstyles/sqlobject/dbconnection.py
===================================================================
--- home/phd/SQLObject/paramstyles/sqlobject/dbconnection.py 2007-04-20 14:19:06 UTC (rev 2577)
+++ home/phd/SQLObject/paramstyles/sqlobject/dbconnection.py 2007-04-20 14:23:33 UTC (rev 2578)
@@ -559,13 +559,12 @@
self.query(self._SO_createJoinTableSQL(join))
def _SO_createJoinTableSQL(self, join):
- return ('CREATE TABLE %s (\n%s %s,\n%s %s\n) %s' %
+ return ('CREATE TABLE %s (\n%s %s,\n%s %s\n)' %
(join.intermediateTable,
join.joinColumn,
self.joinSQLType(join),
join.otherColumn,
- self.joinSQLType(join),
- self.getDBOptions(join)))
+ self.joinSQLType(join)))
def _SO_dropJoinTable(self, join):
self.query("DROP TABLE %s" % join.intermediateTable)
@@ -611,21 +610,10 @@
def createTableSQL(self, soClass):
constraints = self.createReferenceConstraints(soClass)
extraSQL = self.createSQL(soClass)
- createSql = ('CREATE TABLE %s (\n%s\n) %s' %
- (soClass.sqlmeta.table, self.createColumns(soClass),
- self.getDBOptions(soClass)))
+ createSql = ('CREATE TABLE %s (\n%s\n)' %
+ (soClass.sqlmeta.table, self.createColumns(soClass)))
return createSql, constraints + extraSQL
- def getDBOptions(self, SO_or_join):
- if hasattr(SO_or_join, "sqlmeta"):
- engineSQL = SO_or_join.sqlmeta.engineSQL
- else:
- engineSQL = getattr(SO_or_join, "engineSQL", None)
- if engineSQL:
- return "ENGINE = %s" % engineSQL
- else:
- return ""
-
def createColumns(self, soClass):
columnDefs = [self.createIDColumn(soClass)] \
+ [self.createColumn(soClass, col)
Modified: home/phd/SQLObject/paramstyles/sqlobject/main.py
===================================================================
--- home/phd/SQLObject/paramstyles/sqlobject/main.py 2007-04-20 14:19:06 UTC (rev 2577)
+++ home/phd/SQLObject/paramstyles/sqlobject/main.py 2007-04-20 14:23:33 UTC (rev 2578)
@@ -200,8 +200,6 @@
# Default is false, but we set it to true for the *instance*
# when necessary: (bad clever? maybe)
expired = False
- # Engine SQL; currently used for MySQL engine ("MyISAM", "InnoDB", etc.)
- engineSQL = None
# This is a mapping from column names to SOCol (or subclass)
# instances:
@@ -1462,7 +1460,6 @@
continue
if join.soClass.__name__ > join.otherClass.__name__:
continue
- join.engineSQL = cls.sqlmeta.engineSQL
joins.append(join)
return joins
_getJoinsToCreate = classmethod(_getJoinsToCreate)
|
|
From: SourceForge.net <no...@so...> - 2007-04-20 14:19:26
|
Patches item #1450587, was opened at 2006-03-15 21:20 Message generated for change (Comment added) made by phd You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=540674&aid=1450587&group_id=74338 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None Status: Closed >Resolution: Rejected Priority: 5 Private: No Submitted By: Nobody/Anonymous (nobody) Assigned to: Nobody/Anonymous (nobody) Summary: Add support for MySQL ENGINE specification Initial Comment: MySQL supports several different database engine types, each having its own advantage and drawbacks, with two of the most prevalent being InnoDB (support for transactions and indices) and MyISAM. The engine type can be explicitly specified at the end of a CREATE TABLE. E.g., CREATE TABLE test ( id INT PRIMARY KEY AUTO_INCREMENT, value INT ) ENGINE=InnoDB; The patch adds an engine keyword into the SQLObject that can be used to append the ENGINE specification to every table creation. Usage: SQLObject.engine = "InnoDB" ---------------------------------------------------------------------- >Comment By: Oleg Broytmann (phd) Date: 2007-04-20 18:19 Message: Logged In: YES user_id=4799 Originator: NO Reverted and unapplied in the revisions 2575-2577 (0.9, trunk, docs) - it's too special and could be implemented using createSQL. ---------------------------------------------------------------------- Comment By: Oleg Broytmann (phd) Date: 2007-03-02 18:23 Message: Logged In: YES user_id=4799 Originator: NO Applied in the revision 2369. ---------------------------------------------------------------------- Comment By: Oleg Broytmann (phd) Date: 2006-03-21 13:03 Message: Logged In: YES user_id=4799 Please add documentation and tests. ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=540674&aid=1450587&group_id=74338 |
|
From: <sub...@co...> - 2007-04-20 14:19:15
|
Author: phd Date: 2007-04-20 08:19:06 -0600 (Fri, 20 Apr 2007) New Revision: 2577 Modified: SQLObject/docs/News.txt Log: Removed support for MySQL storage ENGINEs - it's too special and could be implemented using createSQL. Modified: SQLObject/docs/News.txt =================================================================== --- SQLObject/docs/News.txt 2007-04-20 14:18:41 UTC (rev 2576) +++ SQLObject/docs/News.txt 2007-04-20 14:19:06 UTC (rev 2577) @@ -56,8 +56,6 @@ * Support for DEFAULT SQL attribute via defaultSQL keyword argument. -* Support for MySQL storage ENGINEs. - * cls.tableExists() as a shortcut for conn.tableExists(cls.sqlmeta.table). * cls.deleteMany(), cls.deleteBy(). |
|
From: <sub...@co...> - 2007-04-20 14:18:44
|
Author: phd
Date: 2007-04-20 08:18:41 -0600 (Fri, 20 Apr 2007)
New Revision: 2576
Modified:
SQLObject/trunk/sqlobject/dbconnection.py
SQLObject/trunk/sqlobject/main.py
Log:
Removed support for MySQL storage ENGINEs - it's too special and could be
implemented using createSQL.
Modified: SQLObject/trunk/sqlobject/dbconnection.py
===================================================================
--- SQLObject/trunk/sqlobject/dbconnection.py 2007-04-20 14:17:58 UTC (rev 2575)
+++ SQLObject/trunk/sqlobject/dbconnection.py 2007-04-20 14:18:41 UTC (rev 2576)
@@ -548,13 +548,12 @@
self.query(self._SO_createJoinTableSQL(join))
def _SO_createJoinTableSQL(self, join):
- return ('CREATE TABLE %s (\n%s %s,\n%s %s\n) %s' %
+ return ('CREATE TABLE %s (\n%s %s,\n%s %s\n)' %
(join.intermediateTable,
join.joinColumn,
self.joinSQLType(join),
join.otherColumn,
- self.joinSQLType(join),
- self.getDBOptions(join)))
+ self.joinSQLType(join)))
def _SO_dropJoinTable(self, join):
self.query("DROP TABLE %s" % join.intermediateTable)
@@ -600,21 +599,10 @@
def createTableSQL(self, soClass):
constraints = self.createReferenceConstraints(soClass)
extraSQL = self.createSQL(soClass)
- createSql = ('CREATE TABLE %s (\n%s\n) %s' %
- (soClass.sqlmeta.table, self.createColumns(soClass),
- self.getDBOptions(soClass)))
+ createSql = ('CREATE TABLE %s (\n%s\n)' %
+ (soClass.sqlmeta.table, self.createColumns(soClass)))
return createSql, constraints + extraSQL
- def getDBOptions(self, SO_or_join):
- if hasattr(SO_or_join, "sqlmeta"):
- engineSQL = SO_or_join.sqlmeta.engineSQL
- else:
- engineSQL = getattr(SO_or_join, "engineSQL", None)
- if engineSQL:
- return "ENGINE = %s" % engineSQL
- else:
- return ""
-
def createColumns(self, soClass):
columnDefs = [self.createIDColumn(soClass)] \
+ [self.createColumn(soClass, col)
Modified: SQLObject/trunk/sqlobject/main.py
===================================================================
--- SQLObject/trunk/sqlobject/main.py 2007-04-20 14:17:58 UTC (rev 2575)
+++ SQLObject/trunk/sqlobject/main.py 2007-04-20 14:18:41 UTC (rev 2576)
@@ -200,8 +200,6 @@
# Default is false, but we set it to true for the *instance*
# when necessary: (bad clever? maybe)
expired = False
- # Engine SQL; currently used for MySQL engine ("MyISAM", "InnoDB", etc.)
- engineSQL = None
# This is a mapping from column names to SOCol (or subclass)
# instances:
@@ -1462,7 +1460,6 @@
continue
if join.soClass.__name__ > join.otherClass.__name__:
continue
- join.engineSQL = cls.sqlmeta.engineSQL
joins.append(join)
return joins
_getJoinsToCreate = classmethod(_getJoinsToCreate)
|
|
From: <sub...@co...> - 2007-04-20 14:18:02
|
Author: phd
Date: 2007-04-20 08:17:58 -0600 (Fri, 20 Apr 2007)
New Revision: 2575
Modified:
SQLObject/branches/0.9/docs/News.txt
SQLObject/branches/0.9/sqlobject/dbconnection.py
SQLObject/branches/0.9/sqlobject/main.py
Log:
Removed support for MySQL storage ENGINEs - it's too special and could be
implemented using createSQL.
Modified: SQLObject/branches/0.9/docs/News.txt
===================================================================
--- SQLObject/branches/0.9/docs/News.txt 2007-04-20 13:58:02 UTC (rev 2574)
+++ SQLObject/branches/0.9/docs/News.txt 2007-04-20 14:17:58 UTC (rev 2575)
@@ -53,8 +53,6 @@
* Support for DEFAULT SQL attribute via defaultSQL keyword argument.
-* Support for MySQL storage ENGINEs.
-
* cls.tableExists() as a shortcut for conn.tableExists(cls.sqlmeta.table).
* cls.deleteMany(), cls.deleteBy().
Modified: SQLObject/branches/0.9/sqlobject/dbconnection.py
===================================================================
--- SQLObject/branches/0.9/sqlobject/dbconnection.py 2007-04-20 13:58:02 UTC (rev 2574)
+++ SQLObject/branches/0.9/sqlobject/dbconnection.py 2007-04-20 14:17:58 UTC (rev 2575)
@@ -548,13 +548,12 @@
self.query(self._SO_createJoinTableSQL(join))
def _SO_createJoinTableSQL(self, join):
- return ('CREATE TABLE %s (\n%s %s,\n%s %s\n) %s' %
+ return ('CREATE TABLE %s (\n%s %s,\n%s %s\n)' %
(join.intermediateTable,
join.joinColumn,
self.joinSQLType(join),
join.otherColumn,
- self.joinSQLType(join),
- self.getDBOptions(join)))
+ self.joinSQLType(join)))
def _SO_dropJoinTable(self, join):
self.query("DROP TABLE %s" % join.intermediateTable)
@@ -600,21 +599,10 @@
def createTableSQL(self, soClass):
constraints = self.createReferenceConstraints(soClass)
extraSQL = self.createSQL(soClass)
- createSql = ('CREATE TABLE %s (\n%s\n) %s' %
- (soClass.sqlmeta.table, self.createColumns(soClass),
- self.getDBOptions(soClass)))
+ createSql = ('CREATE TABLE %s (\n%s\n)' %
+ (soClass.sqlmeta.table, self.createColumns(soClass)))
return createSql, constraints + extraSQL
- def getDBOptions(self, SO_or_join):
- if hasattr(SO_or_join, "sqlmeta"):
- engineSQL = SO_or_join.sqlmeta.engineSQL
- else:
- engineSQL = getattr(SO_or_join, "engineSQL", None)
- if engineSQL:
- return "ENGINE = %s" % engineSQL
- else:
- return ""
-
def createColumns(self, soClass):
columnDefs = [self.createIDColumn(soClass)] \
+ [self.createColumn(soClass, col)
Modified: SQLObject/branches/0.9/sqlobject/main.py
===================================================================
--- SQLObject/branches/0.9/sqlobject/main.py 2007-04-20 13:58:02 UTC (rev 2574)
+++ SQLObject/branches/0.9/sqlobject/main.py 2007-04-20 14:17:58 UTC (rev 2575)
@@ -200,8 +200,6 @@
# Default is false, but we set it to true for the *instance*
# when necessary: (bad clever? maybe)
expired = False
- # Engine SQL; currently used for MySQL engine ("MyISAM", "InnoDB", etc.)
- engineSQL = None
# This is a mapping from column names to SOCol (or subclass)
# instances:
@@ -1462,7 +1460,6 @@
continue
if join.soClass.__name__ > join.otherClass.__name__:
continue
- join.engineSQL = cls.sqlmeta.engineSQL
joins.append(join)
return joins
_getJoinsToCreate = classmethod(_getJoinsToCreate)
|
|
From: <sub...@co...> - 2007-04-20 13:58:07
|
Author: phd
Date: 2007-04-20 07:58:02 -0600 (Fri, 20 Apr 2007)
New Revision: 2574
Modified:
home/phd/SQLObject/paramstyles/sqlobject/dbconnection.py
home/phd/SQLObject/paramstyles/sqlobject/tests/test_joins_conditional.py
Log:
Merged patches from the revisions 2570:2572 from the trunk
Modified: home/phd/SQLObject/paramstyles/sqlobject/dbconnection.py
===================================================================
--- home/phd/SQLObject/paramstyles/sqlobject/dbconnection.py 2007-04-20 13:47:52 UTC (rev 2573)
+++ home/phd/SQLObject/paramstyles/sqlobject/dbconnection.py 2007-04-20 13:58:02 UTC (rev 2574)
@@ -487,17 +487,21 @@
if type(join) is str:
join_str = ' ' + join
elif isinstance(join, sqlbuilder.SQLJoin):
- if tables and join.table1:
+ if join.table1:
join_str = ", "
else:
join_str = ' '
join_str += self.sqlrepr(join)
else:
- if tables and join[0].table1:
- join_str = ", "
- else:
- join_str = ' '
- join_str += " ".join([self.sqlrepr(j) for j in join])
+ join_str = ""
+ for j in join:
+ if j.table1:
+ sep = ", "
+ else:
+ sep = ' '
+ join_str += sep + self.sqlrepr(j)
+ if not tables and join_str.startswith(','):
+ join_str = join_str[1:].strip()
return join_str
def _addWhereClause(self, select, startSelect, limit=1, order=1):
Modified: home/phd/SQLObject/paramstyles/sqlobject/tests/test_joins_conditional.py
===================================================================
--- home/phd/SQLObject/paramstyles/sqlobject/tests/test_joins_conditional.py 2007-04-20 13:47:52 UTC (rev 2573)
+++ home/phd/SQLObject/paramstyles/sqlobject/tests/test_joins_conditional.py 2007-04-20 13:58:02 UTC (rev 2574)
@@ -35,7 +35,7 @@
on_condition=(TestJoin1.q.col1 == TestJoin2.q.col2))
)
assert str(select) == \
- "SELECT test_join1.id, test_join1.col1 FROM test_join1 LEFT JOIN test_join2 ON ((test_join1.col1) = (test_join2.col2)) WHERE 1 = 1"
+ "SELECT test_join1.id, test_join1.col1 FROM test_join1 LEFT JOIN test_join2 ON ((test_join1.col1) = (test_join2.col2)) WHERE 1 = 1"
def test_3perform_join():
setup()
@@ -70,6 +70,12 @@
assert str(select) == \
"SELECT test_join1.id, test_join1.col1 FROM test_join1 LEFT JOIN test_join2 LEFT JOIN test_join3 WHERE 1 = 1"
+ select = TestJoin1.select(
+ join=(LEFTJOIN(TestJoin1, TestJoin2), LEFTJOIN(TestJoin1, TestJoin3))
+ )
+ assert str(select) == \
+ "SELECT test_join1.id, test_join1.col1 FROM test_join1 LEFT JOIN test_join2, test_join1 LEFT JOIN test_join3 WHERE 1 = 1"
+
def test_6join_using():
setup()
setupClass(TestJoin3)
|
|
From: <sub...@co...> - 2007-04-20 13:47:55
|
Author: luke
Date: 2007-04-20 07:47:52 -0600 (Fri, 20 Apr 2007)
New Revision: 2573
Modified:
SQLObject/branches/cache-deps-on-views/sqlobject/materialized/dependency.py
SQLObject/branches/cache-deps-on-views/sqlobject/materialized/materialized.py
SQLObject/branches/cache-deps-on-views/sqlobject/materialized/tests/test_materialized.py
Log:
Minor checkpoint
Modified: SQLObject/branches/cache-deps-on-views/sqlobject/materialized/dependency.py
===================================================================
--- SQLObject/branches/cache-deps-on-views/sqlobject/materialized/dependency.py 2007-04-20 13:43:34 UTC (rev 2572)
+++ SQLObject/branches/cache-deps-on-views/sqlobject/materialized/dependency.py 2007-04-20 13:47:52 UTC (rev 2573)
@@ -148,7 +148,6 @@
if _toProcess is None:
_toProcess = self.instancesToProcess(inst, attrs)
for (cls, attr), insts in _toProcess.iteritems():
- print insts
for inst in insts:
inst._SO_updateCacheObject([attr])
self.process(inst, [attr])
@@ -156,7 +155,9 @@
dep = SQLDependencyManager()
+dependentOn = dep.dependentOn
+
def _processDepsOnChange(inst, kwargs):
dep.process(inst, kwargs.keys())
@@ -168,5 +169,6 @@
toProcess = dep.instancesToProcess(inst, attrs)
def f(inst, toProcess=toProcess):
dep.process(inst, attrs, _toProcess=toProcess)
- post_funcs.append(f)
+ if toProcess:
+ post_funcs.append(f)
listen(_processDepsOnDelete, SQLObject, RowDestroySignal)
\ No newline at end of file
Modified: SQLObject/branches/cache-deps-on-views/sqlobject/materialized/materialized.py
===================================================================
--- SQLObject/branches/cache-deps-on-views/sqlobject/materialized/materialized.py 2007-04-20 13:43:34 UTC (rev 2572)
+++ SQLObject/branches/cache-deps-on-views/sqlobject/materialized/materialized.py 2007-04-20 13:47:52 UTC (rev 2573)
@@ -1,7 +1,8 @@
from sqlobject import SQLObject, SQLObjectNotFound, sqlmeta as _sqlmeta
from sqlobject import events, col
from sqlobject.main import makeProperties
-from dependency import *
+from dependency import dep
+from sqlobject.events import *
class materialized_sqlmeta(_sqlmeta):
cachedIn = None
@@ -16,6 +17,7 @@
cachedIn = cls.table + '_cache'
class cache_sqlmeta:
table = cachedIn
+ idType = cls.idType
cls.cacheClass = type(cls.soClass.__name__+'Cache', (SQLObject,), {'sqlmeta': cache_sqlmeta})
@@ -28,13 +30,11 @@
def _init(self, id, connection=None, **kw):
super(MaterializedSQLObject, self)._init(id, connection=connection, **kw)
try:
- self._SO_cacheObject = self.sqlmeta.cacheClass.get(self.id, connection=connection)
+ self._SO_cacheObject = self.sqlmeta.cacheClass.get(self.id, connection=self._connection)
except SQLObjectNotFound:
- self._SO_cacheObject = None
+ print self.sqlmeta.cacheClass._connection, connection
+ self._SO_cacheObject = self.sqlmeta.cacheClass(id=self.id, connection=self._connection)
- def _create(self, id, **kw):
- super(MaterializedSQLObject, self)._create(id, **kw)
- self._SO_cacheObject = self.sqlmeta.cacheClass(id=self.id)
def _SO_updateCacheObject(self, attrs):
for attr in attrs:
Modified: SQLObject/branches/cache-deps-on-views/sqlobject/materialized/tests/test_materialized.py
===================================================================
--- SQLObject/branches/cache-deps-on-views/sqlobject/materialized/tests/test_materialized.py 2007-04-20 13:43:34 UTC (rev 2572)
+++ SQLObject/branches/cache-deps-on-views/sqlobject/materialized/tests/test_materialized.py 2007-04-20 13:47:52 UTC (rev 2573)
@@ -2,7 +2,7 @@
from sqlobject import *
from sqlobject.tests.dbtest import *
from sqlobject.materialized import *
-from sqlobject.sqlbuilder import ImportProxy
+from sqlobject.sqlbuilder import ImportProxy, AND
MO = ImportProxy('MaterializedOne')
MT = ImportProxy('MaterializedTwo')
@@ -13,16 +13,31 @@
twos = SQLMultipleJoin('MaterializedTwo', joinColumn='oneID')
@cachedAs(IntCol)
- @dep.dependentOn('MaterializedOne', 'twos')
+ @dependentOn('MaterializedOne', 'twos')
def _get_twoCount(self):
print "getting twoCount", self.twos.count()
return self.twos.count()
@cachedAs(IntCol)
- @dep.dependentOn('MaterializedTwo', 'length', MO.q.twos)
+ @dependentOn('MaterializedTwo', 'length', MO.q.twos)
def _get_detailSize(self):
return self.twos.sum('length')
+ @cachedAs(IntCol)
+ @dependentOn('MaterializedTwo', 'id', AND(MO.q.twos, MT.q.length<=4))
+ def _get_smallTwoCount(self):
+ return self.twos.filter(MT.q.length<=4).count()
+
+ @dependentOn('MaterializedTwo', 'id', AND(MO.q.twos, MT.q.length<=4))
+ def _get_smallTwos(self):
+ print "getting small twos"
+ return self.twos.filter(MT.q.length<=4)
+
+ @cachedAs(IntCol)
+ @dependentOn('MaterializedOne', 'smallTwos')
+ def _get_smallTwoCount2(self):
+ return self.smallTwos.count()
+
class MaterializedTwo(MaterializedSQLObject):
class sqlmeta:
cachedIn = 'cache_materialized_two'
@@ -32,19 +47,19 @@
one = ForeignKey('MaterializedOne')
@cachedAs(StringCol)
- @dep.dependentOn('MaterializedOne', 'name', MT.q.one)
+ @dependentOn('MaterializedOne', 'name', MT.q.one)
def _get_name(self):
return self.one.name
@cachedAs(StringCol)
- @dep.dependentOn('MaterializedTwo', 'detail')
- @dep.dependentOn('MaterializedOne', 'name', MT.q.one)
+ @dependentOn('MaterializedTwo', 'detail')
+ @dependentOn('MaterializedOne', 'name', MT.q.one)
def _get_name2(self):
return self.one.name + self.detail
@cachedAs(StringCol)
- @dep.dependentOn('MaterializedTwo', 'detail')
- @dep.dependentOn('MaterializedTwo', 'name')
+ @dependentOn('MaterializedTwo', 'detail')
+ @dependentOn('MaterializedTwo', 'name')
def _get_name3(self):
''' dep on dep '''
return self.name + self.detail
@@ -74,8 +89,8 @@
def testSetupDepsForJoin():
deps = dep.get('MaterializedTwo', 'id')
- assert set((x,y) for x,y,z in deps) == set([('MaterializedOne', 'twos')])
- assert [z for x,y,z in deps][0] is not None
+ assert ('MaterializedOne', 'twos') in set((x,y) for x,y,z in deps)
+ assert None not in [z for x,y,z in deps]
def testProcessInstances():
@@ -113,6 +128,12 @@
assert obj._SO_cacheObject.name == 'G'
assert obj.name == 'G'
+def testChainedModificationSettingCacheObject():
+ obj = twos[2]
+ obj.one.name = 'G'
+ assert obj._SO_cacheObject.name3 == 'G'+obj.detail
+ assert obj.name3 == 'G'+obj.detail
+
def testJoinUpdateSettingCacheObject():
obj = ones[0]
prev = obj.detailSize
@@ -137,6 +158,21 @@
assert obj._SO_cacheObject.detailSize == prevS + new_two.length
assert obj._SO_cacheObject.twoCount == prevC + 1
new_two.destroySelf()
- assert obj.twos.count() == prevC
assert obj._SO_cacheObject.detailSize == prevS
- assert obj._SO_cacheObject.twoCount == prevC
\ No newline at end of file
+ assert obj._SO_cacheObject.twoCount == prevC
+
+def testRestrictedDependencyRoute():
+ assert twos[1].length <= 4
+ insts = dep.instancesToProcess(twos[1], ['id'])
+ assert insts[('MaterializedOne', 'smallTwoCount')] == [ones[0]]
+ assert twos[3].length > 4
+ insts = dep.instancesToProcess(twos[3], ['id'])
+ assert insts[('MaterializedOne', 'smallTwoCount')] == []
+
+def testRestrictedDependencyRoute2():
+ assert twos[1].length <= 4
+ insts = dep.instancesToProcess(twos[1], ['id'])
+ assert insts[('MaterializedOne', 'smallTwos')] == [ones[0]]
+ assert twos[3].length > 4
+ insts = dep.instancesToProcess(twos[3], ['id'])
+ assert insts[('MaterializedOne', 'smallTwos')] == []
\ No newline at end of file
|
|
From: <sub...@co...> - 2007-04-20 13:43:38
|
Author: phd Date: 2007-04-20 07:43:34 -0600 (Fri, 20 Apr 2007) New Revision: 2572 Modified: SQLObject/docs/News.txt Log: Fixed a bug with absent comma in JOINs. Modified: SQLObject/docs/News.txt =================================================================== --- SQLObject/docs/News.txt 2007-04-20 13:43:10 UTC (rev 2571) +++ SQLObject/docs/News.txt 2007-04-20 13:43:34 UTC (rev 2572) @@ -214,6 +214,8 @@ * Fixed a longstanding bug with .select() ignoring 'limit' parameter. +* Fixed a bug with absent comma in JOINs. + SQLObject 0.7.5 =============== |
|
From: <sub...@co...> - 2007-04-20 13:43:13
|
Author: phd
Date: 2007-04-20 07:43:10 -0600 (Fri, 20 Apr 2007)
New Revision: 2571
Modified:
SQLObject/trunk/sqlobject/dbconnection.py
SQLObject/trunk/sqlobject/tests/test_joins_conditional.py
Log:
Fixed a bug with absent comma in JOINs.
Modified: SQLObject/trunk/sqlobject/dbconnection.py
===================================================================
--- SQLObject/trunk/sqlobject/dbconnection.py 2007-04-20 13:42:42 UTC (rev 2570)
+++ SQLObject/trunk/sqlobject/dbconnection.py 2007-04-20 13:43:10 UTC (rev 2571)
@@ -476,7 +476,7 @@
if type(join) is str:
join_str = ' ' + join
elif isinstance(join, sqlbuilder.SQLJoin):
- if tables and join.table1:
+ if join.table1:
join_str = ", "
else:
join_str = ' '
@@ -484,11 +484,13 @@
else:
join_str = ""
for j in join:
- if tables and j.table1:
+ if j.table1:
sep = ", "
else:
sep = ' '
join_str += sep + self.sqlrepr(j)
+ if not tables and join_str.startswith(','):
+ join_str = join_str[1:].strip()
return join_str
def _addWhereClause(self, select, startSelect, limit=1, order=1):
Modified: SQLObject/trunk/sqlobject/tests/test_joins_conditional.py
===================================================================
--- SQLObject/trunk/sqlobject/tests/test_joins_conditional.py 2007-04-20 13:42:42 UTC (rev 2570)
+++ SQLObject/trunk/sqlobject/tests/test_joins_conditional.py 2007-04-20 13:43:10 UTC (rev 2571)
@@ -41,7 +41,7 @@
on_condition=(TestJoin1.q.col1 == TestJoin2.q.col2))
)
assert str(select) == \
- "SELECT test_join1.id, test_join1.col1 FROM test_join1 LEFT JOIN test_join2 ON ((test_join1.col1) = (test_join2.col2)) WHERE 1 = 1"
+ "SELECT test_join1.id, test_join1.col1 FROM test_join1 LEFT JOIN test_join2 ON ((test_join1.col1) = (test_join2.col2)) WHERE 1 = 1"
def test_3perform_join():
setup()
@@ -76,6 +76,12 @@
assert str(select) == \
"SELECT test_join1.id, test_join1.col1 FROM test_join1 LEFT JOIN test_join2 LEFT JOIN test_join3 WHERE 1 = 1"
+ select = TestJoin1.select(
+ join=(LEFTJOIN(TestJoin1, TestJoin2), LEFTJOIN(TestJoin1, TestJoin3))
+ )
+ assert str(select) == \
+ "SELECT test_join1.id, test_join1.col1 FROM test_join1 LEFT JOIN test_join2, test_join1 LEFT JOIN test_join3 WHERE 1 = 1"
+
def test_6join_using():
setup()
setupClass(TestJoin3)
|
|
From: <sub...@co...> - 2007-04-20 13:42:46
|
Author: phd
Date: 2007-04-20 07:42:42 -0600 (Fri, 20 Apr 2007)
New Revision: 2570
Modified:
SQLObject/branches/0.9/docs/News.txt
SQLObject/branches/0.9/sqlobject/dbconnection.py
SQLObject/branches/0.9/sqlobject/tests/test_joins_conditional.py
Log:
Fixed a bug with absent comma in JOINs.
Modified: SQLObject/branches/0.9/docs/News.txt
===================================================================
--- SQLObject/branches/0.9/docs/News.txt 2007-04-20 13:41:03 UTC (rev 2569)
+++ SQLObject/branches/0.9/docs/News.txt 2007-04-20 13:42:42 UTC (rev 2570)
@@ -211,6 +211,8 @@
* Fixed a longstanding bug with .select() ignoring 'limit' parameter.
+* Fixed a bug with absent comma in JOINs.
+
SQLObject 0.7.5
===============
Modified: SQLObject/branches/0.9/sqlobject/dbconnection.py
===================================================================
--- SQLObject/branches/0.9/sqlobject/dbconnection.py 2007-04-20 13:41:03 UTC (rev 2569)
+++ SQLObject/branches/0.9/sqlobject/dbconnection.py 2007-04-20 13:42:42 UTC (rev 2570)
@@ -476,7 +476,7 @@
if type(join) is str:
join_str = ' ' + join
elif isinstance(join, sqlbuilder.SQLJoin):
- if tables and join.table1:
+ if join.table1:
join_str = ", "
else:
join_str = ' '
@@ -484,11 +484,13 @@
else:
join_str = ""
for j in join:
- if tables and j.table1:
+ if j.table1:
sep = ", "
else:
sep = ' '
join_str += sep + self.sqlrepr(j)
+ if not tables and join_str.startswith(','):
+ join_str = join_str[1:].strip()
return join_str
def _addWhereClause(self, select, startSelect, limit=1, order=1):
Modified: SQLObject/branches/0.9/sqlobject/tests/test_joins_conditional.py
===================================================================
--- SQLObject/branches/0.9/sqlobject/tests/test_joins_conditional.py 2007-04-20 13:41:03 UTC (rev 2569)
+++ SQLObject/branches/0.9/sqlobject/tests/test_joins_conditional.py 2007-04-20 13:42:42 UTC (rev 2570)
@@ -41,7 +41,7 @@
on_condition=(TestJoin1.q.col1 == TestJoin2.q.col2))
)
assert str(select) == \
- "SELECT test_join1.id, test_join1.col1 FROM test_join1 LEFT JOIN test_join2 ON ((test_join1.col1) = (test_join2.col2)) WHERE 1 = 1"
+ "SELECT test_join1.id, test_join1.col1 FROM test_join1 LEFT JOIN test_join2 ON ((test_join1.col1) = (test_join2.col2)) WHERE 1 = 1"
def test_3perform_join():
setup()
@@ -76,6 +76,12 @@
assert str(select) == \
"SELECT test_join1.id, test_join1.col1 FROM test_join1 LEFT JOIN test_join2 LEFT JOIN test_join3 WHERE 1 = 1"
+ select = TestJoin1.select(
+ join=(LEFTJOIN(TestJoin1, TestJoin2), LEFTJOIN(TestJoin1, TestJoin3))
+ )
+ assert str(select) == \
+ "SELECT test_join1.id, test_join1.col1 FROM test_join1 LEFT JOIN test_join2, test_join1 LEFT JOIN test_join3 WHERE 1 = 1"
+
def test_6join_using():
setup()
setupClass(TestJoin3)
|
|
From: <sub...@co...> - 2007-04-20 13:41:06
|
Author: phd
Date: 2007-04-20 07:41:03 -0600 (Fri, 20 Apr 2007)
New Revision: 2569
Modified:
SQLObject/branches/0.8/docs/News.txt
SQLObject/branches/0.8/sqlobject/dbconnection.py
SQLObject/branches/0.8/sqlobject/tests/test_joins_conditional.py
Log:
Fixed a bug with absent comma in JOINs.
Modified: SQLObject/branches/0.8/docs/News.txt
===================================================================
--- SQLObject/branches/0.8/docs/News.txt 2007-04-20 13:38:55 UTC (rev 2568)
+++ SQLObject/branches/0.8/docs/News.txt 2007-04-20 13:41:03 UTC (rev 2569)
@@ -154,6 +154,8 @@
* Fixed a longstanding bug with .select() ignoring 'limit' parameter.
+* Fixed a bug with absent comma in JOINs.
+
SQLObject 0.7.5
===============
Modified: SQLObject/branches/0.8/sqlobject/dbconnection.py
===================================================================
--- SQLObject/branches/0.8/sqlobject/dbconnection.py 2007-04-20 13:38:55 UTC (rev 2568)
+++ SQLObject/branches/0.8/sqlobject/dbconnection.py 2007-04-20 13:41:03 UTC (rev 2569)
@@ -450,7 +450,7 @@
if type(join) is str:
join_str = ' ' + join
elif isinstance(join, sqlbuilder.SQLJoin):
- if tables and join.table1:
+ if join.table1:
join_str = ", "
else:
join_str = ' '
@@ -458,11 +458,13 @@
else:
join_str = ""
for j in join:
- if tables and j.table1:
+ if j.table1:
sep = ", "
else:
sep = ' '
join_str += sep + self.sqlrepr(j)
+ if not tables and join_str.startswith(','):
+ join_str = join_str[1:].strip()
return join_str
def _addWhereClause(self, select, startSelect, limit=1, order=1):
Modified: SQLObject/branches/0.8/sqlobject/tests/test_joins_conditional.py
===================================================================
--- SQLObject/branches/0.8/sqlobject/tests/test_joins_conditional.py 2007-04-20 13:38:55 UTC (rev 2568)
+++ SQLObject/branches/0.8/sqlobject/tests/test_joins_conditional.py 2007-04-20 13:41:03 UTC (rev 2569)
@@ -41,7 +41,7 @@
on_condition=(TestJoin1.q.col1 == TestJoin2.q.col2))
)
assert str(select) == \
- "SELECT test_join1.id, test_join1.col1 FROM test_join1 LEFT JOIN test_join2 ON ((test_join1.col1) = (test_join2.col2)) WHERE 1 = 1"
+ "SELECT test_join1.id, test_join1.col1 FROM test_join1 LEFT JOIN test_join2 ON ((test_join1.col1) = (test_join2.col2)) WHERE 1 = 1"
def test_3perform_join():
setup()
@@ -76,6 +76,12 @@
assert str(select) == \
"SELECT test_join1.id, test_join1.col1 FROM test_join1 LEFT JOIN test_join2 LEFT JOIN test_join3 WHERE 1 = 1"
+ select = TestJoin1.select(
+ join=(LEFTJOIN(TestJoin1, TestJoin2), LEFTJOIN(TestJoin1, TestJoin3))
+ )
+ assert str(select) == \
+ "SELECT test_join1.id, test_join1.col1 FROM test_join1 LEFT JOIN test_join2, test_join1 LEFT JOIN test_join3 WHERE 1 = 1"
+
def test_6join_using():
setup()
setupClass(TestJoin3)
|
|
From: <sub...@co...> - 2007-04-20 13:39:01
|
Author: phd
Date: 2007-04-20 07:38:55 -0600 (Fri, 20 Apr 2007)
New Revision: 2568
Modified:
SQLObject/branches/0.7/docs/News.txt
SQLObject/branches/0.7/sqlobject/dbconnection.py
SQLObject/branches/0.7/sqlobject/tests/test_joins_conditional.py
Log:
Fixed a bug with absent comma in JOINs.
Modified: SQLObject/branches/0.7/docs/News.txt
===================================================================
--- SQLObject/branches/0.7/docs/News.txt 2007-04-18 20:55:52 UTC (rev 2567)
+++ SQLObject/branches/0.7/docs/News.txt 2007-04-20 13:38:55 UTC (rev 2568)
@@ -17,6 +17,8 @@
* Fixed a longstanding bug with .select() ignoring 'limit' parameter.
+* Fixed a bug with absent comma in JOINs.
+
SQLObject 0.7.5
===============
Modified: SQLObject/branches/0.7/sqlobject/dbconnection.py
===================================================================
--- SQLObject/branches/0.7/sqlobject/dbconnection.py 2007-04-18 20:55:52 UTC (rev 2567)
+++ SQLObject/branches/0.7/sqlobject/dbconnection.py 2007-04-20 13:38:55 UTC (rev 2568)
@@ -441,7 +441,7 @@
if type(join) is str:
join_str = ' ' + join
elif isinstance(join, sqlbuilder.SQLJoin):
- if tables and join.table1:
+ if join.table1:
join_str = ", "
else:
join_str = ' '
@@ -449,11 +449,13 @@
else:
join_str = ""
for j in join:
- if tables and j.table1:
+ if j.table1:
sep = ", "
else:
sep = ' '
join_str += sep + self.sqlrepr(j)
+ if not tables and join_str.startswith(','):
+ join_str = join_str[1:].strip()
return join_str
def _addWhereClause(self, select, startSelect, limit=1, order=1):
Modified: SQLObject/branches/0.7/sqlobject/tests/test_joins_conditional.py
===================================================================
--- SQLObject/branches/0.7/sqlobject/tests/test_joins_conditional.py 2007-04-18 20:55:52 UTC (rev 2567)
+++ SQLObject/branches/0.7/sqlobject/tests/test_joins_conditional.py 2007-04-20 13:38:55 UTC (rev 2568)
@@ -41,7 +41,7 @@
on_condition=(TestJoin1.q.col1 == TestJoin2.q.col2))
)
assert str(select) == \
- "SELECT test_join1.id, test_join1.col1 FROM test_join1 LEFT JOIN test_join2 ON ((test_join1.col1) = (test_join2.col2)) WHERE 1 = 1"
+ "SELECT test_join1.id, test_join1.col1 FROM test_join1 LEFT JOIN test_join2 ON ((test_join1.col1) = (test_join2.col2)) WHERE 1 = 1"
def test_3perform_join():
setup()
@@ -76,6 +76,12 @@
assert str(select) == \
"SELECT test_join1.id, test_join1.col1 FROM test_join1 LEFT JOIN test_join2 LEFT JOIN test_join3 WHERE 1 = 1"
+ select = TestJoin1.select(
+ join=(LEFTJOIN(TestJoin1, TestJoin2), LEFTJOIN(TestJoin1, TestJoin3))
+ )
+ assert str(select) == \
+ "SELECT test_join1.id, test_join1.col1 FROM test_join1 LEFT JOIN test_join2, test_join1 LEFT JOIN test_join3 WHERE 1 = 1"
+
def test_6join_using():
setup()
setupClass(TestJoin3)
|
|
From: <sub...@co...> - 2007-04-18 17:49:05
|
Author: luke
Date: 2007-04-18 11:49:00 -0600 (Wed, 18 Apr 2007)
New Revision: 2565
Modified:
SQLObject/branches/cache-deps-on-views/sqlobject/materialized/dependency.py
SQLObject/branches/cache-deps-on-views/sqlobject/materialized/materialized.py
SQLObject/branches/cache-deps-on-views/sqlobject/materialized/tests/test_materialized.py
Log:
cacheObject updates on create/set/delete
Modified: SQLObject/branches/cache-deps-on-views/sqlobject/materialized/dependency.py
===================================================================
--- SQLObject/branches/cache-deps-on-views/sqlobject/materialized/dependency.py 2007-04-18 17:47:46 UTC (rev 2564)
+++ SQLObject/branches/cache-deps-on-views/sqlobject/materialized/dependency.py 2007-04-18 17:49:00 UTC (rev 2565)
@@ -3,6 +3,7 @@
from sqlobject.events import *
from sqlobject.include.pydispatch import dispatcher
from sqlobject import classregistry
+from sqlobject import SQLObject
from operator import isCallable
import inspect
@@ -104,7 +105,6 @@
def __init__(self, target, source, *extras):
if isinstance(source[0], sqlbuilder.SQLExpression):
source = (str(source[0].tableName), str(source[0].fieldName)) + source[1:]
- print source
if len(source) == 3:
other = source[2]
try:
@@ -115,6 +115,8 @@
source = source[:2]
else:
extras = (None,) + extras
+ if target[1][:5] == '_get_':
+ target = (target[0], target[1][5:])
self.target = self.DependencyItemClass(target, *extras)
self.source = self.DependencyItemClass(source, *extras)
@@ -130,44 +132,41 @@
targetClass = classregistry.findClass(targetClassName, class_registry=inst.sqlmeta.registry)
- print "Route", route
if inspect.isfunction(route):
argspec = inspect.getargspec(route)
- print "argspec", argspec
if len(argspec[0]) == len(argspec[3]) and not argspec[1] and not argspec[2]:
- print "exec", route()
route = route()
- print "RouteX", route
if route is None:
route = lambda i,c: [i]
elif isinstance(route, sqlbuilder.SQLExpression):
- route = lambda i,c,r=route: c.select(sqlbuilder.AND(r, i))
+ route = lambda i,c,r=route: c.select(sqlbuilder.AND(r, i), connection=i._connection)
ret.setdefault((targetClassName, targetAttr),[]).extend(route(inst, targetClass))
return ret
- def process(self, inst, attrs):
- for (cls, attr), insts in self.instancesToProcess(inst, attrs).iteritems():
+ def process(self, inst, attrs, _toProcess=None):
+ if _toProcess is None:
+ _toProcess = self.instancesToProcess(inst, attrs)
+ for (cls, attr), insts in _toProcess.iteritems():
+ print insts
for inst in insts:
- inst._SO_resetCache(attr)
+ inst._SO_updateCacheObject([attr])
+ self.process(inst, [attr])
-
- def FK(self, name):
- '''route for foreign key'''
- def f(inst, cls):
- return cls.select(cls.q.id==getattr(inst, name+'ID'))
- return f
-
- def J(self, name):
- '''route for join'''
- def f(inst, cls):
- return cls.select(getattr(cls.q,name)==inst.id)
- return f
-
- def S(self, *args):
- '''route for self'''
- if not len(args):
- return self.S
- return args[0]
dep = SQLDependencyManager()
+
+
+def _processDepsOnChange(inst, kwargs):
+ dep.process(inst, kwargs.keys())
+
+listen(_processDepsOnChange, SQLObject, RowUpdatedSignal)
+listen(_processDepsOnChange, SQLObject, RowCreatedSignal)
+
+def _processDepsOnDelete(inst, post_funcs):
+ attrs = ['id'] + inst.sqlmeta.columns.keys()
+ toProcess = dep.instancesToProcess(inst, attrs)
+ def f(inst, toProcess=toProcess):
+ dep.process(inst, attrs, _toProcess=toProcess)
+ post_funcs.append(f)
+listen(_processDepsOnDelete, SQLObject, RowDestroySignal)
\ No newline at end of file
Modified: SQLObject/branches/cache-deps-on-views/sqlobject/materialized/materialized.py
===================================================================
--- SQLObject/branches/cache-deps-on-views/sqlobject/materialized/materialized.py 2007-04-18 17:47:46 UTC (rev 2564)
+++ SQLObject/branches/cache-deps-on-views/sqlobject/materialized/materialized.py 2007-04-18 17:49:00 UTC (rev 2565)
@@ -1,22 +1,51 @@
-from sqlobject import SQLObject, sqlmeta as _sqlmeta
-from sqlobject import events
+from sqlobject import SQLObject, SQLObjectNotFound, sqlmeta as _sqlmeta
+from sqlobject import events, col
+from sqlobject.main import makeProperties
from dependency import *
+class materialized_sqlmeta(_sqlmeta):
+ cachedIn = None
+
+ def setClass(cls, soClass):
+ super(materialized_sqlmeta, cls).setClass(soClass)
+
+ cls.cachedAttributes = {}
+
+ cachedIn = cls.cachedIn
+ if cachedIn is None:
+ cachedIn = cls.table + '_cache'
+ class cache_sqlmeta:
+ table = cachedIn
+
+ cls.cacheClass = type(cls.soClass.__name__+'Cache', (SQLObject,), {'sqlmeta': cache_sqlmeta})
+
+ setClass = classmethod(setClass)
+
class MaterializedSQLObject(SQLObject):
- class sqlmeta(_sqlmeta):
- cachedIn = None
+ sqlmeta = materialized_sqlmeta
- def setClass(cls, soClass):
- super(cls, sqlmeta).setClass(soClass)
-
- if cls.cachedIn is None:
- cls.cachedIn = cls.table + '_cache'
- cls.cacheClass = type(cls.soClass.__name__+'Cache', (SQLObject,))
-
- setClass = classmethod(setClass)
+ def _init(self, id, connection=None, **kw):
+ super(MaterializedSQLObject, self)._init(id, connection=connection, **kw)
+ try:
+ self._SO_cacheObject = self.sqlmeta.cacheClass.get(self.id, connection=connection)
+ except SQLObjectNotFound:
+ self._SO_cacheObject = None
+
+ def _create(self, id, **kw):
+ super(MaterializedSQLObject, self)._create(id, **kw)
+ self._SO_cacheObject = self.sqlmeta.cacheClass(id=self.id)
+ def _SO_updateCacheObject(self, attrs):
+ for attr in attrs:
+ cacheAttr = self.sqlmeta.cachedAttributes.get(attr, None)
+ if cacheAttr:
+ new_value = cacheAttr.func(self)
+ self._SO_cacheObject.set(**{attr+'_dirty': False,
+ attr: new_value})
+
def _addColumn(cls, connection, column_name, column_definition, changeSchema, post_funcs):
+ ''' for automatically adding dependencies to foreign keys'''
def f(cls, col):
if col.foreignKey:
dep.add((cls.__name__, col.name), (col.foreignKey, 'id', lambda cls=cls,col=col: getattr(cls.q, col.origName)))
@@ -25,6 +54,7 @@
events.listen(_addColumn, MaterializedSQLObject, events.AddColumnSignal)
def _addJoin(cls, join_name, join_definition, post_funcs):
+ ''' for automatically adding dependencies to joins'''
def f(cls, join):
dep.add((cls.__name__, join.joinMethodName), (join.otherClassName, 'id', lambda cls=cls,join=join: getattr(cls.q, join.joinMethodName)))
post_funcs.append(f)
@@ -36,18 +66,21 @@
def __init__(self, func, colType, name=None):
self.func = func
self.colType = colType
+
if name is None:
- self.name = self.func.__name__
- else:
- self.name = name
+ name = self.func.__name__
+ if name[:5] == '_get_':
+ name = name[5:]
+ self.name = name
self.__name__ = self.name
self.__dict__.update(func.__dict__)
def __call__(self, obj):
val = None
- if getattr(obj, '_SO_cacheInstance', None):
- val = getattr(obj._SO_cacheInstance, self.name)
+ if getattr(obj, '_SO_cacheObject', None):
+ if not getattr(obj._SO_cacheObject, self.name+"_dirty"):
+ val = getattr(obj._SO_cacheObject, self.name)
if val is None:
val = self.func(obj)
return val
@@ -58,12 +91,13 @@
return decorate
-
-def _processCacheClass(new_class_name, bases, new_attrs, post_funcs, early_funcs):
+def _addColumnsToCacheClass(new_class_name, bases, new_attrs, post_funcs, early_funcs):
def f(cls):
for name, value in new_attrs.items():
if isinstance(value, MaterializedAttr):
- cls.sqlmeta.
- post_funcs.append(f)
+ cls.sqlmeta.cachedAttributes[value.name] = value
+ cls.sqlmeta.cacheClass.sqlmeta.addColumn(value.colType(name=value.name, default=None))
+ cls.sqlmeta.cacheClass.sqlmeta.addColumn(col.BoolCol(name=value.name+'_dirty', default=True))
+ post_funcs.extend((f,makeProperties))
-listen(_processCacheClass, MaterializedSQLObject, ClassCreateSignal)
\ No newline at end of file
+listen(_addColumnsToCacheClass, MaterializedSQLObject, ClassCreateSignal)
Modified: SQLObject/branches/cache-deps-on-views/sqlobject/materialized/tests/test_materialized.py
===================================================================
--- SQLObject/branches/cache-deps-on-views/sqlobject/materialized/tests/test_materialized.py 2007-04-18 17:47:46 UTC (rev 2564)
+++ SQLObject/branches/cache-deps-on-views/sqlobject/materialized/tests/test_materialized.py 2007-04-18 17:49:00 UTC (rev 2565)
@@ -10,11 +10,12 @@
class MaterializedOne(MaterializedSQLObject):
name = StringCol()
- twos = SQLMultipleJoin('MaterializedTwo', joinColumn='one_id')
+ twos = SQLMultipleJoin('MaterializedTwo', joinColumn='oneID')
@cachedAs(IntCol)
- @dep.dependentOn('MaterializedOne', 'twos', MO.q.twos)
+ @dep.dependentOn('MaterializedOne', 'twos')
def _get_twoCount(self):
+ print "getting twoCount", self.twos.count()
return self.twos.count()
@cachedAs(IntCol)
@@ -41,8 +42,15 @@
def _get_name2(self):
return self.one.name + self.detail
+ @cachedAs(StringCol)
+ @dep.dependentOn('MaterializedTwo', 'detail')
+ @dep.dependentOn('MaterializedTwo', 'name')
+ def _get_name3(self):
+ ''' dep on dep '''
+ return self.name + self.detail
+
def setup_module(mod):
- setupClass([MaterializedOne, MaterializedTwo])
+ setupClass([MaterializedOne, MaterializedTwo, MaterializedOne.sqlmeta.cacheClass, MaterializedTwo.sqlmeta.cacheClass])
mod.ones = inserts(MaterializedOne, (('S',),
('T',),
), 'name')
@@ -54,8 +62,8 @@
def testSetup():
deps = dep.get('MaterializedOne', 'name')
- assert set([(x,y) for x,y,z in deps]) == set([('MaterializedTwo','_get_name'),
- ('MaterializedTwo','_get_name2')])
+ assert set([(x,y) for x,y,z in deps]) == set([('MaterializedTwo','name'),
+ ('MaterializedTwo','name2')])
assert [z for x,y,z in deps][0] != [None, None]
def testSetupDepsForFK():
@@ -73,14 +81,62 @@
def testProcessInstances():
assert dep.instancesToProcess(ones[0], ['name']) == {
- ('MaterializedTwo', '_get_name'): [twos[0], twos[1]],
- ('MaterializedTwo', '_get_name2'): [twos[0], twos[1]],
+ ('MaterializedTwo', 'name'): [twos[0], twos[1]],
+ ('MaterializedTwo', 'name2'): [twos[0], twos[1]],
}
-def testCacheObject():
+def testCacheClass():
assert MaterializedOne.sqlmeta.cacheClass.sqlmeta.table == 'materialized_one_cache'
# Overridden by MaterializedTow.sqlmeta.cachedIn
assert MaterializedTwo.sqlmeta.cacheClass.sqlmeta.table == 'cache_materialized_two'
+
+ assert 'name' in MaterializedTwo.sqlmeta.cacheClass.sqlmeta.columns
-def testCacheObject():
- assert ones[0]._SO_cacheObject is None
\ No newline at end of file
+def testManualCacheObject():
+ obj = twos[0]
+ assert hasattr(obj, '_SO_cacheObject')
+ assert obj._SO_cacheObject.name == None
+ obj._SO_cacheObject.name = 'Not Right'
+ obj._SO_cacheObject.name_dirty = False
+ assert obj._SO_cacheObject.name == 'Not Right'
+
+def testDepSettingCacheObject():
+ obj = twos[1]
+ assert obj._SO_cacheObject.name == None
+ dep.process(obj.one, ['name'])
+ assert obj._SO_cacheObject.name == obj._get_name.func(obj)
+
+def testModificationSettingCacheObject():
+ obj = twos[2]
+ assert obj._SO_cacheObject.name == None
+ obj.one.name = 'G'
+ assert obj._SO_cacheObject.name == 'G'
+ assert obj.name == 'G'
+
+def testJoinUpdateSettingCacheObject():
+ obj = ones[0]
+ prev = obj.detailSize
+ obj.twos[0].length += 4
+ assert obj._SO_cacheObject.detailSize == prev + 4
+ assert obj.detailSize == prev + 4
+
+def testJoinAdditionSettingCacheObject():
+ obj = ones[1]
+ prevS = obj.detailSize
+ prevC = obj.twoCount
+ new_two = MaterializedTwo(detail='f', length=4, one=obj)
+ assert obj._SO_cacheObject.detailSize == prevS + new_two.length
+ assert obj._SO_cacheObject.twoCount == prevC + 1
+ assert obj.detailSize == prevS + new_two.length
+
+def testJoinDeletionSettingCacheObject():
+ obj = ones[1]
+ prevS = obj.detailSize
+ prevC = obj.twoCount
+ new_two = MaterializedTwo(detail='g', length=5, one=obj)
+ assert obj._SO_cacheObject.detailSize == prevS + new_two.length
+ assert obj._SO_cacheObject.twoCount == prevC + 1
+ new_two.destroySelf()
+ assert obj.twos.count() == prevC
+ assert obj._SO_cacheObject.detailSize == prevS
+ assert obj._SO_cacheObject.twoCount == prevC
\ No newline at end of file
|
|
From: <sub...@co...> - 2007-04-18 17:47:54
|
Author: luke
Date: 2007-04-18 11:47:46 -0600 (Wed, 18 Apr 2007)
New Revision: 2564
Modified:
SQLObject/branches/cache-deps-on-views/sqlobject/events.py
SQLObject/branches/cache-deps-on-views/sqlobject/main.py
SQLObject/branches/cache-deps-on-views/sqlobject/tests/test_events.py
Log:
Events model changes
Modified: SQLObject/branches/cache-deps-on-views/sqlobject/events.py
===================================================================
--- SQLObject/branches/cache-deps-on-views/sqlobject/events.py 2007-04-18 07:12:26 UTC (rev 2563)
+++ SQLObject/branches/cache-deps-on-views/sqlobject/events.py 2007-04-18 17:47:46 UTC (rev 2564)
@@ -82,11 +82,7 @@
class RowCreatedSignal(Signal):
"""
Called after an instance is created, with the class as the
- sender. Called with the arguments ``(kwargs, post_funcs)``.
- There may be a ``connection`` argument. ``kwargs``may be usefully
- modified. ``post_funcs`` is a list of callbacks, intended to have
- functions appended to it, and are called with the arguments
- ``(new_instance)``.
+ sender. Called with the arguments ``(new_instance, kwargs)``.
Note: this is not called when an instance is created from an
existing database row.
@@ -97,9 +93,13 @@
class RowDestroySignal(Signal):
"""
Called before an instance is deleted. Sender is the instance's
- class. Arguments are ``(instance)``. You cannot cancel the delete,
+ class. Arguments are ``(instance, post_funcs)``. You cannot cancel the delete,
but you can raise an exception (which will probably cancel the
delete, but also cause an uncaught exception if not expected).
+
+ ``post_funcs`` is a list of callbacks, intended to have
+ functions appended to it, and are called with the arguments
+ ``(deleted_instance)``.
Note: this is not called when an instance is destroyed through
garbage collection.
@@ -108,15 +108,39 @@
row can be deleted without first fetching it?
"""
+class RowDestroyedSignal(Signal):
+ """
+ Called after an instance is deleted. Sender is the instance's
+ class. Arguments are ``(instance)``.
+
+ Note: this is not called when an instance is destroyed through
+ garbage collection.
+
+ @@: Should this allow ``instance`` to be a primary key, so that a
+ row can be deleted without first fetching it?
+ """
+
class RowUpdateSignal(Signal):
"""
Called when an instance is updated through a call to ``.set()``
(or a column attribute assignment). The arguments are
- ``(instance, kwargs)``. ``kwargs`` can be modified. This is run
- *before* the instance is updated; if you want to look at the
- current values, simply look at ``instance``.
+ ``(instance, kwargs, post_funcs)``. ``kwargs`` can be modified.
+ This is run *before* the instance is updated; if you want to look
+ at the current values, simply look at ``instance``.
+
+ ``post_funcs`` is a list of callbacks, intended to have
+ functions appended to it, and are called with the arguments
+ ``(deleted_instance)``.
+
"""
+class RowUpdatedSignal(Signal):
+ """
+ Called when an instance is updated through a call to ``.set()``
+ (or a column attribute assignment). The arguments are
+ ``(instance, kwargs)``. This is run *after* the instance is updated.
+ """
+
class AddColumnSignal(Signal):
"""
Called when a column is added to a class, with arguments ``(cls,
Modified: SQLObject/branches/cache-deps-on-views/sqlobject/main.py
===================================================================
--- SQLObject/branches/cache-deps-on-views/sqlobject/main.py 2007-04-18 07:12:26 UTC (rev 2563)
+++ SQLObject/branches/cache-deps-on-views/sqlobject/main.py 2007-04-18 17:47:46 UTC (rev 2564)
@@ -1049,9 +1049,10 @@
# in the database, and we can't insert it until all
# the parts are set. So we just keep them in a
# dictionary until later:
+ post_funcs = []
d = {name: value}
if not self.sqlmeta._creating:
- self.sqlmeta.send(events.RowUpdateSignal, self, d)
+ self.sqlmeta.send(events.RowUpdateSignal, self, d, post_funcs)
if len(d) != 1 or name not in d:
return self.set(**d)
value = d[name]
@@ -1073,10 +1074,15 @@
if self.sqlmeta.cacheValues:
setattr(self, instanceName(name), value)
+
+ for func in post_funcs:
+ func(self)
+ self.sqlmeta.send(events.RowUpdatedSignal, self, d)
def set(self, **kw):
+ post_funcs = []
if not self.sqlmeta._creating:
- self.sqlmeta.send(events.RowUpdateSignal, self, kw)
+ self.sqlmeta.send(events.RowUpdateSignal, self, kw, post_funcs)
# set() is used to update multiple values at once,
# potentially with one SQL statement if possible.
@@ -1160,6 +1166,10 @@
self._connection._SO_update(self, args)
finally:
self._SO_writeLock.release()
+
+ for func in post_funcs:
+ func(self)
+ self.sqlmeta.send(events.RowUpdatedSignal, self, kw)
def _SO_selectInit(self, row):
for col, colValue in zip(self.sqlmeta.columnList, row):
@@ -1223,6 +1233,10 @@
self._create(id, **kw)
for func in post_funcs:
func(self)
+
+ kw = kw.copy()
+ kw['id'] = self.id
+ self.sqlmeta.send(events.RowCreatedSignal, self, kw)
def _create(self, id, **kw):
@@ -1279,9 +1293,6 @@
cache = self._connection.cache
cache.created(id, self.__class__, self)
self._init(id)
- post_funcs = []
- kw = dict([('class',self.__class__),('id',id)])
- self.sqlmeta.send(events.RowCreatedSignal, kw, post_funcs)
def _SO_getID(self, obj):
@@ -1506,7 +1517,8 @@
clearTable = classmethod(clearTable)
def destroySelf(self):
- self.sqlmeta.send(events.RowDestroySignal, self)
+ post_funcs = []
+ self.sqlmeta.send(events.RowDestroySignal, self, post_funcs)
# Kills this object. Kills it dead!
klass = self.__class__
@@ -1567,6 +1579,10 @@
self.sqlmeta._obsolete = True
self._connection._SO_delete(self)
self._connection.cache.expire(self.id, self.__class__)
+
+ for func in post_funcs:
+ func(self)
+ self.sqlmeta.send(events.RowDestroyedSignal, self)
def delete(cls, id, connection=None):
obj = cls.get(id, connection=connection)
Modified: SQLObject/branches/cache-deps-on-views/sqlobject/tests/test_events.py
===================================================================
--- SQLObject/branches/cache-deps-on-views/sqlobject/tests/test_events.py 2007-04-18 07:12:26 UTC (rev 2563)
+++ SQLObject/branches/cache-deps-on-views/sqlobject/tests/test_events.py 2007-04-18 17:47:46 UTC (rev 2564)
@@ -41,14 +41,31 @@
assert len(watcher.log) == 2
assert watcher.log[0] == ({'name': 'foo'}, [])
-def test_row_destrow():
+def test_row_created():
setupClass(EventTester)
+ watcher = make_listen(events.RowCreatedSignal)
+ a = EventTester(name='foo')
+ b = EventTester(name='bar')
+ assert len(watcher.log) == 2
+ assert watcher.log[0] == (a, {'id': a.id, 'name': 'foo'})
+ assert watcher.log[1] == (b, {'id': b.id, 'name': 'bar'})
+
+def test_row_destroyrow():
+ setupClass(EventTester)
watcher = make_listen(events.RowDestroySignal)
f = EventTester(name='foo')
assert not watcher.log
f.destroySelf()
+ assert watcher.log == [(f,[])]
+
+def test_row_destroyedrow():
+ setupClass(EventTester)
+ watcher = make_listen(events.RowDestroyedSignal)
+ f = EventTester(name='foo')
+ assert not watcher.log
+ f.destroySelf()
assert watcher.log == [(f,)]
-
+
def test_row_update():
setupClass(EventTester)
watcher = make_listen(events.RowUpdateSignal)
@@ -57,9 +74,20 @@
f.name = 'bar2'
f.set(name='bar3')
assert watcher.log == [
+ (f, {'name': 'bar2'}, []),
+ (f, {'name': 'bar3'}, [])]
+
+def test_row_updated():
+ setupClass(EventTester)
+ watcher = make_listen(events.RowUpdatedSignal)
+ f = EventTester(name='bar')
+ assert not watcher.log
+ f.name = 'bar2'
+ f.set(name='bar3')
+ assert watcher.log == [
(f, {'name': 'bar2'}),
(f, {'name': 'bar3'})]
-
+
def test_add_column():
setupClass(EventTester)
watcher = make_listen(events.AddColumnSignal)
|
|
From: <sub...@co...> - 2007-04-17 18:44:41
|
Author: luke
Date: 2007-04-17 12:44:35 -0600 (Tue, 17 Apr 2007)
New Revision: 2560
Modified:
SQLObject/branches/sqlbuilder-views+1/sqlobject/dbconnection.py
SQLObject/branches/sqlbuilder-views+1/sqlobject/firebird/firebirdconnection.py
SQLObject/branches/sqlbuilder-views+1/sqlobject/maxdb/maxdbconnection.py
SQLObject/branches/sqlbuilder-views+1/sqlobject/mssql/mssqlconnection.py
SQLObject/branches/sqlbuilder-views+1/sqlobject/mysql/mysqlconnection.py
SQLObject/branches/sqlbuilder-views+1/sqlobject/postgres/pgconnection.py
SQLObject/branches/sqlbuilder-views+1/sqlobject/sqlbuilder.py
SQLObject/branches/sqlbuilder-views+1/sqlobject/sqlite/sqliteconnection.py
SQLObject/branches/sqlbuilder-views+1/sqlobject/sybase/sybaseconnection.py
Log:
Possible implementation to allow sqlbuilder.Select to reference dbconnection._queryAddLimitOffset
Modified: SQLObject/branches/sqlbuilder-views+1/sqlobject/dbconnection.py
===================================================================
--- SQLObject/branches/sqlbuilder-views+1/sqlobject/dbconnection.py 2007-04-17 16:44:32 UTC (rev 2559)
+++ SQLObject/branches/sqlbuilder-views+1/sqlobject/dbconnection.py 2007-04-17 18:44:35 UTC (rev 2560)
@@ -925,10 +925,8 @@
return self.cachedURIs[uri]
if uri.find(':') != -1:
scheme, rest = uri.split(':', 1)
- assert self.schemeBuilders.has_key(scheme), (
- "No SQLObject driver exists for %s (only %s)"
- % (scheme, ', '.join(self.schemeBuilders.keys())))
- conn = self.schemeBuilders[scheme]().connectionFromURI(uri)
+ connCls = self.dbConnectionForScheme(scheme)
+ conn = connCls.connectionFromURI(uri)
else:
# We just have a name, not a URI
assert self.instanceNames.has_key(uri), \
@@ -938,8 +936,15 @@
self.cachedURIs[uri] = conn
return conn
+ def dbConnectionForScheme(self, scheme):
+ assert self.schemeBuilders.has_key(scheme), (
+ "No SQLObject driver exists for %s (only %s)"
+ % (scheme, ', '.join(self.schemeBuilders.keys())))
+ return self.schemeBuilders[scheme]()
+
TheURIOpener = ConnectionURIOpener()
registerConnection = TheURIOpener.registerConnection
registerConnectionInstance = TheURIOpener.registerConnectionInstance
connectionForURI = TheURIOpener.connectionForURI
+dbConnectionForScheme = TheURIOpener.dbConnectionForScheme
Modified: SQLObject/branches/sqlbuilder-views+1/sqlobject/firebird/firebirdconnection.py
===================================================================
--- SQLObject/branches/sqlbuilder-views+1/sqlobject/firebird/firebirdconnection.py 2007-04-17 16:44:32 UTC (rev 2559)
+++ SQLObject/branches/sqlbuilder-views+1/sqlobject/firebird/firebirdconnection.py 2007-04-17 18:44:35 UTC (rev 2560)
@@ -107,7 +107,7 @@
self.printDebug(conn, id, 'QueryIns', 'result')
return id
- def _queryAddLimitOffset(self, query, start, end):
+ def _queryAddLimitOffset(cls, query, start, end):
"""Firebird slaps the limit and offset (actually 'first' and
'skip', respectively) statement right after the select."""
if not start:
@@ -117,11 +117,12 @@
else:
limit_str = "SELECT FIRST %i SKIP %i" % (end-start, start)
- match = self.limit_re.match(query)
+ match = cls.limit_re.match(query)
if match and len(match.groups()) == 2:
return ' '.join([limit_str, match.group(2)])
else:
return query
+ _queryAddLimitOffset = classmethod(_queryAddLimitOffset)
def createTable(self, soClass):
self.query('CREATE TABLE %s (\n%s\n)' % \
Modified: SQLObject/branches/sqlbuilder-views+1/sqlobject/maxdb/maxdbconnection.py
===================================================================
--- SQLObject/branches/sqlbuilder-views+1/sqlobject/maxdb/maxdbconnection.py 2007-04-17 16:44:32 UTC (rev 2559)
+++ SQLObject/branches/sqlbuilder-views+1/sqlobject/maxdb/maxdbconnection.py 2007-04-17 18:44:35 UTC (rev 2560)
@@ -136,7 +136,7 @@
self.printDebug(conn, id, 'QueryIns', 'result')
return id
- def sqlAddLimit(self,query,limit):
+ def sqlAddLimit(cls,query,limit):
sql = query
sql = sql.replace("SELECT","SELECT ROWNO, ")
if sql.find('WHERE') != -1:
@@ -144,12 +144,14 @@
else:
sql = sql + 'WHERE ' + limit
return sql
+ sqlAddLimit = classmethod(sqlAddLimit)
- def _queryAddLimitOffset(self, query, start, end):
+ def _queryAddLimitOffset(cls, query, start, end):
if start:
raise LowerBoundOfSliceIsNotSupported
limit = ' ROWNO <= %d ' % (end)
- return self.sqlAddLimit(query,limit)
+ return cls.sqlAddLimit(query,limit)
+ _queryAddLimitOffset = classmethod(_queryAddLimitOffset)
def createTable(self, soClass):
Modified: SQLObject/branches/sqlbuilder-views+1/sqlobject/mssql/mssqlconnection.py
===================================================================
--- SQLObject/branches/sqlbuilder-views+1/sqlobject/mssql/mssqlconnection.py 2007-04-17 16:44:32 UTC (rev 2559)
+++ SQLObject/branches/sqlbuilder-views+1/sqlobject/mssql/mssqlconnection.py 2007-04-17 18:44:35 UTC (rev 2560)
@@ -143,15 +143,16 @@
self.printDebug(conn, id, 'QueryIns', 'result')
return id
- def _queryAddLimitOffset(self, query, start, end):
+ def _queryAddLimitOffset(cls, query, start, end):
if end and not start:
limit_str = "SELECT TOP %i" % end
- match = self.limit_re.match(query)
+ match = cls.limit_re.match(query)
if match and len(match.groups()) == 2:
return ' '.join([limit_str, match.group(2)])
else:
return query
+ _queryAddLimitOffset = classmethod(_queryAddLimitOffset)
def createReferenceConstraint(self, soClass, col):
return col.mssqlCreateReferenceConstraint()
Modified: SQLObject/branches/sqlbuilder-views+1/sqlobject/mysql/mysqlconnection.py
===================================================================
--- SQLObject/branches/sqlbuilder-views+1/sqlobject/mysql/mysqlconnection.py 2007-04-17 16:44:32 UTC (rev 2559)
+++ SQLObject/branches/sqlbuilder-views+1/sqlobject/mysql/mysqlconnection.py 2007-04-17 18:44:35 UTC (rev 2560)
@@ -150,6 +150,14 @@
self.printDebug(conn, id, 'QueryIns', 'result')
return id
+ def _queryAddLimitOffset(cls, query, start, end):
+ if not start:
+ return "%s LIMIT %i" % (query, end)
+ if not end:
+ return "%s LIMIT %i, -1" % (query, start)
+ return "%s LIMIT %i, %i" % (query, start, end-start)
+ _queryAddLimitOffset = classmethod(_queryAddLimitOffset)
+
def createReferenceConstraint(self, soClass, col):
return col.mysqlCreateReferenceConstraint()
Modified: SQLObject/branches/sqlbuilder-views+1/sqlobject/postgres/pgconnection.py
===================================================================
--- SQLObject/branches/sqlbuilder-views+1/sqlobject/postgres/pgconnection.py 2007-04-17 16:44:32 UTC (rev 2559)
+++ SQLObject/branches/sqlbuilder-views+1/sqlobject/postgres/pgconnection.py 2007-04-17 18:44:35 UTC (rev 2560)
@@ -138,6 +138,14 @@
self.printDebug(conn, id, 'QueryIns', 'result')
return id
+ def _queryAddLimitOffset(cls, query, start, end):
+ if not start:
+ return "%s LIMIT %i" % (query, end)
+ if not end:
+ return "%s OFFSET %i" % (query, start)
+ return "%s LIMIT %i OFFSET %i" % (query, end-start, start)
+ _queryAddLimitOffset = classmethod(_queryAddLimitOffset)
+
def createColumn(self, soClass, col):
return col.postgresCreateSQL()
Modified: SQLObject/branches/sqlbuilder-views+1/sqlobject/sqlbuilder.py
===================================================================
--- SQLObject/branches/sqlbuilder-views+1/sqlobject/sqlbuilder.py 2007-04-17 16:44:32 UTC (rev 2559)
+++ SQLObject/branches/sqlbuilder-views+1/sqlobject/sqlbuilder.py 2007-04-17 18:44:35 UTC (rev 2560)
@@ -637,24 +637,12 @@
select += " ORDER BY %s" % ", ".join([sqlrepr(reverser(x), db) for x in orderBy])
else:
select += " ORDER BY %s" % sqlrepr(reverser(orderBy), db)
+ start, end = self.ops['start'], self.ops['end']
if self.ops['limit'] is not NoDefault:
- select += " LIMIT %s" % sqlrepr(self.ops['limit'], db)
- elif self.ops['start'] or self.ops['end']:
- start, end = self.ops['start'], self.ops['end']
- if db == 'mysql':
- if not start:
- select += "%s LIMIT %i" % end
- elif not end:
- select += "%s LIMIT %i, -1" % start
- else:
- select +="%s LIMIT %i, %i" % (start, end-start)
- else:
- if not start:
- select += " LIMIT %i" % end
- elif not end:
- select += " OFFSET %i" % start
- else:
- select += " LIMIT %i OFFSET %i" % (end-start, start)
+ end = start + limit
+ if start or end:
+ from dbconnection import dbConnectionForScheme
+ select = dbConnectionForScheme(db)._queryAddLimitOffset(select, start, end)
if self.ops['forUpdate']:
select += " FOR UPDATE"
return select
Modified: SQLObject/branches/sqlbuilder-views+1/sqlobject/sqlite/sqliteconnection.py
===================================================================
--- SQLObject/branches/sqlbuilder-views+1/sqlobject/sqlite/sqliteconnection.py 2007-04-17 16:44:32 UTC (rev 2559)
+++ SQLObject/branches/sqlbuilder-views+1/sqlobject/sqlite/sqliteconnection.py 2007-04-17 18:44:35 UTC (rev 2560)
@@ -231,12 +231,13 @@
else:
return DBAPI._insertSQL(self, table, names, values)
- def _queryAddLimitOffset(self, query, start, end):
+ def _queryAddLimitOffset(cls, query, start, end):
if not start:
return "%s LIMIT %i" % (query, end)
if not end:
return "%s LIMIT 0 OFFSET %i" % (query, start)
return "%s LIMIT %i OFFSET %i" % (query, end-start, start)
+ _queryAddLimitOffset = classmethod(_queryAddLimitOffset)
def createColumn(self, soClass, col):
return col.sqliteCreateSQL()
Modified: SQLObject/branches/sqlbuilder-views+1/sqlobject/sybase/sybaseconnection.py
===================================================================
--- SQLObject/branches/sqlbuilder-views+1/sqlobject/sybase/sybaseconnection.py 2007-04-17 16:44:32 UTC (rev 2559)
+++ SQLObject/branches/sqlbuilder-views+1/sqlobject/sybase/sybaseconnection.py 2007-04-17 18:44:35 UTC (rev 2560)
@@ -94,11 +94,12 @@
self.printDebug(conn, id, 'QueryIns', 'result')
return id
- def _queryAddLimitOffset(self, query, start, end):
+ def _queryAddLimitOffset(cls, query, start, end):
# XXX Sybase doesn't support OFFSET
if end:
return "SET ROWCOUNT %i %s SET ROWCOUNT 0" % (end, query)
return query
+ _queryAddLimitOffset = classmethod(_queryAddLimitOffset)
def createReferenceConstraint(self, soClass, col):
return None
|
|
From: SourceForge.net <no...@so...> - 2007-04-17 16:44:47
|
Patches item #1701949, was opened at 2007-04-17 07:42 Message generated for change (Comment added) made by phd You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=540674&aid=1701949&group_id=74338 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: None Group: None >Status: Closed >Resolution: Accepted Priority: 5 Private: No Submitted By: Leandro Lucarella (llucax) >Assigned to: Oleg Broytmann (phd) Summary: Add documentation about 'validator' Col constructor option Initial Comment: Please, review the patch since english is not my native language and it's very likely that I have spell/grammar errors ;) This patch was motivated by this thread: http://permalink.gmane.org/gmane.comp.python.sqlobject/8031, specially to document what is shown on this e-mail: http://permalink.gmane.org/gmane.comp.python.sqlobject/8042. ---------------------------------------------------------------------- >Comment By: Oleg Broytmann (phd) Date: 2007-04-17 20:44 Message: Logged In: YES user_id=4799 Originator: NO Applied in the revisions 2556-2559 (0.7, 0.8, 0.9 and the trunk). Thank you! ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=540674&aid=1701949&group_id=74338 |
|
From: <sub...@co...> - 2007-04-17 16:44:35
|
Author: phd
Date: 2007-04-17 10:44:32 -0600 (Tue, 17 Apr 2007)
New Revision: 2559
Modified:
SQLObject/docs/SQLObject.txt
Log:
Applied the patch 1701949: documentation about 'validator' Col constructor option.
Modified: SQLObject/docs/SQLObject.txt
===================================================================
--- SQLObject/docs/SQLObject.txt 2007-04-17 16:44:19 UTC (rev 2558)
+++ SQLObject/docs/SQLObject.txt 2007-04-17 16:44:32 UTC (rev 2559)
@@ -1048,7 +1048,16 @@
You can use classes (defined below) for this, but if those don't
work it's sometimes easiest just to use `sqlType`. Only necessary
if SQLObject is creating your tables.
+`validator`:
+ formencode_-like validator_. Making long story short, this is
+ an object that provides ``to_python()`` and ``from_python()``
+ to validate *and* convert (adapt or cast) the values when they are
+ read/written from/to the database. You should see formencode_
+ validator_ documentation for more details.
+.. _formencode: http://formencode.org/
+.. _validator: http://formencode.org/Validator.html
+
Column Types
~~~~~~~~~~~~
|
|
From: <sub...@co...> - 2007-04-17 16:44:22
|
Author: phd
Date: 2007-04-17 10:44:19 -0600 (Tue, 17 Apr 2007)
New Revision: 2558
Modified:
SQLObject/branches/0.9/docs/SQLObject.txt
Log:
Applied the patch 1701949: documentation about 'validator' Col constructor option.
Modified: SQLObject/branches/0.9/docs/SQLObject.txt
===================================================================
--- SQLObject/branches/0.9/docs/SQLObject.txt 2007-04-17 16:44:04 UTC (rev 2557)
+++ SQLObject/branches/0.9/docs/SQLObject.txt 2007-04-17 16:44:19 UTC (rev 2558)
@@ -1048,7 +1048,16 @@
You can use classes (defined below) for this, but if those don't
work it's sometimes easiest just to use `sqlType`. Only necessary
if SQLObject is creating your tables.
+`validator`:
+ formencode_-like validator_. Making long story short, this is
+ an object that provides ``to_python()`` and ``from_python()``
+ to validate *and* convert (adapt or cast) the values when they are
+ read/written from/to the database. You should see formencode_
+ validator_ documentation for more details.
+.. _formencode: http://formencode.org/
+.. _validator: http://formencode.org/Validator.html
+
Column Types
~~~~~~~~~~~~
|
|
From: <sub...@co...> - 2007-04-17 16:44:07
|
Author: phd
Date: 2007-04-17 10:44:04 -0600 (Tue, 17 Apr 2007)
New Revision: 2557
Modified:
SQLObject/branches/0.8/docs/SQLObject.txt
Log:
Applied the patch 1701949: documentation about 'validator' Col constructor option.
Modified: SQLObject/branches/0.8/docs/SQLObject.txt
===================================================================
--- SQLObject/branches/0.8/docs/SQLObject.txt 2007-04-17 16:42:33 UTC (rev 2556)
+++ SQLObject/branches/0.8/docs/SQLObject.txt 2007-04-17 16:44:04 UTC (rev 2557)
@@ -1045,7 +1045,16 @@
You can use classes (defined below) for this, but if those don't
work it's sometimes easiest just to use `sqlType`. Only necessary
if SQLObject is creating your tables.
+`validator`:
+ formencode_-like validator_. Making long story short, this is
+ an object that provides ``to_python()`` and ``from_python()``
+ to validate *and* convert (adapt or cast) the values when they are
+ read/written from/to the database. You should see formencode_
+ validator_ documentation for more details.
+.. _formencode: http://formencode.org/
+.. _validator: http://formencode.org/Validator.html
+
Column Types
~~~~~~~~~~~~
|
|
From: <sub...@co...> - 2007-04-17 16:42:36
|
Author: phd
Date: 2007-04-17 10:42:33 -0600 (Tue, 17 Apr 2007)
New Revision: 2556
Modified:
SQLObject/branches/0.7/docs/SQLObject.txt
Log:
Applied the patch 1701949: documentation about 'validator' Col constructor option.
Modified: SQLObject/branches/0.7/docs/SQLObject.txt
===================================================================
--- SQLObject/branches/0.7/docs/SQLObject.txt 2007-04-17 16:33:44 UTC (rev 2555)
+++ SQLObject/branches/0.7/docs/SQLObject.txt 2007-04-17 16:42:33 UTC (rev 2556)
@@ -1044,7 +1044,16 @@
You can use classes (defined below) for this, but if those don't
work it's sometimes easiest just to use `sqlType`. Only necessary
if SQLObject is creating your tables.
+`validator`:
+ formencode_-like validator_. Making long story short, this is
+ an object that provides ``to_python()`` and ``from_python()``
+ to validate *and* convert (adapt or cast) the values when they are
+ read/written from/to the database. You should see formencode_
+ validator_ documentation for more details.
+.. _formencode: http://formencode.org/
+.. _validator: http://formencode.org/Validator.html
+
Column Types
~~~~~~~~~~~~
|
|
From: SourceForge.net <no...@so...> - 2007-04-17 16:34:38
|
Bugs item #1699518, was opened at 2007-04-13 00:34 Message generated for change (Comment added) made by phd You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=540672&aid=1699518&group_id=74338 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: General Group: SQLObject release (specify) >Status: Closed >Resolution: Fixed Priority: 5 Private: No Submitted By: kumar mcmillan (kumar303) Assigned to: Oleg Broytmann (phd) Summary: select(limit=n) - limit keyword is not recognized Initial Comment: 0.8.1 release here is a failing test case :( from sqlobject import * def test(): c = connectionForURI('sqlite:/:memory:') class Foo(SQLObject): bar = 1 Foo.createTable(connection=c) f = Foo(connection=c) f = Foo(connection=c) assert Foo.select(connection=c).count() == 2 assert Foo.select(connection=c, limit=1).count() == 1 if __name__ == '__main__': test() ---------------------------------------------------------------------- >Comment By: Oleg Broytmann (phd) Date: 2007-04-17 20:34 Message: Logged In: YES user_id=4799 Originator: NO Fixed in Subversion in the revisions 2250-2254 (0.7, 0.8, 0.9, trunk and docs). Will be in the next round of releases. Thank you! ---------------------------------------------------------------------- Comment By: Oleg Broytmann (phd) Date: 2007-04-16 22:28 Message: Logged In: YES user_id=4799 Originator: NO Yes, that's a long-standing bug in SelectResults. Meanwhile you can use .select()[:1] or .select().limit(1). ---------------------------------------------------------------------- Comment By: kumar mcmillan (kumar303) Date: 2007-04-16 21:07 Message: Logged In: YES user_id=540473 Originator: YES sorry, bad example. The bug is not with count(), it is with sql reproduction of the entire select. It is not including the limit=limit part of the query. Here is a better test, still failing. from sqlobject import * def test(): c = connectionForURI('sqlite:/:memory:') class Foo(SQLObject): bar = StringCol() Foo.createTable(connection=c) f = Foo(bar='bar', connection=c) f = Foo(bar='foo', connection=c) rs = Foo.select(connection=c) assert len(list(rs)) == 2 rs = Foo.select(connection=c, limit=1) print rs assert len(list(rs)) == 1 if __name__ == '__main__': test() print "OK" File Added: test_sresults.py ---------------------------------------------------------------------- Comment By: Oleg Broytmann (phd) Date: 2007-04-16 17:16 Message: Logged In: YES user_id=4799 Originator: NO Using both COUNT() and LIMIT is meaningless. LIMIT limits the number of rows returned by SELECT, but SELECT COUNT() returns exactly 1 (one) row, so what are you limiting? If you want to limit what SELECT * returns and later count it - use few separate queries, or a complex query with subqueries. ---------------------------------------------------------------------- Comment By: kumar mcmillan (kumar303) Date: 2007-04-13 00:38 Message: Logged In: YES user_id=540473 Originator: YES tested in SQLObject-0.10dev_r2521-py2.4.egg ... still broken ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=540672&aid=1699518&group_id=74338 |
|
From: <sub...@co...> - 2007-04-17 16:33:47
|
Author: phd
Date: 2007-04-17 10:33:44 -0600 (Tue, 17 Apr 2007)
New Revision: 2555
Modified:
home/phd/SQLObject/paramstyles/sqlobject/sresults.py
home/phd/SQLObject/paramstyles/sqlobject/tests/test_select.py
home/phd/SQLObject/paramstyles/sqlobject/versioning/__init__.py
Log:
Merged patches from the revisions 2552:2554 from the trunk
Modified: home/phd/SQLObject/paramstyles/sqlobject/sresults.py
===================================================================
--- home/phd/SQLObject/paramstyles/sqlobject/sresults.py 2007-04-17 16:31:40 UTC (rev 2554)
+++ home/phd/SQLObject/paramstyles/sqlobject/sresults.py 2007-04-17 16:33:44 UTC (rev 2555)
@@ -21,16 +21,21 @@
self.clauseTables = clauseTables
self.tables = tablesDict.keys()
self.ops = ops
- if self.ops.get('orderBy', sqlbuilder.NoDefault) is sqlbuilder.NoDefault:
- self.ops['orderBy'] = sourceClass.sqlmeta.defaultOrder
- orderBy = self.ops['orderBy']
+ if ops.get('orderBy', sqlbuilder.NoDefault) is sqlbuilder.NoDefault:
+ ops['orderBy'] = sourceClass.sqlmeta.defaultOrder
+ orderBy = ops['orderBy']
if isinstance(orderBy, list) or isinstance(orderBy, tuple):
orderBy = map(self._mungeOrderBy, orderBy)
else:
orderBy = self._mungeOrderBy(orderBy)
- self.ops['dbOrderBy'] = orderBy
+ ops['dbOrderBy'] = orderBy
if ops.has_key('connection') and ops['connection'] is None:
del ops['connection']
+ if ops.get('limit', None):
+ assert not ops.get('start', None) and not ops.get('end', None), \
+ "'limit' cannot be used with 'start' or 'end'"
+ ops["start"] = 0
+ ops["end"] = ops["limit"]
def __repr__(self):
return "<%s at %x>" % (self.__class__.__name__, id(self))
@@ -145,13 +150,13 @@
if self.ops.get('end', None) is not None \
and self.ops['end'] < end:
end = self.ops['end']
- return self.clone(start=start, end=end)
+ return self.clone(limit=None, start=start, end=end)
else:
if value < 0:
return list(iter(self))[value]
else:
start = self.ops.get('start', 0) + value
- return list(self.clone(start=start, end=start+1))[0]
+ return list(self.clone(limit=None, start=start, end=start+1))[0]
def __iter__(self):
# @@: This could be optimized, using a simpler algorithm
@@ -178,6 +183,7 @@
def count(self):
""" Counting elements of current select results """
+ assert not self.ops.get('limit'), "'limit' is meaningless with 'distinct'"
assert not (self.ops.get('distinct') and (self.ops.get('start')
or self.ops.get('end'))), \
"distinct-counting of sliced objects is not supported"
Modified: home/phd/SQLObject/paramstyles/sqlobject/tests/test_select.py
===================================================================
--- home/phd/SQLObject/paramstyles/sqlobject/tests/test_select.py 2007-04-17 16:31:40 UTC (rev 2554)
+++ home/phd/SQLObject/paramstyles/sqlobject/tests/test_select.py 2007-04-17 16:33:44 UTC (rev 2555)
@@ -1,9 +1,8 @@
from __future__ import generators # for enumerate
from sqlobject import *
from sqlobject.main import SQLObjectIntegrityError
-from sqlobject.tests.dbtest import *
-from sqlobject.tests.dbtest import setSQLiteConnectionFactory
-from py.test import raises
+from dbtest import *
+from dbtest import setSQLiteConnectionFactory
try:
enumerate
@@ -86,6 +85,12 @@
raises(SQLObjectIntegrityError, 'IterTest.selectBy(name="b").getOne()')
raises(SQLObjectIntegrityError, 'IterTest.selectBy(name="b").getOne(None)')
+def test_05_select_limit():
+ setupIter()
+ assert len(list(IterTest.select(limit=2))) == 2
+ raises(AssertionError, IterTest.select(limit=2).distinct)
+ raises(AssertionError, IterTest.select(limit=2).clone, start=1)
+
def test_selectBy():
setupClass(IterTest)
a = IterTest(name='a')
Modified: home/phd/SQLObject/paramstyles/sqlobject/versioning/__init__.py
===================================================================
--- home/phd/SQLObject/paramstyles/sqlobject/versioning/__init__.py 2007-04-17 16:31:40 UTC (rev 2554)
+++ home/phd/SQLObject/paramstyles/sqlobject/versioning/__init__.py 2007-04-17 16:33:44 UTC (rev 2555)
@@ -12,7 +12,7 @@
self.masterClass.get(self.masterID).set(**values)
def nextVersion(self):
- version = self.select(AND(self.q.masterID == self.masterID, self.q.id > self.id), limit=1, orderBy=self.q.id)
+ version = self.select(AND(self.q.masterID == self.masterID, self.q.id > self.id), orderBy=self.q.id)
if version.count():
return version[0]
else:
|