[sqlalchemy] Session.merge and multiple databases

2010-08-25 Thread Raf Geens
Hi,

I have a sqlite database A and a MySQL database B which share the same
schema, where I want to synchronize the contents of certain tables in
A with those in B at certain times. Except for the synchronizing step
the contents on A's side don't change, while those on B's side might.

I'm trying to do this using Session.merge, which works if the row
doesn't exist yet in A, or does but hasn't changed in B. If it has
changed in B, I get a ConcurrentModificationError when the merge is
flushed.

#Suppose this individual doesn't yet exist in A
individual = session_B.query(Individual).filter(...).one()
session_A.merge(individual)
#This will work and add the individual
session_A.commit()

individual.firstname = 'test'
session_B.commit()

individual = session_B.query(Individual).filter(...).one()
session_A.merge(individual)
#This will throw the ConcurrentModificationError
session_A.commit()

The error is:
Traceback (most recent call last):
  File stdin, line 1, in module
  File C:\Python25\lib\site-packages\sqlalchemy-0.5.6-py2.5.egg
\sqlalchemy\orm\
session.py, line 673, in commit
self.transaction.commit()
  File C:\Python25\lib\site-packages\sqlalchemy-0.5.6-py2.5.egg
\sqlalchemy\orm\
session.py, line 378, in commit
self._prepare_impl()
  File C:\Python25\lib\site-packages\sqlalchemy-0.5.6-py2.5.egg
\sqlalchemy\orm\
session.py, line 362, in _prepare_impl
self.session.flush()
  File C:\Python25\lib\site-packages\sqlalchemy-0.5.6-py2.5.egg
\sqlalchemy\orm\
session.py, line 1356, in flush
self._flush(objects)
  File C:\Python25\lib\site-packages\sqlalchemy-0.5.6-py2.5.egg
\sqlalchemy\orm\
session.py, line 1434, in _flush
flush_context.execute()
  File C:\Python25\lib\site-packages\sqlalchemy-0.5.6-py2.5.egg
\sqlalchemy\orm\
unitofwork.py, line 261, in execute
UOWExecutor().execute(self, tasks)
  File C:\Python25\lib\site-packages\sqlalchemy-0.5.6-py2.5.egg
\sqlalchemy\orm\
unitofwork.py, line 753, in execute
self.execute_save_steps(trans, task)
  File C:\Python25\lib\site-packages\sqlalchemy-0.5.6-py2.5.egg
\sqlalchemy\orm\
unitofwork.py, line 768, in execute_save_steps
self.save_objects(trans, task)
  File C:\Python25\lib\site-packages\sqlalchemy-0.5.6-py2.5.egg
\sqlalchemy\orm\
unitofwork.py, line 759, in save_objects
task.mapper._save_obj(task.polymorphic_tosave_objects, trans)
  File C:\Python25\lib\site-packages\sqlalchemy-0.5.6-py2.5.egg
\sqlalchemy\orm\
mapper.py, line 1401, in _save_obj
raise exc.ConcurrentModificationError(Updated rowcount %d does
not match nu
mber of objects updated %d % (rows, len(update)))
sqlalchemy.orm.exc.ConcurrentModificationError: Updated rowcount 0
does not matc
h number of objects updated 1

Am I trying to use Session.merge the wrong way?

Kind regards,
Raf Geens

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



Re: [sqlalchemy] Session.merge and multiple databases

2010-08-25 Thread Michael Bayer

On Aug 25, 2010, at 10:50 AM, Raf Geens wrote:

 Hi,
 
 I have a sqlite database A and a MySQL database B which share the same
 schema, where I want to synchronize the contents of certain tables in
 A with those in B at certain times. Except for the synchronizing step
 the contents on A's side don't change, while those on B's side might.
 
 I'm trying to do this using Session.merge, which works if the row
 doesn't exist yet in A, or does but hasn't changed in B. If it has
 changed in B, I get a ConcurrentModificationError when the merge is
 flushed.

