From 52f770bf8cf00b33ac904e3d578667ed41a311e7 Mon Sep 17 00:00:00 2001 From: Mike McLean Date: May 23 2023 03:51:26 +0000 Subject: basic QueryView working --- diff --git a/kojihub/db.py b/kojihub/db.py index 50673d7..74f03b9 100644 --- a/kojihub/db.py +++ b/kojihub/db.py @@ -852,8 +852,9 @@ class QueryView: } ''' - def __init__(self, fields, clauses, values, opts=None): + def __init__(self, clauses=None, fields=None, opts=None): self.extra_joins = [] + self.values = {} tables = list(self.tables) # copy fields = self.get_fields(fields) fields, aliases = zip(*fields.items()) @@ -862,27 +863,50 @@ class QueryView: self.query = QueryProcessor( columns=fields, aliases=aliases, tables=tables, joins=joins, - clauses=clauses, values=values, + clauses=clauses, values=self.values, opts=opts) - def get_fields(self): - fields = {} - joins = [] - clauses = [] - - x_joins = set() - for field in self.fields: - f_info = self.fieldmap.get(field) - if f_info is None: - raise koji.ParameterError(f'Invalid field for query {field}') - fullname, joinkey = f_info - fullname = fullname or field - fields[fullname] = field - if joinkey: - x_joins.add(joinkey) - - def get_clauses(self): - pass + def get_fields(self, fields): + fields = fields or self.fieldmap.keys() # XXX stable order + + return {self.map_field(f): f for f in fields} + + def map_field(self, field): + f_info = self.fieldmap.get(field) + if f_info is None: + raise koji.ParameterError(f'Invalid field for query {field}') + fullname, joinkey = f_info + fullname = fullname or field + if joinkey: + self.extra_joins.append(joinkey) + return fullname + + def get_clauses(self, clauses): + # for now, just a very simple implementation + result = [] + clauses = clauses or [] + for n, clause in enumerate(clauses): + # TODO checks check checks + if len(clause) == 2: + # implicit operator + field, value = clause + if isinstance(value, (list, tuple)): + op = 'IN' + else: + op = '=' + elif len(clause) == 3: + field, op, value = clause + op = op.upper() + if op not in ('IN', '=', '!=', '>', '<', '>=', '<='): + raise koji.ParameterError(f'Invalid operator: {op}') + else: + raise koji.ParameterError(f'Invalid clause: {clause}') + fullname = self.map_field(field) + key = f'v_{field}_{n}' + self.values[key] = value + result.append(f'{fullname} {op} %({key})s') + + return result def get_joins(self): joins = list(self.joins) diff --git a/kojihub/scheduler.py b/kojihub/scheduler.py index 0283c26..822ad6d 100644 --- a/kojihub/scheduler.py +++ b/kojihub/scheduler.py @@ -4,7 +4,7 @@ import time import koji from . import kojihub -from .db import QueryProcessor, InsertProcessor, UpdateProcessor, db_lock +from .db import QueryProcessor, InsertProcessor, UpdateProcessor, QueryView, db_lock logger = logging.getLogger('koji.scheduler') @@ -125,6 +125,22 @@ def get_host_data(hostID=None): return query.execute() +class TaskRunsQuery(QueryView): + + tables = ['scheduler_task_runs'] + fieldmap = { + 'id': ['scheduler_task_runs.id', None], + 'task_id': ['scheduler_task_runs.task_id', None], + 'host_id': ['scheduler_task_runs.host_id', None], + 'active': ['scheduler_task_runs.active', None], + 'create_ts': ["date_part('epoch', scheduler_task_runs.create_time)", None], + } + + +def get_task_runs2(clauses=None, fields=None): + return TaskRunsQuery(clauses, fields).execute() + + def get_task_runs(taskID=None, hostID=None, active=None): taskID = kojihub.convert_value(taskID, cast=int, none_allowed=True) hostID = kojihub.convert_value(hostID, cast=int, none_allowed=True) @@ -548,4 +564,5 @@ class TaskScheduler(object): class SchedulerExports: getTaskRuns = staticmethod(get_task_runs) + getTaskRuns2 = staticmethod(get_task_runs2) getHostData = staticmethod(get_host_data)