[sqlalchemy] matches_any: an extension to the Query object, and a HSTORE attribute access property

2014-01-07 Thread Philip Scott
Hi folks,

SQLAlchemy is at the heart of what we do at work (UK based hedge fund); so 
first of all a big thank you; I am not quite sure where we'd be without 
you. We would like to give back to the community as much as we can (I tried 
to get some of the developers on the company xmas present list this year 
but was too late.. cross your fingers for next year).

We have extended SQLAlchemy in a few places, though it is quite 
intermingled with our domain specific stuff I keep an eye out for little 
snippets that might be useful to others. So here's a trivial one; take it 
or leave it (and feel free to think of a better name). Knowing my luck it 
already exists; though I have looked hard through the docs!

class QueryEnhanced(Query):
''' Add a few extra bells and whistles to the standard Query object '''
def matches_any(self):
''' Returns true if your query would return 1 or more rows; false 
otherwise.
The following two statements ask the same question; but 
matches_any is _much_ quicker on large tables:
my_query.matches_any()
my_query.count() != 0
'''
return self.session.scalar(select([self.exists()]))

The other bit of technology we have that could be unpicked without _too_ 
much trouble is a sort of reverse CompositeProperty; many attributes of 
different types, including collections, out of one HSTORE column (with a 
sort of side-loaded instrumentation for mutation tracking that I think 
could have been done in a more idiosyncratic way). 

Paraphrasing a bit but you can do things like:

class Animal(Base):
data   = Column(MutableDict.as_mutable(HSTORE))

colour = HsProperty(data, String)
legs   = HsProperty(data, Integer)
discovered = HsProperty(data, Date)
fun_facts  = HsProperty(data, JSONEncoded(list))

'colour', 'legs', 'discovered', and 'fun_facts' end up as keys in the 
HSTORE and the values are strings, integers, dates and lists on the python 
side but stored as strings in the HSTORE such a way that they can be 
CAST-ed in a server query [where possible]:

session().query(Animal).filter(Animal.legs  2)

and get a query like

SELECT ... FROM animal WHERE CAST(animal.data - legs AS INTEGER)  2

You can also put an arbitrary JSONEncodable object in there too. 
Collections get converted to Mutable counterparts for change-tracking.

In many ways it is similar to ColumnProperty except that - the properties 
are writable (and when written only trigger the relevant bits of the hstore 
to be updated). Also on object instances the values in HsProperties are 
fetched as part of the query; we lazily de-serialise them directly from the 
hstore dictionary. 

Before spend a couple of days removing our corporate clutter from that, 
getting permission to license it etc.. and posting either as a patch or 
extension I thought I would see if there is any interest (or if someone has 
already done it better?). It's implemented as a custom metaclass right now, 
but I think I might be able to do it fully with events.

Code aside, if you can think of ways in which we as a company could support 
SQLAlchemy (bear in mind I am not in charge of the purse strings, but I can 
make a pitch on your behalf; we are still awaiting the fruits of our 
donation to the PyPy 
http://morepypy.blogspot.co.uk/2012/01/py3k-and-numpy-first-stage-thanks-to.htmlguys
 
:).** Then do let me know. I don't check this email account all that 
regularly but my work address is my firstname.lastname at cantabcapital dot 
com

Keep up the good work!

** [shameless plug] Or if you are keen, enthusiastic, mostly competent, and 
looking for a well paid job where you get to do loads of Python  SQLAlchemy

-- 
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+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/groups/opt_out.


Re: [sqlalchemy] matches_any: an extension to the Query object, and a HSTORE attribute access property