can't reproduce in 0.5.6 nor in 0.6.3, so a full test script that reproduces 
will be needed.  Alternatively, you might want to look at your SQL output and 
see what primary key is attempting to be updated:

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()
class A(Base):
__tablename__ = 'a'
id = Column(Integer, primary_key=True)
firstname = Column(String)

e1 = create_engine('sqlite://', echo=True)
e2 = create_engine('sqlite://', echo=True)

Base.metadata.create_all(e1)
Base.metadata.create_all(e2)

session_B = sessionmaker(e1)()
session_A = sessionmaker(e2)()

individual = A(firstname='foo')
session_B.add(individual)
session_B.commit()

#Suppose this individual doesn't yet exist in A
individual = session_B.query(A).one()
session_A.merge(individual)
#This will work and add the individual
session_A.commit()

individual.firstname = 'test'
session_B.commit()

individual = session_B.query(A).one()
session_A.merge(individual)
#This will throw the ConcurrentModificationError
session_A.commit()




 
 #Suppose this individual doesn't yet exist in A
 individual = session_B.query(Individual).filter(...).one()
 session_A.merge(individual)
 #This will work and add the individual
 session_A.commit()
 
 individual.firstname = 'test'
 session_B.commit()
 
 individual = session_B.query(Individual).filter(...).one()
 session_A.merge(individual)
 #This will throw the ConcurrentModificationError
 session_A.commit()
 
 The error is:
 Traceback (most recent call last):
  File stdin, line 1, in module
  File C:\Python25\lib\site-packages\sqlalchemy-0.5.6-py2.5.egg
 \sqlalchemy\orm\
 session.py, line 673, in commit
self.transaction.commit()
  File C:\Python25\lib\site-packages\sqlalchemy-0.5.6-py2.5.egg
 \sqlalchemy\orm\
 session.py, line 378, in commit
self._prepare_impl()
  File C:\Python25\lib\site-packages\sqlalchemy-0.5.6-py2.5.egg
 \sqlalchemy\orm\
 session.py, line 362, in _prepare_impl
self.session.flush()
  File C:\Python25\lib\site-packages\sqlalchemy-0.5.6-py2.5.egg
 \sqlalchemy\orm\
 session.py, line 1356, in flush
self._flush(objects)
  File C:\Python25\lib\site-packages\sqlalchemy-0.5.6-py2.5.egg
 \sqlalchemy\orm\
 session.py, line 1434, in _flush
flush_context.execute()
  File C:\Python25\lib\site-packages\sqlalchemy-0.5.6-py2.5.egg
 \sqlalchemy\orm\
 unitofwork.py, line 261, in execute
UOWExecutor().execute(self, tasks)
  File C:\Python25\lib\site-packages\sqlalchemy-0.5.6-py2.5.egg
 \sqlalchemy\orm\
 unitofwork.py, line 753, in execute
self.execute_save_steps(trans, task)
  File C:\Python25\lib\site-packages\sqlalchemy-0.5.6-py2.5.egg
 \sqlalchemy\orm\
 unitofwork.py, line 768, in execute_save_steps
self.save_objects(trans, task)
  File C:\Python25\lib\site-packages\sqlalchemy-0.5.6-py2.5.egg
 \sqlalchemy\orm\
 unitofwork.py, line 759, in save_objects
task.mapper._save_obj(task.polymorphic_tosave_objects, trans)
  File C:\Python25\lib\site-packages\sqlalchemy-0.5.6-py2.5.egg
 \sqlalchemy\orm\
 mapper.py, line 1401, in _save_obj
raise exc.ConcurrentModificationError(Updated rowcount %d does
 not match nu
 mber of objects updated %d % (rows, len(update)))
 sqlalchemy.orm.exc.ConcurrentModificationError: Updated rowcount 0
 does not matc
 h number of objects updated 1
 
 Am I trying to use Session.merge the wrong way?
 
 Kind regards,
 Raf Geens
 
 -- 
 You received this message because you are subscribed to the Google Groups 
 sqlalchemy group.
 To post to this group, send email to sqlalch...@googlegroups.com.
 To unsubscribe from this group, send email to 
 sqlalchemy+unsubscr...@googlegroups.com.
 For more options, visit this group at 
 http://groups.google.com/group/sqlalchemy?hl=en.
 

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



