Support retrieving Query objects for Bakedqueries

Issue #4318 resolved
Sai Sindhur Malleni
created an issue

Trying to use baked queries and refactored this function

def get_oldest_pending_db_row_with_lock(context):
    journal_dep = aliased(models.OpenDaylightJournal)
    dep_query = context.session.query(journal_dep).filter(
        models.OpenDaylightJournal.seqnum == journal_dep.seqnum
    ).outerjoin(
        journal_dep.depending_on, aliased=True).filter(
        or_(models.OpenDaylightJournal.state == odl_const.PENDING,
            models.OpenDaylightJournal.state == odl_const.PROCESSING))
    row = context.session.query(models.OpenDaylightJournal).filter(
        models.OpenDaylightJournal.state == odl_const.PENDING,
        ~ dep_query.exists()
    ).order_by(
        asc(models.OpenDaylightJournal.last_retried)).first()
    if row:
        update_db_row_state(context, row, odl_const.PROCESSING)

    return row

to use baked queries, as follows:

def get_oldest_pending_db_row_with_lock():
    s = session
    journal_dep = aliased(models.OpenDaylightJournal)
    dep_query = bakery(lambda s1: session.query(journal_dep))
    dep_query += lambda dep_query: dep_query.filter(
        models.OpenDaylightJournal.seqnum == journal_dep.seqnum)
    dep_query += lambda dep_query: dep_query.outerjoin(
        journal_dep.depending_on, aliased=True)
    dep_query += lambda dep_query: dep_query.filter(
        or_(models.OpenDaylightJournal.state == odl_const.PENDING,
            models.OpenDaylightJournal.state == odl_const.PROCESSING))

    row = bakery(lambda s2: session.query(models.OpenDaylightJournal))
    row += lambda row: row.filter(
        models.OpenDaylightJournal.state == odl_const.PENDING,
        ~ dep_query.exists())
    row += lambda row: row.order_by(
        asc(models.OpenDaylightJournal.last_retried))
    row(s).all()
    if row:
        update_db_row_state(row, odl_const.PROCESSING)

    return row

We are seeing a traceback as follows,

Traceback (most recent call last):
  File "saidb.py", line 129, in <module>
    get_oldest_pending_db_row_with_lock_baked()
  File "saidb.py", line 122, in get_oldest_pending_db_row_with_lock_baked
    row(s).all()
  File "/usr/lib64/python2.7/site-packages/sqlalchemy/ext/baked.py", line 434, in all
    return list(self)
  File "/usr/lib64/python2.7/site-packages/sqlalchemy/ext/baked.py", line 326, in __iter__
    baked_context = bq._bake(self.session)
  File "/usr/lib64/python2.7/site-packages/sqlalchemy/ext/baked.py", line 198, in _bake
    query = self._as_query(session)
  File "/usr/lib64/python2.7/site-packages/sqlalchemy/ext/baked.py", line 221, in _as_query
    query = step(query)
  File "saidb.py", line 119, in <lambda>
    ~ dep_query.exists())
AttributeError: 'BakedQuery' object has no attribute 'exists'

So, looks like the query object is not retrievable. Any workarounds, plans to implement this?

Comments (10)

  1. Michael Bayer repo owner

    this is not a great solution. this is what that code looks like :

    journal_dep = aliased(models.OpenDaylightJournal)
    dep_query = bakery(lambda s1: s1.query(journal_dep))
    dep_query += lambda q: q.filter(
        models.OpenDaylightJournal.seqnum == journal_dep.seqnum)
    dep_query += lambda q: q.outerjoin(
        journal_dep.depending_on, aliased=True)
    dep_query += lambda q: q.filter(
        or_(models.OpenDaylightJournal.state == odl_const.PENDING,
            models.OpenDaylightJournal.state == odl_const.PROCESSING))
    
    row = bakery(lambda s2: s2.query(models.OpenDaylightJournal))
    row += lambda q: q.filter(
        models.OpenDaylightJournal.state == odl_const.PENDING,
        ~ (dep_query._as_query(context.session)).exists())
    

    the "session" is extremely stateful, as well as the "context" object in neutron, and when looking at the code for a bakedquery, we shouldn't see anything stateful at all inside those lambdas. in this case, we are just getting a blank Query out, but we shouldn't have to see anything stateful there.

  2. Michael Bayer repo owner

    Add BakedQuery.to_query() method

    Added new feature :meth:.BakedQuery.to_query, which allows for a clean way of using one :class:.BakedQuery as a subquery inside of another :class:.BakedQuery without needing to refer explicitly to a :class:.Session.

    Fixes: #4318 Change-Id: I528056c7d140036c27b95500d7a60dcd14784016

    → <<cset b601051b217c>>

  3. Log in to comment