| |
@@ -26,6 +26,8 @@
|
| |
from flask_restful import reqparse
|
| |
|
| |
from sqlalchemy.orm import exc as orm_exc
|
| |
+ from sqlalchemy import distinct
|
| |
+ from sqlalchemy.sql import text
|
| |
from werkzeug.exceptions import HTTPException
|
| |
from werkzeug.exceptions import BadRequest as JSONBadRequest
|
| |
|
| |
@@ -319,22 +321,7 @@
|
| |
# =============================================================================
|
| |
# RESULTS
|
| |
# =============================================================================
|
| |
-
|
| |
- def select_results(since_start=None, since_end=None, outcomes=None, groups=None, testcases=None, testcases_like=None, result_data=None, _sort=None):
|
| |
- # Checks if the sort parameter specified in the request is valid before querying.
|
| |
- # Sorts by submit_time in a descending order if the sort parameter is absent or invalid.
|
| |
- query_sorted = False
|
| |
- if _sort:
|
| |
- sort_match = re.match(r'^(?P<order>asc|desc):(?P<column>.+)$', _sort)
|
| |
- if sort_match:
|
| |
- if sort_match.group('column') == 'submit_time':
|
| |
- sort_order = {'asc': db.asc, 'desc': db.desc}[sort_match.group('order')]
|
| |
- sort_column = getattr(Result, sort_match.group('column'))
|
| |
- q = db.session.query(Result).order_by(sort_order(sort_column))
|
| |
- query_sorted = True
|
| |
- if not query_sorted:
|
| |
- q = db.session.query(Result).order_by(db.desc(Result.submit_time))
|
| |
-
|
| |
+ def filter_results(q, since_start=None, since_end=None, outcomes=None, groups=None, testcases=None, testcases_like=None, result_data=None):
|
| |
# Time constraints
|
| |
if since_start:
|
| |
q = q.filter(Result.submit_time >= since_start)
|
| |
@@ -388,6 +375,26 @@
|
| |
return q
|
| |
|
| |
|
| |
+ def select_results(since_start=None, since_end=None, outcomes=None, groups=None, testcases=None, testcases_like=None, result_data=None, _sort=None):
|
| |
+ # Checks if the sort parameter specified in the request is valid before querying.
|
| |
+ # Sorts by submit_time in a descending order if the sort parameter is absent or invalid.
|
| |
+ query_sorted = False
|
| |
+ if _sort:
|
| |
+ sort_match = re.match(r'^(?P<order>asc|desc):(?P<column>.+)$', _sort)
|
| |
+ if sort_match:
|
| |
+ if sort_match.group('column') == 'submit_time':
|
| |
+ sort_order = {'asc': db.asc, 'desc': db.desc}[sort_match.group('order')]
|
| |
+ sort_column = getattr(Result, sort_match.group('column'))
|
| |
+ q = db.session.query(Result).order_by(sort_order(sort_column))
|
| |
+ query_sorted = True
|
| |
+ if not query_sorted:
|
| |
+ q = db.session.query(Result).order_by(db.desc(Result.submit_time))
|
| |
+
|
| |
+ q = filter_results(q, since_start, since_end, outcomes, groups, testcases, testcases_like, result_data)
|
| |
+
|
| |
+ return q
|
| |
+
|
| |
+
|
| |
def __get_results_parse_args():
|
| |
retval = {"args": None, "error": None, "result_data": None}
|
| |
try:
|
| |
@@ -417,6 +424,7 @@
|
| |
args['testcases'] = [tc.strip() for tc in args['testcases'].split(',') if tc.strip()]
|
| |
args['testcases:like'] = [tc.strip() for tc in args['testcases:like'].split(',') if tc.strip()]
|
| |
args['groups'] = [group.strip() for group in args['groups'].split(',') if group.strip()]
|
| |
+ args['_distinct_on'] = [_distinct_on.strip() for _distinct_on in args['_distinct_on'].split(',') if _distinct_on.strip()]
|
| |
retval['args'] = args
|
| |
|
| |
# find results_data with the query parameters
|
| |
@@ -456,39 +464,72 @@
|
| |
return p['error']
|
| |
|
| |
args = p['args']
|
| |
+ if not args['_distinct_on']:
|
| |
+ q = select_results(
|
| |
+ since_start=args['since']['start'],
|
| |
+ since_end=args['since']['end'],
|
| |
+ groups=args['groups'],
|
| |
+ testcases=args['testcases'],
|
| |
+ testcases_like=args['testcases:like'],
|
| |
+ result_data=p['result_data'],
|
| |
+ _sort=args['_sort'],
|
| |
+ )
|
| |
|
| |
- q = select_results(
|
| |
- since_start=args['since']['start'],
|
| |
- since_end=args['since']['end'],
|
| |
- groups=args['groups'],
|
| |
- testcases=args['testcases'],
|
| |
- testcases_like=args['testcases:like'],
|
| |
- result_data=p['result_data'],
|
| |
- _sort=args['_sort'],
|
| |
- )
|
| |
-
|
| |
- # Produce a subquery with the same filter criteria as above *except*
|
| |
- # test case name, which we group by and join on.
|
| |
- sq = select_results(
|
| |
- since_start=args['since']['start'],
|
| |
- since_end=args['since']['end'],
|
| |
- groups=args['groups'],
|
| |
- result_data=p['result_data'],
|
| |
- )\
|
| |
- .order_by(None)\
|
| |
- .with_entities(
|
| |
- Result.testcase_name.label('testcase_name'),
|
| |
- db.func.max(Result.submit_time).label('max_submit_time'))\
|
| |
- .group_by(Result.testcase_name)\
|
| |
- .subquery()
|
| |
- q = q.join(sq, db.and_(Result.testcase_name == sq.c.testcase_name,
|
| |
- Result.submit_time == sq.c.max_submit_time))
|
| |
+ # Produce a subquery with the same filter criteria as above *except*
|
| |
+ # test case name, which we group by and join on.
|
| |
+ sq = select_results(
|
| |
+ since_start=args['since']['start'],
|
| |
+ since_end=args['since']['end'],
|
| |
+ groups=args['groups'],
|
| |
+ result_data=p['result_data'],
|
| |
+ )\
|
| |
+ .order_by(None)\
|
| |
+ .with_entities(
|
| |
+ Result.testcase_name.label('testcase_name'),
|
| |
+ db.func.max(Result.submit_time).label('max_submit_time'))\
|
| |
+ .group_by(Result.testcase_name)\
|
| |
+ .subquery()
|
| |
+ q = q.join(sq, db.and_(Result.testcase_name == sq.c.testcase_name,
|
| |
+ Result.submit_time == sq.c.max_submit_time))
|
| |
+
|
| |
+ results = q.all()
|
| |
+
|
| |
+ return jsonify(dict(
|
| |
+ data=[SERIALIZE(o) for o in results],
|
| |
+ ))
|
| |
+
|
| |
+ testcases = args.get('testcases', None)
|
| |
+ testcases_like = args.get('testcases:like', None)
|
| |
+ since_start = args['since'].get('start', None)
|
| |
+ since_end = args['since'].get('end', None)
|
| |
+ groups = args.get('groups', None)
|
| |
+ distinct_on = args['_distinct_on']
|
| |
+
|
| |
+ if not any([testcases, testcases_like, since_start, since_end, groups, p['result_data']]):
|
| |
+ return jsonify({'message': ("Please, provide at least one "
|
| |
+ "filter beside '_distinct_on'")}), 400
|
| |
+
|
| |
+ q = db.session.query(Result)
|
| |
+ q = filter_results(q, since_start=since_start, since_end=since_end,
|
| |
+ groups=groups, testcases=testcases,
|
| |
+ testcases_like=testcases_like, result_data=p['result_data'])
|
| |
+
|
| |
+ values_distinct_on = ['result.testcase_name']
|
| |
+ for i in distinct_on:
|
| |
+ name = 'result_data_{}'.format(i)
|
| |
+ alias = db.aliased(
|
| |
+ db.session.query(ResultData).filter(ResultData.key == i).subquery(), name=name)
|
| |
+ q = q.outerjoin(alias)
|
| |
+ values_distinct_on.append('{}.value'.format(name))
|
| |
+ q = q.distinct(*values_distinct_on).order_by(
|
| |
+ text(', '.join(values_distinct_on)), db.desc(text('result.submit_time')))
|
| |
|
| |
results = q.all()
|
| |
-
|
| |
- return jsonify(dict(
|
| |
+ results = dict(
|
| |
data=[SERIALIZE(o) for o in results],
|
| |
- ))
|
| |
+ )
|
| |
+ results['data'] = sorted(results['data'], key=lambda x: x['submit_time'], reverse=True)
|
| |
+ return jsonify(results)
|
| |
|
| |
|
| |
RP['get_results'] = reqparse.RequestParser()
|
| |
@@ -498,6 +539,7 @@
|
| |
RP['get_results'].add_argument('outcome', location='args')
|
| |
RP['get_results'].add_argument('groups', default="", location='args')
|
| |
RP['get_results'].add_argument('_sort', default="", location='args')
|
| |
+ RP['get_results'].add_argument('_distinct_on', default="", location='args')
|
| |
# TODO - can this be done any better?
|
| |
RP['get_results'].add_argument('testcases', default="", location='args')
|
| |
RP['get_results'].add_argument('testcases:like', default="", location='args')
|
| |
I'm getting
AssertionError: assert 6 == 5
here.