Re: [sqlalchemy] Session.merge and multiple databases

2010-08-25 Thread Raf Geens

 On 25/08/2010 17:15, Michael Bayer wrote:

On Aug 25, 2010, at 10:50 AM, Raf Geens wrote:


Hi,

I have a sqlite database A and a MySQL database B which share the same
schema, where I want to synchronize the contents of certain tables in
A with those in B at certain times. Except for the synchronizing step
the contents on A's side don't change, while those on B's side might.

I'm trying to do this using Session.merge, which works if the row
doesn't exist yet in A, or does but hasn't changed in B. If it has
changed in B, I get a ConcurrentModificationError when the merge is
flushed.

can't reproduce in 0.5.6 nor in 0.6.3, so a full test script that reproduces 
will be needed.  Alternatively, you might want to look at your SQL output and 
see what primary key is attempting to be updated:

Thanks for the quick reply. I've looked at the SQL output of the last 
commit and it appears to match on the correct primary key. However, the 
Individual has a version_id_col defined in the mapper, and it's trying 
to match on the wrong value there, which seems to cause the update to 
fail. I'll try to reproduce it in a full script.


Raf

--
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



Re: [sqlalchemy] Session.merge and multiple databases

2010-08-25 Thread Raf Geens

 On 25/08/2010 17:47, Raf Geens wrote:

 On 25/08/2010 17:15, Michael Bayer wrote:

On Aug 25, 2010, at 10:50 AM, Raf Geens wrote:


Hi,

I have a sqlite database A and a MySQL database B which share the same
schema, where I want to synchronize the contents of certain tables in
A with those in B at certain times. Except for the synchronizing step
the contents on A's side don't change, while those on B's side might.

I'm trying to do this using Session.merge, which works if the row
doesn't exist yet in A, or does but hasn't changed in B. If it has
changed in B, I get a ConcurrentModificationError when the merge is
flushed.
can't reproduce in 0.5.6 nor in 0.6.3, so a full test script that 
reproduces will be needed.  Alternatively, you might want to look at 
your SQL output and see what primary key is attempting to be updated:


Thanks for the quick reply. I've looked at the SQL output of the last 
commit and it appears to match on the correct primary key. However, 
the Individual has a version_id_col defined in the mapper, and it's 
trying to match on the wrong value there, which seems to cause the 
update to fail. I'll try to reproduce it in a full script.


Raf


This one reproduces it for me:

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()
class A(Base):
__tablename__ = 'a'
id = Column(Integer, primary_key=True)
stamp = Column(Integer, default = 0)
__mapper_args__ = {'version_id_col' : stamp}
firstname = Column(String)

e1 = create_engine('sqlite://', echo=True)
e2 = create_engine('sqlite://', echo=True)

Base.metadata.create_all(e1)
Base.metadata.create_all(e2)

session_B = sessionmaker(e1)()
session_A = sessionmaker(e2)()

individual = A(firstname='foo')
session_B.add(individual)
session_B.commit()

#Suppose this individual doesn't yet exist in A
individual = session_B.query(A).one()
session_A.merge(individual)
#This will work and add the individual
session_A.commit()

individual.firstname = 'test'
session_B.commit()

individual = session_B.query(A).one()
session_A.merge(individual)
#This will throw the ConcurrentModificationError
session_A.commit()

--
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



RE: [sqlalchemy] Session.merge and multiple databases

