[odb-users] How to make a "lazy" QList?

Boris Kolpackov boris at codesynthesis.com
Thu Aug 2 08:39:53 EDT 2012


Hi Rene,

Rene Jensen <rene at catatonic.dk> writes:

> Now that I have pondered the ramifications of my own suggestion, I think
> that making real lazy variants of lists, vectors etc. might be overdoing
> it. What is needed is a (programmer-friendly) technique to control loading
> of parts of an object. E.g.
> 
> 
>   class Author
>   { ...
>     #pragma db lazyloaded
>     QList <QLazySharedPointer<Book> >    authorsBooks;
> 
>     #pragma db lazyloaded
>     vector<QLazySharedPointer<Article> >  authorsArticles;
>     ...
>   }
> 
> Author* A = ... some default load procedure ... will not load "lazyloaded"
> members
> A->authorsBooks.size() // 0 ... not loaded
> 
> db->load_lazymembers (A);
> 
> A->authorsBooks.size() // 34

Yes, we've thought about this approach also. The major problem here is
that there is no good place to store the loaded/unloaded flag. While it
might not be necessary from the users' perspective (i.e., we can say
that it is the user's responsibility to know whether the lazy parts
are loaded or not), it gets tricky when we consider an operation like
update(). ODB has no way of knowing whether the container is loaded
(and thus we need to write the elements to the database) or not (and
thus we should do nothing for this container).

The other issue is that you may have several lazy containers in a class
and may want to load only one of them at a time. With the above approach
there is no way to specify which member to load. Doing something like
db->load_lazymembers (A, &Author::authorsBooks) will work but will 
require authorsBooks to be public. Plus:

A->authorsBooks.load ();

Feels more natural than:

db->load_lazymembers (A, &Author::authorsBooks);

The other alternative that we are considering is to provide a smart
pointer-like class template that implements laziness:

class Author
{ ...
  #pragma db lazyloaded
  odb::lazy<QList <QLazySharedPointer<Book> > >    authorsBooks;

};

A->authorsBooks.load ();
A->authorsBooks->size ();
(*A->authorsBooks)[0]->load (); // Not very elegant.

This is the approach that will probably be most suitable for simple
members if/when we decide to support lazy loading for them as well.

On a more conceptual level, what seems to be the ultimate goal is
to have the ability to segment data members into lazy-loadable
sections. Supporting lazy loading for simple members will require
a separate statement for each member, if we do it member-by-member.
This is a significant overhead. So grouping members into as few
sections as possible is a good idea. Maybe something along these
lines:

class Author
{ 

  odb::lazy_section publications;

  #pragma db lazy(publications)
  QList <QLazySharedPointer<Book> >    authorsBooks;

  #pragma db lazy(publications)
  vector<QLazySharedPointer<Article> >  authorsArticles;  

};

if (!A->publications.loaded ())
  A->publications.load (); // Loads authorsBooks and authorsArticles.

Just some thoughts.

Boris



More information about the odb-users mailing list