2014-01-07 Thread jason kirtland
On Tue, Jan 7, 2014 at 11:14 AM, Philip Scott safetyfirstp...@gmail.comwrote:

 Hi folks,

 SQLAlchemy is at the heart of what we do at work (UK based hedge fund); so
 first of all a big thank you; I am not quite sure where we'd be without
 you. We would like to give back to the community as much as we can (I tried
 to get some of the developers on the company xmas present list this year
 but was too late.. cross your fingers for next year).

 We have extended SQLAlchemy in a few places, though it is quite
 intermingled with our domain specific stuff I keep an eye out for little
 snippets that might be useful to others. So here's a trivial one; take it
 or leave it (and feel free to think of a better name). Knowing my luck it
 already exists; though I have looked hard through the docs!

 class QueryEnhanced(Query):
 ''' Add a few extra bells and whistles to the standard Query object '''
 def matches_any(self):
 ''' Returns true if your query would return 1 or more rows; false
 otherwise.
 The following two statements ask the same question; but
 matches_any is _much_ quicker on large tables:
 my_query.matches_any()
 my_query.count() != 0
 '''
 return self.session.scalar(select([self.exists()]))

 The other bit of technology we have that could be unpicked without _too_
 much trouble is a sort of reverse CompositeProperty; many attributes of
 different types, including collections, out of one HSTORE column (with a
 sort of side-loaded instrumentation for mutation tracking that I think
 could have been done in a more idiosyncratic way).

 Paraphrasing a bit but you can do things like:

 class Animal(Base):
 data   = Column(MutableDict.as_mutable(HSTORE))

 colour = HsProperty(data, String)
 legs   = HsProperty(data, Integer)
 discovered = HsProperty(data, Date)
 fun_facts  = HsProperty(data, JSONEncoded(list))

 'colour', 'legs', 'discovered', and 'fun_facts' end up as keys in the
 HSTORE and the values are strings, integers, dates and lists on the python
 side but stored as strings in the HSTORE such a way that they can be
 CAST-ed in a server query [where possible]:

 session().query(Animal).filter(Animal.legs  2)

 and get a query like

 SELECT ... FROM animal WHERE CAST(animal.data - legs AS INTEGER)  2

 You can also put an arbitrary JSONEncodable object in there too.
 Collections get converted to Mutable counterparts for change-tracking.

 In many ways it is similar to ColumnProperty except that - the properties
 are writable (and when written only trigger the relevant bits of the hstore
 to be updated). Also on object instances the values in HsProperties are
 fetched as part of the query; we lazily de-serialise them directly from the
 hstore dictionary.

 Before spend a couple of days removing our corporate clutter from that,
 getting permission to license it etc.. and posting either as a patch or
 extension I thought I would see if there is any interest (or if someone has
 already done it better?). It's implemented as a custom metaclass right now,
 but I think I might be able to do it fully with events.


I would be very interested in this work. At my org we have a subset of the
same idea that we're depending upon, but it's tied to an ancient SQLAlchemy
version and we never took it all the way into the query space like that.
That looks absolutely fabulous!

-- 
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+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/groups/opt_out.


Re: [sqlalchemy] matches_any: an extension to the Query object, and a HSTORE attribute access property

2014-01-07 Thread Michael Bayer

On Jan 7, 2014, at 2:14 PM, Philip Scott safetyfirstp...@gmail.com wrote:

 
 The other bit of technology we have that could be unpicked without _too_ much 
 trouble is a sort of reverse CompositeProperty; many attributes of different 
 types, including collections, out of one HSTORE column (with a sort of 
 side-loaded instrumentation for mutation tracking that I think could have 
 been done in a more idiosyncratic way). 
 
 Paraphrasing a bit but you can do things like:
 
 class Animal(Base):
 data   = Column(MutableDict.as_mutable(HSTORE))
 
 colour = HsProperty(data, String)
 legs   = HsProperty(data, Integer)
 discovered = HsProperty(data, Date)
 fun_facts  = HsProperty(data, JSONEncoded(list))
 
 'colour', 'legs', 'discovered', and 'fun_facts' end up as keys in the HSTORE 
 and the values are strings, integers, dates and lists on the python side but 
 stored as strings in the HSTORE such a way that they can be CAST-ed in a 
 server query [where possible]:
 
 session().query(Animal).filter(Animal.legs  2)
 
 and get a query like
 
 SELECT ... FROM animal WHERE CAST(animal.data - legs AS INTEGER)  2
 
 You can also put an arbitrary JSONEncodable object in there too. Collections 
 get converted to Mutable counterparts for change-tracking.
 
 In many ways it is similar to ColumnProperty except that - the properties are 
 writable (and when written only trigger the relevant bits of the hstore to be 
 updated). Also on object instances the values in HsProperties are fetched as 
 part of the query; we lazily de-serialise them directly from the hstore 
 dictionary. 
 
 Before spend a couple of days removing our corporate clutter from that, 
 getting permission to license it etc.. and posting either as a patch or 
 extension I thought I would see if there is any interest (or if someone has 
 already done it better?). It's implemented as a custom metaclass right now, 
 but I think I might be able to do it fully with events.

that’s a very nice pattern!  It looks like you could do that strictly with 
Python descriptors, such as subclassing @hybrid_property, no ?   Each property 
is just an expression against the “data” column, either python-side (lazily 
deserialize a key) or expression-side (do a postgresql expression for a certain 
key), and you can also trigger the mutable.is_changed() flag within the setter. 
  I don’t think you’d need events.

 
 Code aside, if you can think of ways in which we as a company could support 
 SQLAlchemy (bear in mind I am not in charge of the purse strings, but I can 
 make a pitch on your behalf; we are still awaiting the fruits of our donation 
 to the PyPy guys :).** Then do let me know. I don't check this email account 
 all that regularly but my work address is my firstname.lastname at 
 cantabcapital dot com

Thanks !   I think what I’m usually looking for are people resources.  Doc 
fixes and pull requests and such.   If I could organize some significant batch 
of work as something that would work under a “grant” model, I’ll let you know.  
 I haven’t figured out how to work that way, yet.




signature.asc
Description: Message signed with OpenPGP using GPGMail