self.composite_class = argument
if is_dataclass(self.composite_class):
- self._setup_for_dataclass(registry, cls, originating_module, key)
+ self._setup_for_dataclass(
+ decl_scan, registry, cls, originating_module, key
+ )
else:
for attr in self.attrs:
if (
@util.preload_module("sqlalchemy.orm.decl_base")
def _setup_for_dataclass(
self,
+ decl_scan: _ClassScanMapperConfig,
registry: _RegistryType,
cls: Type[Any],
originating_module: Optional[str],
if isinstance(attr, MappedColumn):
attr.declarative_scan_for_composite(
+ decl_scan,
registry,
cls,
originating_module,
# Column will be merged into it in _init_column_for_annotation().
return MappedColumn()
- def declarative_scan(
+ def _adjust_for_existing_column(
self,
decl_scan: _ClassScanMapperConfig,
- registry: _RegistryType,
- cls: Type[Any],
- originating_module: Optional[str],
key: str,
- mapped_container: Optional[Type[Mapped[Any]]],
- annotation: Optional[_AnnotationScanType],
- extracted_mapped_annotation: Optional[_AnnotationScanType],
- is_dataclass_field: bool,
- ) -> None:
- column = self.column
-
+ given_column: Column[_T],
+ ) -> Column[_T]:
if (
self._use_existing_column
and decl_scan.inherits
)
supercls_mapper = class_mapper(decl_scan.inherits, False)
- colname = column.name if column.name is not None else key
- column = self.column = supercls_mapper.local_table.c.get( # type: ignore[assignment] # noqa: E501
- colname, column
+ colname = (
+ given_column.name if given_column.name is not None else key
)
+ given_column = supercls_mapper.local_table.c.get( # type: ignore[assignment] # noqa: E501
+ colname, given_column
+ )
+ return given_column
+
+ def declarative_scan(
+ self,
+ decl_scan: _ClassScanMapperConfig,
+ registry: _RegistryType,
+ cls: Type[Any],
+ originating_module: Optional[str],
+ key: str,
+ mapped_container: Optional[Type[Mapped[Any]]],
+ annotation: Optional[_AnnotationScanType],
+ extracted_mapped_annotation: Optional[_AnnotationScanType],
+ is_dataclass_field: bool,
+ ) -> None:
+ column = self.column
+
+ column = self.column = self._adjust_for_existing_column(
+ decl_scan, key, self.column
+ )
if column.key is None:
column.key = key
self._init_column_for_annotation(
cls,
+ decl_scan,
+ key,
registry,
extracted_mapped_annotation,
originating_module,
@util.preload_module("sqlalchemy.orm.decl_base")
def declarative_scan_for_composite(
self,
+ decl_scan: _ClassScanMapperConfig,
registry: _RegistryType,
cls: Type[Any],
originating_module: Optional[str],
decl_base = util.preloaded.orm_decl_base
decl_base._undefer_column_name(param_name, self.column)
self._init_column_for_annotation(
- cls, registry, param_annotation, originating_module
+ cls, decl_scan, key, registry, param_annotation, originating_module
)
def _init_column_for_annotation(
self,
cls: Type[Any],
+ decl_scan: _ClassScanMapperConfig,
+ key: str,
registry: _RegistryType,
argument: _AnnotationScanType,
originating_module: Optional[str],
if use_args_from is not None:
+ self.column = use_args_from._adjust_for_existing_column(
+ decl_scan, key, self.column
+ )
+
if (
self._has_insert_default
or self._attribute_options.dataclasses_default
else:
is_(getattr(Element.__table__.c.data, paramname), override_value)
+ def test_use_existing_column_from_pep_593(self, decl_base):
+ """test #12787"""
+
+ global Label
+ Label = Annotated[
+ str, mapped_column(String(20), use_existing_column=True)
+ ]
+
+ class A(decl_base):
+ __tablename__ = "table_a"
+
+ id: Mapped[int] = mapped_column(primary_key=True)
+ discriminator: Mapped[int]
+
+ __mapper_args__ = {
+ "polymorphic_on": "discriminator",
+ "polymorphic_abstract": True,
+ }
+
+ class A_1(A):
+ label: Mapped[Label]
+
+ __mapper_args__ = {"polymorphic_identity": 1}
+
+ class A_2(A):
+ label: Mapped[Label]
+
+ __mapper_args__ = {"polymorphic_identity": 2}
+
+ is_(A_1.label.property.columns[0], A_2.label.property.columns[0])
+
+ eq_(A_1.label.property.columns[0].table, A.__table__)
+ eq_(A_2.label.property.columns[0].table, A.__table__)
+
@testing.variation(
"union",
[
else:
is_(getattr(Element.__table__.c.data, paramname), override_value)
+ def test_use_existing_column_from_pep_593(self, decl_base):
+ """test #12787"""
+
+ # anno only: global Label
+ Label = Annotated[
+ str, mapped_column(String(20), use_existing_column=True)
+ ]
+
+ class A(decl_base):
+ __tablename__ = "table_a"
+
+ id: Mapped[int] = mapped_column(primary_key=True)
+ discriminator: Mapped[int]
+
+ __mapper_args__ = {
+ "polymorphic_on": "discriminator",
+ "polymorphic_abstract": True,
+ }
+
+ class A_1(A):
+ label: Mapped[Label]
+
+ __mapper_args__ = {"polymorphic_identity": 1}
+
+ class A_2(A):
+ label: Mapped[Label]
+
+ __mapper_args__ = {"polymorphic_identity": 2}
+
+ is_(A_1.label.property.columns[0], A_2.label.property.columns[0])
+
+ eq_(A_1.label.property.columns[0].table, A.__table__)
+ eq_(A_2.label.property.columns[0].table, A.__table__)
+
@testing.variation(
"union",
[