On 12-10-05 11:27 AM, Michael Bayer wrote: > On Oct 5, 2012, at 10:26 AM, Andre wrote: > > > > > I would like to make this more efficient by adding an attribute to the > > DocumentBase class above, which simply does a SQL query to get the size of > > the > > file_object at the DB level, thinking that this will not require to load > > the > > binary object into memory to compute its size. Of course, this behavior > > could > > be done by adding an extra field (such as file_size) to my DB tables with > > binary object, which would be set when the binary object is stored in the > > database, but I thought that it would be more elegant if the DB didn't have > > that extra column just to keep track of the binary object size. > > IMO there's no question you'd use SQL side functions to get this length, > unless > they were found to be inefficient. Storing the length separately arguably > breaks normalization. > > > > > After reading and searching the web, I think one way to do this is using a > > column_property attribute in my DocumentBase class, such as: > > > > @declared_attr > > def file_size(cls): > > return > > column_property(select([func.length(cls.file_object)]).where(cls.id == id)) > > > > But the above is not working for me, and gives me the following error: > > > > File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/sql/compiler.py", > > line 388, in visit_column > > raise exc.CompileError("Cannot compile Column object until " > > CompileError: Cannot compile Column object until it's 'name' is assigned. > > > > I'm sure I'm missing something very basic here. Or maybe there is a > > simpler > > way of doing this? > > this was a little confusing because I kept assuming it was calling > func.length(cls.file_object) that was throwing things off. But it's not > (well > it is, but separately), it's that WHERE clause. The column_property() is an > expression that's loaded inline with your class, so unless you are > correlating a > different table back onto the parent table, you don't need a WHERE clause for > it. the usage of WHERE here would at most describe selecting from an alias > of > the table correlated against its unaliased form, but that's not needed here > and > also the mechanics of column_property() + declarative mixins + declared_attr > are > already getting into territories where things are more prone to not being > possible, due to Python class mechanics (which also give us all these great > mixin capabilities in the first place, not to detract from them!). > > In fact the "cls.id == id" there is creating a binary expression against the > Python built-in function "id()". > > Anyway, there's no need to embed a SELECT in here, you just need len(col), so > remove the select(), and also we need to navigate around that deferred() to > get > at the Column (this is something maybe I can improve, I added a ticket for > that): > > class DocumentBase(Base): > __abstract__ = True > filename = Column(String) > > @declared_attr > def file_object(cls): > return deferred(Column('file_object', LargeBinary)) > > @declared_attr > def file_size(cls): > return column_property(func.length(cls.file_object.columns[0])) > > class Document(DocumentBase): > __tablename__ = 'document' > > print Session().query(Document) > > SQL: > > SELECT length(:length_2) AS length_1, document.id AS document_id, > document.filename AS document_filename > FROM document > > now even if you wanted it to work as, "when I call file_size, it emits a SQL > query", you can do that too - just defer() that expression also: > > @declared_attr > def file_size(cls): > return deferred(func.length(cls.file_object.columns[0])) > > then you'll get SQL output like this when you say some_document.file_size: > > SELECT length(file_object) AS length_1 > FROM document > WHERE document.id = ? Thanks Michael for the quick and detailed reply. This works and is exactly what I needed. Many thanks. Much appreciated.
Regards, Andre > > > > > > > > > > > > > > > > > (I'm using sqlalchemy 0.7) > > > > Thanks a lot, > > Andre > > > > -- > > You received this message because you are subscribed to the Google Groups > > "sqlalchemy" group. > > To view this discussion on the web visit > > https://groups.google.com/d/msg/sqlalchemy/-/3XisZc_YH9IJ. > > To post to this group, send email to sqlalchemy@googlegroups.com > > <mailto:sqlalchemy@googlegroups.com>. > > To unsubscribe from this group, send email to > > sqlalchemy+unsubscr...@googlegroups.com > > <mailto:sqlalchemy+unsubscr...@googlegroups.com>. > > For more options, visit this group at > > http://groups.google.com/group/sqlalchemy?hl=en. > > -- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To post to this group, send email to sqlalchemy@googlegroups.com. > To unsubscribe from this group, send email to > sqlalchemy+unsubscr...@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/sqlalchemy?hl=en. -- Andre Charbonneau Shared Services Canada Telephone: 613-993-3129 -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.