Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
403 views
in Technique[技术] by (71.8m points)

python - Does SQLAlchemy save order when adding objects to session?

Does this assert always pass or not? In other words, does SQLAlchemy save the order (in generating INSERT queries) when adding new objects to session?

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)

None, in production I'm using postgresql, sqlite is for testing.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

After looking a bit at the SQLAlchemy source, it looks like add() records when it was inserted: https://github.com/zzzeek/sqlalchemy/blob/master/lib/sqlalchemy/orm/session.py#L1719

The relevant snippet:

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)

And this is called from Session.add => self._save_or_update_state => self._save_or_update_impl => self._save_impl.

It's then used in _sort_states when saving: https://github.com/zzzeek/sqlalchemy/blob/master/lib/sqlalchemy/orm/persistence.py#L859

Unfortunately, this is only implementation-level proof. I couldn't find anything in the documentation that guarantees it...

Update: I've since looked a bit more into this, it turns out there's a concept called Unit of Work in SQLAlchemy that somewhat defines the order during a flush: http://www.aosabook.org/en/sqlalchemy.html (search for Unit of Work).

Within the same class, the order is indeed determined by the order that add was called. However, you may see different orderings in the INSERTs between different classes. If you add object a of type A and later add object b of type B, but a turns out to have a foreign key to b, you'll see an INSERT for b before the INSERT for a.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...