X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=PLC%2FFilter.py;h=c20fd9c5512ed14219afc09401ee6c835cb3bbb0;hb=cee5ab52df1c9f38b6eaff2dd354cb22f59028c7;hp=9f5fb42befcbfc5e1fadb275fad6548fb31fdc10;hpb=17a90e3c5373b78b5aea38e011a96455c0024eae;p=plcapi.git diff --git a/PLC/Filter.py b/PLC/Filter.py index 9f5fb42..c20fd9c 100644 --- a/PLC/Filter.py +++ b/PLC/Filter.py @@ -5,14 +5,17 @@ except NameError: from sets import Set set = Set +import time + from PLC.Faults import * from PLC.Parameter import Parameter, Mixed, python_type class Filter(Parameter, dict): """ A type of parameter that represents a filter on one or more - columns of a database table. fields should be a dictionary of - field names and types, e.g. + columns of a database table. + + field should be a dictionary of field names and types, e.g. {'node_id': Parameter(int, "Node identifier"), 'hostname': Parameter(int, "Fully qualified hostname", max = 255), @@ -24,6 +27,21 @@ class Filter(Parameter, dict): representing an intersection (if join_with is AND) or union (if join_with is OR) filter. If a value is a sequence type, then it should represent a list of possible values for that field. + + Special forms: + * a field starting with the ~ character means negation. + example : { '~peer_id' : None } + * a field starting with < [ ] or > means lower than or greater than + < > uses strict comparison + [ ] is for using <= or >= instead + example : { '>time' : 1178531418 } + example : { ']event_id' : 2305 } + * a field starting with [ or ] means older than or more recent than + the associated value should be a given unix timestamp + * a (string) value containing either a * or a % character is + treated as a (sql) pattern; * are replaced with % that is the + SQL wildcard character. + example : { 'hostname' : '*.jp' } """ def __init__(self, fields = {}, filter = {}, doc = "Attribute filter"): @@ -46,6 +64,15 @@ class Filter(Parameter, dict): # Null filter means no filter Parameter.__init__(self, self.fields, doc = doc, nullok = True) + # this code is not used anymore + # at some point the select in the DB for event objects was done on + # the events table directly, that is stored as a timestamp, thus comparisons + # needed to be done based on SQL timestamps as well + def unix2timestamp (self,unix): + s = time.gmtime(unix) + return "TIMESTAMP'%04d-%02d-%02d %02d:%02d:%02d'" % (s.tm_year,s.tm_mon,s.tm_mday, + s.tm_hour,s.tm_min,s.tm_sec) + def sql(self, api, join_with = "AND"): """ Returns a SQL conditional that represents this filter. @@ -60,13 +87,22 @@ class Filter(Parameter, dict): assert join_with in ("AND", "OR") for field, value in self.iteritems(): - # provide for negation with a field starting with ~ - negation=False - if field[0] == '~': - negation = True - field = field[1:] + # handle negation, numeric comparisons + # simple, 1-depth only mechanism + + modifiers={'~' : False, + '<' : False, '>' : False, + '[' : False, ']' : False, + } + + for char in modifiers.keys(): + if field[0] == char: + modifiers[char]=True; + field = field[1:] + break if field not in self.fields: +# print 'current fields',self.fields raise PLCInvalidArgument, "Invalid filter field '%s'" % field if isinstance(value, (list, tuple, set)): @@ -87,12 +123,23 @@ class Filter(Parameter, dict): value = str(api.db.quote(value.replace("*", "%"))) else: operator = "=" - value = str(api.db.quote(value)) + if modifiers['<']: + operator='<' + if modifiers['>']: + operator='>' + if modifiers['[']: + operator='<=' + if modifiers[']']: + operator='>=' + else: + value = str(api.db.quote(value)) clause = "%s %s %s" % (field, operator, value) - if negation: - clause = " ( NOT %s ) "%clause - + + if modifiers['~']: + clause = " ( NOT %s ) " % (clause) + conditionals.append(clause) +# print 'sql=',(" %s " % join_with).join(conditionals) return (" %s " % join_with).join(conditionals)