mapper on a temporary class

35 views
Skip to first unread message

Kent

unread,
Jan 26, 2021, 3:16:33 PM1/26/21
to sqlalchemy
Question: if I add a mapper to a class that is only needed temporarily, does using the mapper compile it along side my "normal" mappers such that I'll leak memory when I mean for the class to be garbage collected?

Put another way, can I add a mapper to a class that doesn't influence my "main mappers" and gets thrown away when the class is thrown away or is that not possible?

Thanks in advance,
Kent

Mike Bayer

unread,
Jan 26, 2021, 6:18:20 PM1/26/21
to noreply-spamdigest via sqlalchemy


On Tue, Jan 26, 2021, at 3:16 PM, Kent wrote:
Question: if I add a mapper to a class that is only needed temporarily, does using the mapper compile it along side my "normal" mappers such that I'll leak memory when I mean for the class to be garbage collected?

Put another way, can I add a mapper to a class that doesn't influence my "main mappers" and gets thrown away when the class is thrown away or is that not possible?

Assuming the class already has a mapper, and this is an additional mapper that maps the class in a different way, this feature is called a "non-primary mapper" and requires that you pass the non_primary=True flag.    If you are using non-primary mappers, then yes they get garbage collected.

This is also a deprecated feature that won't be in SQLAlchemy 2.0.    The only use case we can identify for "non-primary mappers" is when you want to create a relationship() to one, and for that use case we now support the "Relationship to AliasedClass" pattern.

For anything else involving retrieving a class from an alternate selectable of some kind, you should be able to use AliasedClass for, e.g. sqlalchemy.orm.aliased(), so I would recommend using that instead unless you are on a very old version of SQLAlchemy.








Thanks in advance,
Kent


--
SQLAlchemy -
The Python SQL Toolkit and Object Relational Mapper
 
 
To post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description.
---
You received this message because you are subscribed to the Google Groups "sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+...@googlegroups.com.

Kent Bower

unread,
Jan 26, 2021, 7:31:35 PM1/26/21
to sqlal...@googlegroups.com
I should have given these details from the get-go:  the use case is a specialized select() (dynamically built) which would be extremely convenient to map relationships against for convenience in subquery loading, etc. So, the class would not already have a mapper.  Can I pass non_primary=True anyway, or won’t this work?


You received this message because you are subscribed to a topic in the Google Groups "sqlalchemy" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/sqlalchemy/IAqOQFpiB20/unsubscribe.
To unsubscribe from this group and all its topics, send an email to sqlalchemy+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/c8f7f84e-af90-450c-9289-ed84fc6996a9%40www.fastmail.com.

Mike Bayer

unread,
Jan 26, 2021, 8:17:26 PM1/26/21
to noreply-spamdigest via sqlalchemy


On Tue, Jan 26, 2021, at 7:31 PM, Kent Bower wrote:
I should have given these details from the get-go:  the use case is a specialized select() (dynamically built) which would be extremely convenient to map relationships against for convenience in subquery loading, etc. So, the class would not already have a mapper.  Can I pass non_primary=True anyway, or won’t this work?

You can use relationship loading with the aliased class approach too; the relationships that are on the class would just work against your altered select() statement.  Also I would recommend ditching subqueryloading in favor of selectinload() , which is better than subqueryload in pretty much every way.

if you want to make totally custom relatoinships to new classes that aren't on the class normally, and such and have different primaryjoin conditions and all that, and it's not possible to have these relationships at least as placeholders on the normal class, then it starts to look like you want to make a subclass and map to that with concrete=True.


Mike Bayer

unread,
Jan 26, 2021, 8:18:10 PM1/26/21
to noreply-spamdigest via sqlalchemy


On Tue, Jan 26, 2021, at 7:31 PM, Kent Bower wrote:
I should have given these details from the get-go:  the use case is a specialized select() (dynamically built) which would be extremely convenient to map relationships against for convenience in subquery loading, etc. So, the class would not already have a mapper.  Can I pass non_primary=True anyway, or won’t this work?

oh if the class doesn't have a mapper, then defintiely, just make ad-hoc subclasses of it and map to those.    vastly easier that way.



Kent Bower

unread,
Jan 26, 2021, 9:01:51 PM1/26/21
to sqlal...@googlegroups.com
Thanks a ton for your responses. 

Do all the normal columns of an aliased class need to match the ad-hoc select to which I map the alias?

oh if the class doesn't have a mapper, then defintiely, just make ad-hoc subclasses of it and map to those.    vastly easier that way.

Mapping to a subclass would be different from mapping directly to an ad-hoc class?  (Mostly I’m concerned whether the very act of adding a mapper to a class will keep the reference and prevent its garbage collection or in some other way modify the “main” mappers, especially if this is done via a thread. Like, would that modify the compiled mappers for the entire process... these are the things running through my head.)


Mike Bayer

unread,
Jan 27, 2021, 1:25:33 PM1/27/21
to noreply-spamdigest via sqlalchemy


On Tue, Jan 26, 2021, at 9:01 PM, Kent Bower wrote:
Thanks a ton for your responses. 

Do all the normal columns of an aliased class need to match the ad-hoc select to which I map the alias?

handwavy handwavy sort of yes, sort of no?    there needs to be a 1-1 correspondence of columns, yes, aliasedclass can't define additional attributes that arent there normally.  as to how they are lined up, there's an option to do it by name in the aliased() function adapt_on_names.  otherwise it's expected that your select() is derived from the Table objects that are originally mapped.



oh if the class doesn't have a mapper, then defintiely, just make ad-hoc subclasses of it and map to those.    vastly easier that way.

Mapping to a subclass would be different from mapping directly to an ad-hoc class?

if the class itself is ad-hoc, then you're fine, you can make new classes with mappers all you want and they are GCed if you lose them (assuming no relationships involving long-lived classes with backrefs), yes.






 (Mostly I’m concerned whether the very act of adding a mapper to a class will keep the reference and prevent its garbage collection or in some other way modify the “main” mappers, especially if this is done via a thread. Like, would that modify the compiled mappers for the entire process... these are the things running through my head.)

the configure_mappers() function these days is threadsafe, it uses a mutex, so you are "good" there but there's a mutex involved if you are looking for high levels of concurrency.   if your ad-hoc classes are not subclasses of any long lived classes and if you are careful to limit relationships to only point to long lived classes and not have any backrefs, it should be OK.  I'd test it though :)    set up a weakref.ref() to your ad-hoc mapper objects and make sure those ref objects get their callback hook invoked.




Kent Bower

unread,
Jan 27, 2021, 2:49:37 PM1/27/21
to sqlal...@googlegroups.com
Excellent.  As always, thanks very much for your time and answers (let alone awesome software)!


Reply all
Reply to author
Forward
0 new messages