equal_any() DB API helper produces incorrect SQL query

Bug #1292285 reported by Roman Podoliaka
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
OpenStack Compute (nova)
Fix Released
Undecided
Roman Podoliaka

Bug Description

Given an attribute name and a list of values equal_any() is meant to produce a WHERE clause which returns rows for which the column (denoted by an attribute of an SQLAlchemy model) is equal to ANY of passed values that involves using of SQL OR operator. In fact, AND operator is used to combine equality expressions.

E.g. for a model:

class Instance(BaseModel):
    __tablename__ = 'instances'

   id = sa.Column('id', sa.Integer, primary_key=True)
   ...
   task_state = sa.Column('task_state', sa.String(30))

using of equal_any():

  q = model_query(context, Instance).
  constraint = Constraint({'task_state': equal_any('error', 'deleting')})
  q = constraint.apply(Instance, q)

will produce:

SELECT * from instances
WHERE task_state = 'error' AND task_state = 'deleting'

instead of expected:

SELECT * from instances
WHERE task_state = 'error' OR task_state = 'deleting'

Tags: db
Changed in nova:
assignee: nobody → Roman Podoliaka (rpodolyaka)
Revision history for this message
OpenStack Infra (hudson-openstack) wrote : Fix proposed to nova (master)

Fix proposed to branch: master
Review: https://review.openstack.org/80431

Changed in nova:
status: New → In Progress
Revision history for this message
OpenStack Infra (hudson-openstack) wrote : Fix merged to nova (master)

Reviewed: https://review.openstack.org/80431
Committed: https://git.openstack.org/cgit/openstack/nova/commit/?id=8ff06df88b1f979f5a67f9d55fa0e828a6e73d04
Submitter: Jenkins
Branch: master

commit 8ff06df88b1f979f5a67f9d55fa0e828a6e73d04
Author: Roman Podoliaka <email address hidden>
Date: Thu Mar 13 23:48:56 2014 +0200

    Fix equal_any() DB API helper

    equal_any() query helper is meant to produce a WHERE clause combining
    a few conditions with OR operator in order to select the rows for
    which the given column is equal to ANY of passed values. In fact,
    it uses AND operator instead of OR, which means that an incorrect
    WHERE clause will be returned, if more than one value is passed to
    equal_any().

    This is caused by the fact that the or_() function from SQLAlchemy
    expression language is used incorrectly: it accepts unpacked
    instances of BinaryExpression, but a list of ones is passed.
    Unfortunately, in 0.7.x and 0.8.x branches of SQLAlchemy passing
    a list of values to or_() won't raise an exception immidiately,
    and the result will be an iterable, which explains why we didn't
    see equal_any() was actually broken before. Besides, equal_any() is
    rarely used in our code base and the test didn't cover the case when
    more than 1 value is passed to the function.

    This effectively fixes the error when running Nova unit tests
    with SQLAlchemy 0.9.x releases.

    Closes-Bug: #1292285

    Change-Id: If4c0f1d3e016e2affb0d49293c62ca9df0d033f7

Changed in nova:
status: In Progress → Fix Committed
Changed in nova:
milestone: none → icehouse-rc1
Thierry Carrez (ttx)
Changed in nova:
status: Fix Committed → Fix Released
Thierry Carrez (ttx)
Changed in nova:
milestone: icehouse-rc1 → 2014.1
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.