Skip to content

Query Plan SQL construct

Michael Bayer edited this page Nov 18, 2024 · 5 revisions

This example illustrates how to implement PostgreSQL's EXPLAIN and EXPLAIN ANALYZE around SQLAlchemy Core statement objects, using a construct that can be executed like any other statement to provide the results of a query plan. Syntaxes for other databases can be added as well.

Examples for 1.4 and 1.3 are shown below. Note the 1.4 interface for creating a custom SQL object might be simplified a bit soon.

"""EXPLAIN any query.

Includes PostgreSQL EXPLAIN syntax.

SQLAlchemy 1.4 / 2.0 version.


"""
from sqlalchemy import Column
from sqlalchemy import create_engine
from sqlalchemy import Integer
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql.expression import ClauseElement
from sqlalchemy.sql.expression import Executable


class explain(Executable, ClauseElement):
    inherit_cache = False

    def __init__(self, stmt, analyze=False):
        self.statement = stmt
        self.analyze = analyze


@compiles(explain, "postgresql")
def pg_explain(element, compiler, **kw):
    text = "EXPLAIN "
    if element.analyze:
        text += "ANALYZE "
    text += compiler.process(element.statement, **kw)

    return text


if __name__ == "__main__":
    from sqlalchemy.orm import aliased
    from sqlalchemy.orm import declarative_base
    from sqlalchemy.orm import Session
    from sqlalchemy import select

    Base = declarative_base()

    class Foo(Base):
        __tablename__ = "foo"
        id = Column(Integer, primary_key=True)

    engine = create_engine(
        "postgresql://scott:tiger@localhost/test", echo=True
    )

    Base.metadata.create_all(engine)

    with Session(engine) as sess:

        falias = aliased(Foo)
        q = select(Foo).where(Foo.id > 5).join(falias, Foo.id == falias.id)

        print(sess.execute(explain(q)).fetchall())
"""EXPLAIN any query.

Includes PostgreSQL EXPLAIN syntax.

SQLAlchemy 1.3 and prior version.


"""

from sqlalchemy import Column
from sqlalchemy import create_engine
from sqlalchemy import Integer
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql.expression import _literal_as_text
from sqlalchemy.sql.expression import ClauseElement
from sqlalchemy.sql.expression import Executable


class explain(Executable, ClauseElement):
    def __init__(self, stmt, analyze=False):
        self.statement = _literal_as_text(stmt)
        self.analyze = analyze


@compiles(explain, "postgresql")
def pg_explain(element, compiler, **kw):
    text = "EXPLAIN "
    if element.analyze:
        text += "ANALYZE "
    text += compiler.process(element.statement, **kw)

    return text


if __name__ == "__main__":
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.orm import Session
    from sqlalchemy.orm import aliased

    Base = declarative_base()

    class Foo(Base):
        __tablename__ = "foo"
        id = Column(Integer, primary_key=True)

    engine = create_engine(
        "postgresql://scott:tiger@localhost/test", echo=True
    )

    Base.metadata.create_all(engine)

    sess = Session(engine)

    falias = aliased(Foo)
    q = sess.query(Foo).filter(Foo.id > 5).join(falias, Foo.id == falias.id)

    print(sess.execute(explain(q)).fetchall())
Clone this wiki locally
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy