This issue was introduced in version 2.0.2`.
from __future__ import annotations
from sqlalchemy import create_engine, select, insert, literal
from sqlalchemy.orm import MappedAsDataclass, Mapped, mapped_column, DeclarativeBase, Session, column_property
engine = create_engine("sqlite:///:memory:", echo=True)
class Base(DeclarativeBase):
pass
class User(MappedAsDataclass, Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(init=False, primary_key=True)
name: Mapped[str] = mapped_column()
age: Mapped[int] = mapped_column()
is_adult: Mapped[int] = column_property(age >= 18, default=None)
Base.metadata.create_all(engine)
with Session(bind=engine) as session:
stmt = select(
literal(1).label("id"),
literal("John").label("name"),
literal(30).label("age"),
)
insert_stmt = (
insert(User)
.from_select(["id", "name", "age"], stmt)
.returning(User)
)
result = session.scalars(insert_stmt)
Traceback (most recent call last):
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/sql/elements.py", line 1456, in __getattr__
return getattr(self.comparator, key)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Comparator' object has no attribute 'name'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/main.py", line 39, in <module>
result = session.scalars(insert_stmt)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/orm/session.py", line 2339, in scalars
return self._execute_internal(
^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/orm/session.py", line 2124, in _execute_internal
result: Result[Any] = compile_state_cls.orm_execute_statement(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/orm/bulk_persistence.py", line 1232, in orm_execute_statement
return cls._return_orm_returning(
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/orm/bulk_persistence.py", line 541, in _return_orm_returning
return loading.instances(result, querycontext)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/orm/loading.py", line 131, in instances
with util.safe_reraise():
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/util/langhelpers.py", line 147, in __exit__
raise exc_value.with_traceback(exc_tb)
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/orm/loading.py", line 112, in instances
*[
^
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/orm/loading.py", line 113, in <listcomp>
query_entity.row_processor(context, cursor)
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/orm/context.py", line 2589, in row_processor
_instance = loading._instance_processor(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/orm/loading.py", line 931, in _instance_processor
prop.create_row_processor(
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/orm/interfaces.py", line 1038, in create_row_processor
strat.create_row_processor(
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/orm/strategies.py", line 276, in create_row_processor
col = adapter.columns[col]
~~~~~~~~~~~~~~~^^^^^
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/util/_collections.py", line 361, in __missing__
self[key] = val = self.creator(self.weakself(), key)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/sql/util.py", line 1389, in _locate_col
c = ClauseAdapter.traverse(self, col)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/sql/visitors.py", line 811, in traverse
return replacement_traverse(obj, self.__traverse_options__, replace)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/sql/visitors.py", line 1177, in replacement_traverse
obj = clone(
^^^^^^
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/sql/visitors.py", line 1173, in clone
newelem._copy_internals(clone=clone, **kw)
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/sql/elements.py", line 4562, in _copy_internals
self._element = clone(self._element, **kw)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/sql/visitors.py", line 1156, in clone
newelem = replace(elem)
^^^^^^^^^^^^^
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/sql/visitors.py", line 805, in replace
e = cast(ReplacingExternalTraversal, v).replace(element)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/sql/util.py", line 1211, in replace
return self._corresponding_column( # type: ignore
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/sql/util.py", line 1139, in _corresponding_column
newcol = self.selectable.exported_columns.get(col.name)
^^^^^^^^
File "/Users/yuriikarabas/PycharmProjects/sqlalchemy2-sandbox/venv/lib/python3.11/site-packages/sqlalchemy/sql/elements.py", line 1458, in __getattr__
raise AttributeError(
AttributeError: Neither 'BinaryExpression' object nor 'Comparator' object has an attribute 'name'
Describe the bug
column_propertybreaks ORM insert from select with returning model.This issue was introduced in version 2.0.2`.
Optional link from https://docs.sqlalchemy.org which documents the behavior that is expected
No response
SQLAlchemy Version in Use
2.0.3
DBAPI (i.e. the database driver)
pysqlite
Database Vendor and Major Version
SQLite
Python Version
3.11
Operating system
OSX
To Reproduce
Error
Additional context
No response