The "stringification" of a SQLAlchemy statement or Query in the vast majority
of cases is as simple as::
- print str(statement)
+ print(str(statement))
this applies both to an ORM :class:`~.orm.query.Query` as well as any :func:`.select` or other
statement. Additionally, to get the statement as compiled to a
specific dialect or engine, if the statement itself is not already
bound to one you can pass this in to :meth:`.ClauseElement.compile`::
- print statement.compile(someengine)
+ print(statement.compile(someengine))
or without an :class:`.Engine`::
from sqlalchemy.dialects import postgresql
- print statement.compile(dialect=postgresql.dialect())
+ print(statement.compile(dialect=postgresql.dialect()))
When given an ORM :class:`~.orm.query.Query` object, in order to get at the
:meth:`.ClauseElement.compile`
accessor first::
statement = query.statement
- print statement.compile(someengine)
+ print(statement.compile(someengine))
The above forms will render the SQL statement as it is passed to the Python
:term:`DBAPI`, which includes that bound parameters are not rendered inline.
s = select([t]).where(t.c.x == 5)
- print s.compile(compile_kwargs={"literal_binds": True})
+ print(s.compile(compile_kwargs={"literal_binds": True}))
the above approach has the caveats that it is only supported for basic
types, such as ints and strings, and furthermore if a :func:`.bindparam`
without a pre-set value is used directly, it won't be able to
-stringify that either. Additionally, the ``compile_kwargs`` argument
-itself is only available as of SQLAlchemy 0.9; and there are slightly
-more verbose ways of getting ``literal_binds`` injected with 0.8.
+stringify that either.
-.. topic:: Applying compiler kw arguments prior to 0.9
+To support inline literal rendering for types not supported, implement
+a :class:`.TypeDecorator` for the target type which includes a
+:meth:`.TypeDecorator.process_literal_param` method::
- We can provide a fixed set of ``**kw`` by calling upon ``process()``
- directly::
+ from sqlalchemy import TypeDecorator, Integer
- compiled = s.compile()
- print compiled.process(s, literal_binds=True)
- Note that in this approach the statement is actually being stringified
- twice, hence using ``compile_kwargs`` in 0.9 should be preferred.
+ class MyFancyType(TypeDecorator):
+ impl = Integer
+ def process_literal_param(self, value, dialect):
+ return "my_fancy_formatting(%s)" % value
-If we want to skip using ``literal_binds`` altogether due to the above
-caveats, we can take the approach of replacing them out ahead of time
-with whatever we want::
+ from sqlalchemy import Table, Column, MetaData
- from sqlalchemy.sql import visitors, text
+ tab = Table('mytable', MetaData(), Column('x', MyFancyType()))
- def replace_bindparam(element):
- if hasattr(element, 'effective_value'):
- return text(str(element.effective_value))
-
- s = visitors.replacement_traverse(s, {}, replace_bindparam)
- print s
-
-Still another approach to injecting functionality where bound
-parameters are concerned is to use the :doc:`Compilation Extension
-API <core/compiler>`::
-
- from sqlalchemy.ext.compiler import compiles
- from sqlalchemy.sql.expression import BindParameter
-
- s = select([t]).where(t.c.x == 5)
+ print(
+ tab.select().where(tab.c.x > 5).compile(
+ compile_kwargs={"literal_binds": True})
+ )
- @compiles(BindParameter)
- def as_str(element, compiler, **kw):
- if 'binds_as_str' in kw:
- return str(element.effective_value)
- else:
- return compiler.visit_bindparam(element, **kw)
+producing output like::
- print s.compile(compile_kwargs={"binds_as_str": True})
+ SELECT mytable.x
+ FROM mytable
+ WHERE mytable.x > my_fancy_formatting(5)
-Above, we pass a self-defined flag ``binds_as_str`` through the compiler,
-which we then intercept within our custom render method for :class:`.BindParameter`.
Why does ``.col.in_([])`` Produce ``col != col``? Why not ``1=0``?
-------------------------------------------------------------------