Merge "Implements complex query functionality for samples"
This commit is contained in:
@@ -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'),
|
||||
|
||||
Reference in New Issue
Block a user