2010-08-25 Thread King Simon-NFHD78
 -Original Message-
 From: sqlalchemy@googlegroups.com 
 [mailto:sqlalch...@googlegroups.com] On Behalf Of Raf Geens
 Sent: 25 August 2010 16:48
 To: sqlalchemy@googlegroups.com
 Subject: Re: [sqlalchemy] Session.merge and multiple databases
 
 
   On 25/08/2010 17:15, Michael Bayer wrote:
  On Aug 25, 2010, at 10:50 AM, Raf Geens wrote:
 
  Hi,
 
  I have a sqlite database A and a MySQL database B which 
 share the same
  schema, where I want to synchronize the contents of 
 certain tables in
  A with those in B at certain times. Except for the 
 synchronizing step
  the contents on A's side don't change, while those on B's 
 side might.
 
  I'm trying to do this using Session.merge, which works if the row
  doesn't exist yet in A, or does but hasn't changed in B. If it has
  changed in B, I get a ConcurrentModificationError when the merge is
  flushed.
  can't reproduce in 0.5.6 nor in 0.6.3, so a full test 
 script that reproduces will be needed.  Alternatively, you 
 might want to look at your SQL output and see what primary 
 key is attempting to be updated:
 
 Thanks for the quick reply. I've looked at the SQL output of the last 
 commit and it appears to match on the correct primary key. 
 However, the 
 Individual has a version_id_col defined in the mapper, and 
 it's trying 
 to match on the wrong value there, which seems to cause the update to 
 fail. I'll try to reproduce it in a full script.
 
 Raf

The version_id_col is likely not to work - the whole point of the column
is that SA adds the current version to the WHERE clause, and then checks
to see if any rows were updated. If they were, the object was still at
the same version that SA loaded from the database. If no rows were
updated, it assumes it was because someone else modified the object and
incremented the version number (hence the ConcurrentModificationError).

SA increments the version number every time a change to the object is
flushed to the database. So when your object is modified in B, the
version number no longer matches the version in A and no rows match the
criteria.

I don't know how you fix this if you want to continue using the
version_id_col feature - is there any chance that you could do without
it (perhaps by implementing similar functionality in a SessionExtension
which only gets attached to the primary session)?

Simon

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



Re: [sqlalchemy] Session.merge and multiple databases

2010-08-25 Thread Raf Geens

 On 25/08/2010 18:03, King Simon-NFHD78 wrote:

-Original Message-
From: sqlalchemy@googlegroups.com
[mailto:sqlalch...@googlegroups.com] On Behalf Of Raf Geens
Sent: 25 August 2010 16:48
To: sqlalchemy@googlegroups.com
Subject: Re: [sqlalchemy] Session.merge and multiple databases


   On 25/08/2010 17:15, Michael Bayer wrote:

On Aug 25, 2010, at 10:50 AM, Raf Geens wrote:


Hi,

I have a sqlite database A and a MySQL database B which

share the same

schema, where I want to synchronize the contents of

certain tables in

A with those in B at certain times. Except for the

synchronizing step

the contents on A's side don't change, while those on B's

side might.

I'm trying to do this using Session.merge, which works if the row
doesn't exist yet in A, or does but hasn't changed in B. If it has
changed in B, I get a ConcurrentModificationError when the merge is
flushed.

can't reproduce in 0.5.6 nor in 0.6.3, so a full test

script that reproduces will be needed.  Alternatively, you
might want to look at your SQL output and see what primary
key is attempting to be updated:
Thanks for the quick reply. I've looked at the SQL output of the last
commit and it appears to match on the correct primary key.
However, the
Individual has a version_id_col defined in the mapper, and
it's trying
to match on the wrong value there, which seems to cause the update to
fail. I'll try to reproduce it in a full script.

Raf

The version_id_col is likely not to work - the whole point of the column
is that SA adds the current version to the WHERE clause, and then checks
to see if any rows were updated. If they were, the object was still at
the same version that SA loaded from the database. If no rows were
updated, it assumes it was because someone else modified the object and
incremented the version number (hence the ConcurrentModificationError).

SA increments the version number every time a change to the object is
flushed to the database. So when your object is modified in B, the
version number no longer matches the version in A and no rows match the
criteria.

I don't know how you fix this if you want to continue using the
version_id_col feature - is there any chance that you could do without
it (perhaps by implementing similar functionality in a SessionExtension
which only gets attached to the primary session)?

Simon


I'll see if I can do without it. Thanks for the clarification.

Raf

--
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.