2012-04-14 13 views
8

Questo asserisce sempre passare o no? In altre parole, SQLAlchemy salva l'ordine (durante la generazione di query INSERT) quando si aggiungono nuovi oggetti alla sessione?SQLAlchemy salva l'ordine nell'aggiunta di oggetti alla sessione?

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) 

Nessuno, in produzione sto utilizzando postgresql, sqlite è per il test.

+1

Non riesco a trovare il codice in sqlalchemy che fa sì che questo sia così (il suo 'dict's e' set's in molti posti) né posso produrre un controesempio convincente (a corto della non-monotonicità nella sequenza), e quindi +1 – SingleNegationElimination

risposta

-2

No, li fa quando si commette, non quando si aggiunge.

+0

Sapevo che le query vengono inviate a db in flush() o commit(). Ma immagino che sqlalchemy generi query INSERT con l'ordine dei comandi session.add(). (Ho provato con la classe Entity e postgres di cui sopra) –

+0

Sì, genera query di inserimento, ma l'id (chiave primaria) potrebbe essere determinato dal db, poiché potrebbe esserci un trigger che viene eseguito su insert che aumenta la sequenza nr e così via . – rapadura

+1

Il richiedente originale si chiede se le istruzioni INSERT siano o meno emesse, al momento del commit, nell'ordine in cui sono state aggiunte. In aumento, perché mi sto chiedendo lo stesso. // Modifica: capito! Risposta in un po '. – munchybunch

5

Dopo aver guardato un po 'alla fonte SQLAlchemy, sembra che add() record quando è stato inserito: https://github.com/zzzeek/sqlalchemy/blob/master/lib/sqlalchemy/orm/session.py#L1719

Il frammento rilevanti:

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) 

E questo è chiamato da Session.add =>self._save_or_update_state =>self._save_or_update_impl =>self._save_impl.

E 'quindi utilizzato in _sort_states durante il salvataggio: https://github.com/zzzeek/sqlalchemy/blob/master/lib/sqlalchemy/orm/persistence.py#L859

Purtroppo, questo è solo a livello di implementazione di prova. Non ho trovato nulla nella documentazione che lo garantisce ...

Aggiornamento: allora ho guardato un po 'di più in questo, si scopre c'è un concetto chiamato unità di lavoro in SQLAlchemy che definisce in qualche modo l'ordine durante uno svuotamento: http://www.aosabook.org/en/sqlalchemy.html (cerca Unità di lavoro).

All'interno della stessa classe, l'ordine è effettivamente determinato dall'ordine con cui è stato chiamato add. Tuttavia, è possibile visualizzare diversi ordini negli INSERT tra classi diverse. Se si aggiunge oggetto a di tipo A e successivamente vengono aggiunti oggetto b di tipo B, ma a risulta avere una chiave esterna per b, vedrete un inserto per b prima della INSERT per a.

+0

Questa è la risposta giusta – zzzeek

Problemi correlati