Issue 1:
Migrated issue, originally created by RobS (@phro)

I'm not really sure what's going on here but for this particular schema after reflection via the automapper the indexes are duplicated. If you remove anything from the table definitions the duplication goes away.

$ cat repro.sql
CREATE TABLE "users" ("id" integer not null primary key autoincrement not null, "slug" varchar(150) not null, "email" varchar(254) not null);
CREATE UNIQUE INDEX users_email_unique on "users" ("email");
CREATE TABLE "refreshtokens" ("id" integer not null primary key autoincrement, "user_id" integer not null, foreign key("user_id") references "users"("id"));
CREATE UNIQUE INDEX users_slug_unique on "users" ("slug");

$ sqlite3 repro.db ".read repro.sql"

$ cat repro.py
from sqlalchemy.ext.automap import automap_base
from sqlalchemy.orm import Session
from sqlalchemy import create_engine

Base = automap_base()
engine = create_engine("sqlite:///repro.db")
Base.prepare(engine, reflect=True)
users = Base.metadata.tables.get('users')
print(users.indexes)

$ python repro.py
set([Index('users_slug_unique', Column('slug', VARCHAR(length=150), table=<users>, nullable=False), unique=True), Index('users_email_unique', Column('email', VARCHAR(length=254), table=<users>, nullable=False), unique=True), Index('users_email_unique', Column('email', VARCHAR(length=254), table=<users>, nullable=False), unique=True), Index('users_slug_unique', Column('slug', VARCHAR(length=150), table=<users>, nullable=False), unique=True)])

$ pip freeze
PyMySQL==0.7.9
SQLAlchemy==1.1.4

$ python --version
Python 2.7.9

$ sqlite3 --version
3.8.7.1 2014-10-29 13:59:56 3b7b72c4685aa5cf5e675c2c47ebec10d9704221

Issue 2:
Migrated issue, originally created by Marek Derňár (@marderko)

Founded bug in "Transactions and Connection Management" documentation http://docs.sqlalchemy.org/en/latest/orm/session_transaction.html section "Supporting Tests with Rollbacks". There is:

# then each time that SAVEPOINT ends, reopen it
@event.listens_for(self.session, "after_transaction_end")
def restart_savepoint(session, transaction):
if transaction.nested and not transaction._parent.nested:
# ensure that state is expired the way
# session.commit() at the top level normally does
# (optional step)
session.expire_all()
session.begin_nested()

I think the if condition is not correct and the right condition is:

if transaction.nested and not session.transaction.nested:

Explanation:

There are constructed some transaction path (or tree) which have session.transaction in the end (tree leaf) and session.transaction._parent._parent....._parent in the start (tree root) and variable transaction from restart_savepoint is the start point (tree leaf). I think the second condition wants to restrict maximal length of path (or tree depth) to 2. But the condition is for path start and session.begin_nested() begins nested transaction in the end - so I change the condition also for the path end.

I attached failing example with two factories (second has first as subfactory) and simple parametrized test. It is really slow and it fails for tests number > 919 because of maximal recursion depth.

After condition change it is really quickly and no fail in any test.

Attachments: savepoint_fail.zip