[odb-users] queries during results iterations

Adnan RIHAN axel50397 at gmail.com
Fri Apr 17 15:40:16 EDT 2015


Hi Boris,

On 17 avril 2015 at 17:18:38, Boris Kolpackov (boris at codesynthesis.com(mailto:boris at codesynthesis.com)) wrote:

> No, that's how you should do it and it should work. Can you show the
> body of post_load() as well as the top-level transaction that iterates
> over Warehouse?

Sure. First of all, WarehouseWidget loads EntityManager::all() to get all the Warehouse lines:
template                        <typename T>
QOdbList<QSharedPointer<T> >    all(OrderBy orderBy = ORD_NATURALLY, bool useCache = true)
{
    [...]

    QOdbList<QSharedPointer<T> >    list;

    try {
        odb::transaction    t(this->m_db->begin(), !odb::transaction::has_current());
        odb::result<T>      r(this->m_db->query<T>(useCache));

        for (typename odb::result<T>::iterator i(r.begin()); i != r.end(); ++i) {
            list.append(QSharedPointer<T>(new T(*i)));
        }

        odb::transaction::current().commit();
    } catch (const odb::result_not_cached &e) {
        this->m_lastError = ERR_NOT_CACHED;
        this->m_lastRawError = e.what();
        qDebug() << "ODB Exception:" << this->m_lastRawError;
    } catch (const odb::exception &e) {
        this->m_lastRawError = e.what();
        qDebug() << "ODB Exception:" << this->m_lastRawError;
    }

    [...]

    return (list);
}


Here is the callback (« find() » and « findOne() » call respectively « query() » and « query_one() » :
void    Warehouse::dbCallback(odb::callback_event e, odb::database &db)
{
    switch (e) {
        case odb::callback_event::post_load: {
            this->m_openStock = MasterController::inst()->em()->findOne<Invoice>(
                            odb::query<Invoice>::type == "IV_INVENT"
                            && odb::query<Invoice>::createdAt >= this->m_openedAt.addDays(-1)
                            && odb::query<Invoice>::createdAt <= this->m_openedAt
            );

            this->m_closeStock = MasterController::inst()->em()->findOne<Invoice>(
                             odb::query<Invoice>::type == "IV_INVENT"
                             && odb::query<Invoice>::createdAt >= this->m_openedAt
                             && odb::query<Invoice>::createdAt <= this->m_closedAt
            );

            this->m_invoices = MasterController::inst()->em()->find<Invoice>(
                             odb::query<Invoice>::type != "IV_INVENT"
                             && odb::query<Invoice>::createdAt >= this->m_openedAt
                             && odb::query<Invoice>::createdAt <= this->m_closedAt
            );
            break;
        }

        default: break;
    }
}


Apparently, the callback is correctly called, but when back to EntityManager::all(), it continues until it reaches « ++i » (I’ve checked by moving it to the end of the for loop).

> Is there an eager-loaded pointer in Invoice (directly or indirectly)
> that point to (another) Warehouse?

No, the Invoice class doesn’t have any pointers except to Customer (which is currently always null). I must say that the EntityManager isn’t a Singleton itself, but is accessed via a Singleton, which makes it global. But as the queries are done entirely in a method, I don’t think there is a conflict (each call has its own stack).

Thanks for your help.
--  
Cordialement, Adnan RIHAN.

GPG: 5675-62BA (https://keybase.io/max13/key.asc)
-> Si vous n'utilisez pas GPG mais souhaitez quand même m’envoyer un e-mail chiffré: (https://encrypt.to/0x567562BA).



More information about the odb-users mailing list