2011-10-25 15 views
25

Estoy tratando de eliminar algunas filas secundarias utilizando una consulta filtrada sin resultado:sqlalchemy borrar subconsulta

sl = DBSession.query(Puesto.id).filter(Puesto.locales_id == id).subquery() 
DBSession.query(Servicio).filter(Servicio.puestos_id.in_(sl)).delete() 

estoy recibiendo InvalidRequestError: Could not evaluate current criteria in Python. Specify 'fetch' or False for the synchronize_session parameter. como un error.

completo seguimiento de la pila:

Traceback (most recent call last): 
    File "/usr/src/tg2env/ceaf/ceaf/controllers/root.py", line 1673, in delete_local 
    DBSession.query(Servicio).filter(Servicio.puestos_id.in_(sl)).delete() 
    File "/usr/src/tg2env/lib/python2.4/site-packages/SQLAlchemy-0.6.6-py2.4.egg/sqlalchemy/orm/query.py", line 2126, in delete 
    raise sa_exc.InvalidRequestError(
InvalidRequestError: Could not evaluate current criteria in Python. Specify 'fetch' or False for the synchronize_session parameter. 

no estoy capaz de encontrar dónde está el problema ...

Alguna idea?

Saludos

Respuesta

53

Después de mirar en la fuente donde se produce su excepción Recomiendo probar esto:

sl = DBSession.query(Puesto.id).filter(Puesto.locales_id == id).subquery() 
DBSession.query(Servicio).filter(Servicio.puestos_id.in_(sl)) \ 
.delete(synchronize_session='fetch') 

Véase el documentation of the delete method por lo que esto significa. Pasar el argumento fetch básicamente ejecutará la consulta dos veces, una como selección y una como eliminación.

Si no se desea ejecutar dos consultas, pasar synchronize_session=False lugar y luego llamar session.expire_all() inmediatamente después de la eliminación de avoid having inconsistent state dentro de la tienda MetaData.

+0

El primer enfoque funciona muy bien. ¿Por qué ahora trabajando con synchronize_session = 'evaluate'? – LooPer

+1

Como la eliminación utiliza 'in_' con una subconsulta, es necesaria una consulta' select' para que 'MetaData' decida cuál de sus objetos en memoria caducará. Pasar esta opción le da permiso para hacer eso. Hacer esto sin condiciones pondría en riesgo el bajo rendimiento en ciertas situaciones. – wberry

+2

Este documento también dice que si nos comprometemos de inmediato, no necesitamos llamar a session.expire_all(), con autocommit = False. – giga