--- /dev/null
+.. change::
+ :tags: bug, orm
+ :tickets: 8753
+
+ Improved "dictionary mode" for :meth:`_orm.Session.get` so that synonym
+ names which refer to primary key attribute names may be indicated in the
+ named dictionary.
dict(self.class_manager._all_sqla_attributes())
)
+ @HasMemoized.memoized_attribute
+ @util.preload_module("sqlalchemy.orm.descriptor_props")
+ def _pk_synonyms(self) -> Dict[str, str]:
+ """return a dictionary of {syn_attribute_name: pk_attr_name} for
+ all synonyms that refer to primary key columns
+
+ """
+ descriptor_props = util.preloaded.orm_descriptor_props
+
+ pk_keys = {prop.key for prop in self._identity_key_props}
+
+ return {
+ syn.key: syn.name
+ for k, syn in self._props.items()
+ if isinstance(syn, descriptor_props.SynonymProperty)
+ and syn.name in pk_keys
+ }
+
@HasMemoized.memoized_attribute
@util.preload_module("sqlalchemy.orm.descriptor_props")
def synonyms(self) -> util.ReadOnlyProperties[SynonymProperty[Any]]:
)
if is_dict:
+
+ pk_synonyms = mapper._pk_synonyms
+
+ if pk_synonyms:
+ correct_keys = set(pk_synonyms).intersection(
+ primary_key_identity
+ )
+
+ if correct_keys:
+ primary_key_identity = dict(primary_key_identity)
+ for k in correct_keys:
+ primary_key_identity[
+ pk_synonyms[k]
+ ] = primary_key_identity[k]
+
try:
primary_key_identity = list(
primary_key_identity[prop.key]
raise sa_exc.InvalidRequestError(
"Incorrect names of values in identifier to formulate "
"primary key for session.get(); primary key attribute "
- "names are %s"
+ "names are %s (synonym names are also accepted)"
% ",".join(
"'%s'" % prop.key
for prop in mapper._identity_key_props
u2 = s.get(User, 7)
assert u is not u2
+ def test_get_synonym_direct_name(self, decl_base):
+ """test #8753"""
+
+ class MyUser(decl_base):
+ __table__ = self.tables.users
+
+ syn_id = synonym("id")
+
+ s = fixture_session()
+ u = s.get(MyUser, {"syn_id": 7})
+ eq_(u.id, 7)
+
+ def test_get_synonym_indirect(self, decl_base):
+ """test #8753"""
+
+ class MyUser(decl_base):
+ __table__ = self.tables.users
+
+ uid = __table__.c.id
+ syn_id = synonym("uid")
+
+ s = fixture_session()
+ u = s.get(MyUser, {"syn_id": 7})
+ eq_(u.uid, 7)
+
def test_get_composite_pk_no_result(self):
CompositePk = self.classes.CompositePk