SQL Expression Language
=======================
+.. _error_l7de:
+
+Compiler StrSQLCompiler can't render element of type <element type>
+-------------------------------------------------------------------
+
+This error usually occurs when attempting to stringify a SQL expression
+construct that includes elements which are not part of the default compilation;
+in this case, the error will be against the :class:`.StrSQLCompiler` class.
+In less common cases, it can also occur when the wrong kind of SQL expression
+is used with a particular type of database backend; in those cases, other
+kinds of SQL compiler classes will be named, such as ``SQLCompiler`` or
+``sqlalchemy.dialects.postgresql.PGCompiler``. The guidance below is
+more specific to the "stringification" use case but describes the general
+background as well.
+
+Normally, a Core SQL construct or ORM :class:`.Query` object can be stringified
+directly, such as when we use ``print()``::
+
+ >>> from sqlalchemy import column
+ >>> print(column('x') == 5)
+ x = :x_1
+
+When the above SQL expression is stringified, the :class:`.StrSQLCompiler`
+compiler class is used, which is a special statement compiler that is invoked
+when a construct is stringified without any dialect-specific information.
+
+However, there are many constructs that are specific to some particular kind
+of database dialect, for which the :class:`.StrSQLCompiler` doesn't know how
+to turn into a string, such as the PostgreSQL
+`"insert on conflict" <postgresql_insert_on_conflict>`_ construct::
+
+ >>> from sqlalchemy.dialects.postgresql import insert
+ >>> from sqlalchemy import table, column
+ >>> my_table = table('my_table', column('x'), column('y'))
+ >>> insert_stmt = insert(my_table).values(x='foo')
+ >>> insert_stmt = insert_stmt.on_conflict_do_nothing(
+ ... index_elements=['y']
+ ... )
+ >>> print(insert_stmt)
+ Traceback (most recent call last):
+
+ ...
+
+ sqlalchemy.exc.UnsupportedCompilationError:
+ Compiler <sqlalchemy.sql.compiler.StrSQLCompiler object at 0x7f04fc17e320>
+ can't render element of type
+ <class 'sqlalchemy.dialects.postgresql.dml.OnConflictDoNothing'>
+
+In order to stringify constructs that are specific to particular backend,
+the :meth:`.ClauseElement.compile` method must be used, passing either an
+:class:`.Engine` or a :class:`.Dialect` object which will invoke the correct
+compiler. Below we use a PostgreSQL dialect::
+
+ >>> from sqlalchemy.dialects import postgresql
+ >>> print(insert_stmt.compile(dialect=postgresql.dialect()))
+ INSERT INTO my_table (x) VALUES (%(x)s) ON CONFLICT (y) DO NOTHING
+
+For an ORM :class:`.Query` object, the statement can be accessed using the
+:attr:`~.orm.query.Query.statement` accessor::
+
+ statement = query.statement
+ print(statement.compile(dialect=postgresql.dialect()))
+
+See the FAQ link below for additional detail on direct stringification /
+compilation of SQL elements.
+
+.. seealso::
+
+ :ref:`faq_sql_expression_string`
+
+
TypeError: <operator> not supported between instances of 'ColumnProperty' and <something>
-----------------------------------------------------------------------------------------
How do I render SQL expressions as strings, possibly with bound parameters inlined?
------------------------------------------------------------------------------------
-The "stringification" of a SQLAlchemy statement or Query in the vast majority
-of cases is as simple as::
-
- 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))
-
-or without an :class:`.Engine`::
+The "stringification" of a SQLAlchemy Core statement object or
+expression fragment, as well as that of an ORM :class:`.Query` object,
+in the majority of simple cases is as simple as using
+the ``str()`` builtin function, as below when use it with the ``print``
+function (note the Python ``print`` function also calls ``str()`` automatically
+if we don't use it explicitly)::
+
+ >>> from sqlalchemy import table, column, select
+ >>> t = table('my_table', column('x'))
+ >>> statement = select([t])
+ >>> print(str(statement))
+ SELECT my_table.x
+ FROM my_table
+
+The ``str()`` builtin, or an equivalent, can be invoked on ORM
+:class:`.Query` object as well as any statement such as that of
+:func:`.select`, :func:`.insert` etc. and also any expression fragment, such
+as::
+
+ >>> from sqlalchemy import column
+ >>> print(column('x') == 'some value')
+ x = :x_1
+
+Stringifying for Specific Databases
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A complication arises when the statement or fragment we are stringifying
+contains elements that have a database-specific string format, or when it
+contains elements that are only available within a certain kind of database.
+In these cases, we might get a stringified statement that is not in the correct
+syntax for the database we are targeting, or the operation may raise a
+:class:`.UnsupportedCompilationError` exception. In these cases, it is
+necessary that we stringify the statement using the
+:meth:`.ClauseElement.compile` method, while passing along an :class:`.Engine`
+or :class:`.Dialect` object that represents the target database. Such as
+below, if we have a MySQL database engine, we can stringify a statement in
+terms of the MySQL dialect::
+
+ from sqlalchemy import create_engine
+
+ engine = create_engine("mysql+pymysql://scott:tiger@localhost/test")
+ print(statement.compile(engine))
+
+More directly, without building up an :class:`.Engine` object we can
+instantiate a :class:`.Dialect` object directly, as below where we
+use a PostgreSQL dialect::
from sqlalchemy.dialects import postgresql
print(statement.compile(dialect=postgresql.dialect()))
statement = query.statement
print(statement.compile(someengine))
+Rendering Bound Parameters Inline
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. warning:: **Never** use this technique with string content received from
+ untrusted input, such as from web forms or other user-input applications.
+ SQLAlchemy's facilities to coerce Python values into direct SQL string
+ values are **not secure against untrusted input and do not validate the type
+ of data being passed**. Always use bound parameters when programmatically
+ invoking non-DDL SQL statements against a relational database.
+
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.
SQLAlchemy normally does not stringify bound parameters, as this is handled
s = select([t]).where(t.c.x == 5)
- print(s.compile(compile_kwargs={"literal_binds": True}))
+ print(s.compile(compile_kwargs={"literal_binds": True})) # **do not use** with untrusted input!!!
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`