<p dir="auto"><strong>Migrated issue, originally created by RobS (<a href="https://github.com/phro">@phro</a>)</strong></p>
<p dir="auto">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.</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="$ cat repro.sql 
CREATE TABLE &quot;users&quot; (&quot;id&quot; integer not null primary key autoincrement not null, &quot;slug&quot; varchar(150) not null, &quot;email&quot; varchar(254) not null);
CREATE UNIQUE INDEX users_email_unique on &quot;users&quot; (&quot;email&quot;);
CREATE TABLE &quot;refreshtokens&quot; (&quot;id&quot; integer not null primary key autoincrement, &quot;user_id&quot; integer not null, foreign key(&quot;user_id&quot;) references &quot;users&quot;(&quot;id&quot;));
CREATE UNIQUE INDEX users_slug_unique on &quot;users&quot; (&quot;slug&quot;);

$ sqlite3 repro.db &quot;.read repro.sql&quot;

$ 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(&quot;sqlite:///repro.db&quot;)
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=&lt;users&gt;, nullable=False), unique=True), Index('users_email_unique', Column('email', VARCHAR(length=254), table=&lt;users&gt;, nullable=False), unique=True), Index('users_email_unique', Column('email', VARCHAR(length=254), table=&lt;users&gt;, nullable=False), unique=True), Index('users_slug_unique', Column('slug', VARCHAR(length=150), table=&lt;users&gt;, 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"><pre class="notranslate"><code class="notranslate">$ 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=&lt;users&gt;, nullable=False), unique=True), Index('users_email_unique', Column('email', VARCHAR(length=254), table=&lt;users&gt;, nullable=False), unique=True), Index('users_email_unique', Column('email', VARCHAR(length=254), table=&lt;users&gt;, nullable=False), unique=True), Index('users_slug_unique', Column('slug', VARCHAR(length=150), table=&lt;users&gt;, 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
</code></pre></div>
<p dir="auto"><strong>Migrated issue, originally created by Marek Derňár (<a href="https://github.com/marderko">@marderko</a>)</strong></p>
<p dir="auto">Founded bug in "Transactions and Connection Management" documentation <a href="http://docs.sqlalchemy.org/en/latest/orm/session_transaction.html" rel="nofollow">http://docs.sqlalchemy.org/en/latest/orm/session_transaction.html</a> section "Supporting Tests with Rollbacks". There is:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="# then each time that SAVEPOINT ends, reopen it
@event.listens_for(self.session, &quot;after_transaction_end&quot;)
    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()"><pre class="notranslate"><code class="notranslate"># 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()
</code></pre></div>
<p dir="auto">I think the if condition is not correct and the right condition is:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="if transaction.nested and not session.transaction.nested:"><pre class="notranslate"><code class="notranslate">if transaction.nested and not session.transaction.nested:
</code></pre></div>
<p dir="auto">Explanation:</p>
<p dir="auto">There are constructed some transaction path (or tree) which have <code class="notranslate">session.transaction</code> in the end (tree leaf) and <code class="notranslate">session.transaction._parent._parent....._parent</code> in the start (tree root) and variable transaction from <code class="notranslate">restart_savepoint</code> 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 <code class="notranslate">session.begin_nested()</code> begins nested transaction in the end - so I change the condition also for the path end.</p>
<p dir="auto">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 &gt; 919 because of maximal recursion depth.<br>
After condition change it is really quickly and no fail in any test.</p>
<hr>
<p dir="auto">Attachments: <a href="../wiki/imported_issue_attachments/4297/savepoint_fail.zip">savepoint_fail.zip</a></p>