On Sat, Jun 06, 2009 at 12:20:50PM +0200, Herwig Hochleitner wrote:
> I intended to illustrate following behavior:
>
> Two instances of the same class with same id; one pulled via a  
> connection (with cache=False); one pulled via a transaction createt from  
> that same connection;
> --> Commits to the transaction _do_ invalidate the instance pulled via  
> connection (thanks to cache=False);
> --> Changes to the connection instance _don't_ invalidate the  
> transaction instance;
>
> This asymmetric behavior seems strange to me

   AFAIU it is meaningless from the transaction point of view. Changes
outside a transaction (regardless of the backend and SQLObject) must not
creep inside the transaction, right?
   Actually, in SQLite one cannot even change the DB outside a transaction
if there is an open transaction. Let's see. Start sqlite3 test.db and
initialize a table:

sqlite> CREATE TABLE test (id integer PRIMARY KEY, test VARCHAR (255));
sqlite> INSERT INTO test (test) VALUES ('test1');
sqlite> INSERT INTO test (test) VALUES ('test2');
sqlite> SELECT * FROM test;
1|test1
2|test2

   Now start another sqlite3, open the same DB test.db and start a
transaction:

sqlite> BEGIN;
sqlite> SELECT * FROM test;
1|test1
2|test2

   Back to the first connection:

sqlite> INSERT INTO test (test) VALUES ('test3');
SQL error: database is locked
sqlite> UPDATE test SET test='test3';
SQL error: database is locked

   No way, see? Now the second transactioned connection:

sqlite> COMMIT;

   Back to the first connection:

sqlite> INSERT INTO test (test) VALUES ('test3');

   And again the second transactioned connection:

sqlite> SELECT * FROM test;
1|test1
2|test2
3|test3

   Let us see how Postgres handles this. First createdb test and start two
psql test.

test=# CREATE TABLE test (id serial, test VARCHAR(255));
NOTICE:  CREATE TABLE will create implicit sequence "test_id_seq" for serial 
column "test.id"
CREATE TABLE
test=# INSERT INTO test (test) VALUES ('test1');
INSERT 0 1
test=# INSERT INTO test (test) VALUES ('test2');
INSERT 0 1
test=# SELECT * FROM test;
 id | test  
----+-------
  1 | test1
  2 | test2
(2 rows)

   Second connection:

test=# BEGIN;
BEGIN
test=# SELECT * FROM test;
 id | test  
----+-------
  1 | test1
  2 | test2
(2 rows)

   First connection:

test=# INSERT INTO test (test) VALUES ('test3');
INSERT 0 1

   Second transactioned connection:

test=# SELECT * FROM test;
 id | test  
----+-------
  1 | test1
  2 | test2
  3 | test3
(3 rows)

   The new row is visible. Back to the first connection:

test=# UPDATE test SET test='test4';
UPDATE 3

   Second transactioned connection:

test=# SELECT * FROM test;
 id | test  
----+-------
  1 | test4
  2 | test4
  3 | test4
(3 rows)

   The change is visible inside the transaction in Read Committed Isolation
Level. Let's try Serializable Isolation Level. Second transactioned connection:

test=# COMMIT;
ROLLBACK
test=# BEGIN;
BEGIN
test=# SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET
test=# SELECT * FROM test;
 id | test  
----+-------
  1 | test4
  2 | test4
  3 | test4
(3 rows)

   First connection:

test=# INSERT INTO test (test) VALUES ('test5');
INSERT 0 1

   Second transactioned connection:

test=# SELECT * FROM test;
 id | test  
----+-------
  1 | test4
  2 | test4
  3 | test4
(3 rows)

   No changes, see? First connection:

test=# UPDATE test SET test='test6';
UPDATE 4
test=# SELECT * FROM test;
 id | test  
----+-------
  1 | test6
  2 | test6
  3 | test6
  4 | test6
(4 rows)

   Second transactioned connection:

test=# SELECT * FROM test;
 id | test  
----+-------
  1 | test4
  2 | test4
  3 | test4
(3 rows)

   Still no changes. Data added or changed outside a transaction is not
visible in the transaction in Serializable Isolation Level. So SQLObject
has to be very clever to manipulate caches inside and outside transactions.

> Can I evade manually syncing all the transactions.

   Well, the simplest (not the best) way would be, probably, to turn off
caching completely:

class MyTable(SQLObject):
   class sqlmeta:
      cacheValues = False

> what's the  
> best way to invalidate a transaction's cache for a given instance/all  
> instances of given class?

   MyTable.sqlmeta.expireAll() or MyTable.sqlmeta.expireAll(transaction)

Oleg.
-- 
     Oleg Broytmann            http://phd.pp.ru/            p...@phd.pp.ru
           Programmers don't die, they just GOSUB without RETURN.

------------------------------------------------------------------------------
Are you an open source citizen? Join us for the Open Source Bridge conference!
Portland, OR, June 17-19. Two days of sessions, one day of unconference: $250.
Need another reason to go? 24-hour hacker lounge. Register today!
http://ad.doubleclick.net/clk;215844324;13503038;v?http://opensourcebridge.org
_______________________________________________
sqlobject-discuss mailing list
sqlobject-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sqlobject-discuss

Reply via email to