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 = ? > > > (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. > 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. -- 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.