Merge "Implements complex query functionality for samples"

This commit is contained in:
Jenkins
2014-02-11 12:19:41 +00:00
committed by Gerrit Code Review
10 changed files with 1120 additions and 38 deletions

View File

@@ -24,8 +24,10 @@ import os
import types
from sqlalchemy import and_
from sqlalchemy import asc
from sqlalchemy import desc
from sqlalchemy import func
from sqlalchemy import or_
from sqlalchemy.orm import aliased
from ceilometer.openstack.common.db import exception as dbexc
@@ -170,6 +172,19 @@ def make_query_from_filter(session, query, sample_filter, require_meter=True):
class Connection(base.Connection):
"""SqlAlchemy connection."""
operators = {"=": operator.eq,
"<": operator.lt,
">": operator.gt,
"<=": operator.le,
"=<": operator.le,
">=": operator.ge,
"=>": operator.ge,
"!=": operator.ne}
complex_operators = {"or": or_,
"and": and_}
ordering_functions = {"asc": asc,
"desc": desc}
def __init__(self, conf):
url = conf.database.connection
if url == 'sqlite://':
@@ -517,23 +532,11 @@ class Connection(base.Connection):
source=resource.sources[0].id,
user_id=resource.user_id)
def get_samples(self, sample_filter, limit=None):
"""Return an iterable of api_models.Samples.
:param sample_filter: Filter.
:param limit: Maximum number of results to return.
"""
if limit == 0:
return
session = self._get_db_session()
query = session.query(models.Meter)
query = make_query_from_filter(session, query, sample_filter,
require_meter=False)
if limit:
def _retrieve_samples(self, query, orderby, limit, table):
query = self._apply_order_by(query, orderby, table)
if limit is not None:
query = query.limit(limit)
samples = query.from_self()\
.order_by(desc(models.Meter.timestamp)).all()
samples = query.all()
for s in samples:
# Remove the id generated by the database when
@@ -557,6 +560,67 @@ class Connection(base.Connection):
message_signature=s.message_signature,
)
def get_samples(self, sample_filter, limit=None):
"""Return an iterable of api_models.Samples.
:param sample_filter: Filter.
:param limit: Maximum number of results to return.
"""
if limit == 0:
return []
table = models.Meter
session = self._get_db_session()
query = session.query(table)
query = make_query_from_filter(session, query, sample_filter,
require_meter=False)
return self._retrieve_samples(query, None, limit, table)
def query_samples(self, filter_expr=None, orderby=None, limit=None):
if limit == 0:
return []
table = models.Meter
session = self._get_db_session()
query = session.query(table)
if filter_expr is not None:
sql_condition = self._transform_expression(filter_expr,
table)
query = query.filter(sql_condition)
return self._retrieve_samples(query, orderby, limit, table)
def _transform_expression(self, expression_tree, table):
def transform(sub_tree):
operator = sub_tree.keys()[0]
nodes = sub_tree.values()[0]
if operator in self.complex_operators:
op = self.complex_operators[operator]
element_list = []
for node in nodes:
element = transform(node)
element_list.append(element)
return op(*element_list)
else:
op = self.operators[operator]
return op(getattr(table, nodes.keys()[0]), nodes.values()[0])
return transform(expression_tree)
def _apply_order_by(self, query, orderby, table):
if orderby is not None:
for field in orderby:
ordering_function = self.ordering_functions[field.values()[0]]
query = query.order_by(ordering_function(
getattr(table, field.keys()[0])))
else:
query = query.order_by(desc(table.timestamp))
return query
def _make_stats_query(self, sample_filter, groupby):
select = [
models.Meter.counter_unit.label('unit'),