2012-04-14 1 views
8

Besteht diese Behauptung immer oder nicht? Mit anderen Worten, speichert SQLAlchemy die Reihenfolge (beim Generieren von INSERT-Abfragen) beim Hinzufügen neuer Objekte zur Sitzung?Speichert SQLAlchemy die Reihenfolge beim Hinzufügen von Objekten zur Sitzung?

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) 

Keine, in der Produktion verwende ich postgresql, sqlite ist zum Testen.

+1

Ich kann weder den Code in sqlalchemy finden, der dies verursacht (seine 'dict's und' set's an vielen Stellen), noch kann ich ein zwingendes Gegenbeispiel erzeugen (kurz der Nicht-Monotonie in der Sequenz), und so +1 – SingleNegationElimination

Antwort

-2

Nein, es tut sie, wenn Sie sich verpflichten, nicht wenn Sie hinzufügen.

+0

Ich wusste, dass Abfragen an db in flush() oder commit() gesendet werden. Aber ich schätze, dass sqlalchemy INSERT-Abfragen in der Reihenfolge der Befehle von session.add() generiert. (Ich testete mit der oben genannten Entity-Klasse und Postgres) –

+0

Ja erzeugt es einfügen Abfragen, aber die ID (Primärschlüssel) könnte durch die db bestimmt werden, da es einen Trigger, der auf Insert, die Sequenz nr und so weiter erhöht wird . – rapadura

+1

Der ursprüngliche Fragesteller fragt sich, ob die INSERT-Anweisungen beim Commit in der Reihenfolge ausgegeben werden, in der sie hinzugefügt wurden. Upvoted, weil ich das gleiche frage. // Edit: habe es herausgefunden! In ein bisschen antworten. – munchybunch

5

Nach einem wenig an der SQLAlchemy Quelle sucht, sieht es aus wie add() Aufzeichnungen, wenn sie eingeführt wurde: https://github.com/zzzeek/sqlalchemy/blob/master/lib/sqlalchemy/orm/session.py#L1719

Der entsprechende Code-Schnipsel:

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) 

Und das aus Session.add =>self._save_or_update_state = aufgerufen>self._save_or_update_impl =>self._save_impl.

Es ist dann in _sort_states verwendet beim Speichern: https://github.com/zzzeek/sqlalchemy/blob/master/lib/sqlalchemy/orm/persistence.py#L859

Leider ist dies nur umsetzungs Ebene Beweis. Ich konnte nichts in der Dokumentation, die es garantiert ...

aktualisieren: Ich habe da ein wenig mehr in diese sah, stellt sich heraus, es ist ein Konzept Unit of Work in SQLAlchemy aufgerufen, etwas definiert die Reihenfolge während einer Flush: http://www.aosabook.org/en/sqlalchemy.html (Suche nach Unit of Work).

Innerhalb derselben Klasse wird die Reihenfolge in der Tat durch die Reihenfolge bestimmt, die add aufgerufen wurde. Möglicherweise sehen Sie jedoch unterschiedliche Sortierungen in den INSERTs zwischen verschiedenen Klassen. Wenn Sie Objekt a vom Typ A hinzufügen und später Objekt hinzufügen b vom Typ B, aber a stellt sich heraus, einen Fremdschlüssel zu b haben, erhalten Sie eine INSERT für b vor dem INSERT für a sehen.

+0

Das ist die richtige Antwort – zzzeek