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 [email protected]
> > <mailto:[email protected]>.
> > To unsubscribe from this group, send email to
> > [email protected]
> > <mailto:[email protected]>.
> > 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 [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> 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 [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en.