2012-04-14 17 views
8

¿Esto siempre pasa o no? En otras palabras, ¿guarda SQLAlchemy el orden (al generar consultas INSERT) cuando agrega nuevos objetos a la sesión?¿SQLAlchemy guarda orden al agregar objetos a la sesión?

from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.orm.session import sessionmaker 
from sqlalchemy.engine import create_engine 
from sqlalchemy.types import Integer 
from sqlalchemy.schema import Column 

engine = create_engine('sqlite://') 
Base = declarative_base(engine) 
Session = sessionmaker(bind=engine) 
session = Session() 

class Entity(Base): 
    __tablename__ = 'entity' 
    id = Column(Integer(), primary_key=True) 
Entity.__table__.create(checkfirst=True) 


first = Entity() 
session.add(first) 

second = Entity() 
session.add(second) 

session.commit() 
assert second.id > first.id 
print(first.id, second.id) 

Ninguno, en la producción que estoy usando PostgreSQL, SQLite es para la prueba.

+1

No puedo encontrar el código en sqlalchemy que hace que esto sea así (es 'dict's y' set's en muchos lugares) ni puedo producir un contraejemplo convincente (excepto la falta de monotonicidad en la secuencia), y así +1 – SingleNegationElimination

Respuesta

-2

No, los hace cuando se compromete, no cuando se agrega.

+0

Sabía que las consultas se envían a db in flush() o commit(). Pero supongo que sqlalchemy genera consultas INSERT con el orden de los comandos session.add(). (Probé con la clase de entidad anterior y postgres) –

+0

Sí, genera consultas de inserción, pero el id (clave principal) podría ser determinado por el db, ya que podría haber un desencadenador que se ejecute en insert lo que aumenta la secuencia nr y así sucesivamente . – rapadura

+1

El asker original se pregunta si las declaraciones INSERT se emiten o no, al confirmarlas, en el orden en que se agregaron. Upvoted, porque me pregunto lo mismo. // Edit: ¡lo descubrí! Respondiendo en un momento. – munchybunch

5

Después de mirar un poco en la fuente SQLAlchemy, parece que add() registros cuando se insertó: https://github.com/zzzeek/sqlalchemy/blob/master/lib/sqlalchemy/orm/session.py#L1719

El fragmento relevante:

def _save_impl(self, state): 
    if state.key is not None: 
     raise sa_exc.InvalidRequestError(
      "Object '%s' already has an identity - it can't be registered " 
      "as pending" % state_str(state)) 

    self._before_attach(state) 
    if state not in self._new: 
     self._new[state] = state.obj() 
     state.insert_order = len(self._new) # THE INSERT ORDER IS SAVED! 
    self._attach(state) 

Y esto se llama desde Session.add =>self._save_or_update_state =>self._save_or_update_impl =>self._save_impl.

Se utiliza después en _sort_states al guardar: https://github.com/zzzeek/sqlalchemy/blob/master/lib/sqlalchemy/orm/persistence.py#L859

Por desgracia, esto es sólo una prueba de nivel de aplicación. No pude encontrar nada en la documentación que garantice que ...

actualización: Desde entonces, he mirado un poco más en esto, resulta que hay un concepto llamado unidad de trabajo en SQLAlchemy que de alguna manera define el orden durante una descarga: http://www.aosabook.org/en/sqlalchemy.html (busque Unidad de trabajo).

Dentro de la misma clase, la orden está de hecho determinada por el orden en que se llamó a add. Sin embargo, puede ver diferentes ordenamientos en los INSERT entre diferentes clases. Si se agrega objeto a de tipo A y posteriormente añade objeto b de tipo B, pero a resulta que tiene una clave externa a b, verá una inserción para b antes del INSERT para a.

+0

Esta es la respuesta correcta – zzzeek

Cuestiones relacionadas