source: trunk/plugins/dashboardreportsplugin/dashboardreports/patch/trac-query.7385.diff @ 391

Revision 391, 8.5 KB checked in by aculapov, 5 years ago (diff)
  • added patch for trac rev 7385
  • trac/ticket/api.py

     
    183183            valid_states.update(controller.get_all_status()) 
    184184        return sorted(valid_states) 
    185185 
     186    def get_all_ticket_fields(self): 
     187        """New method until full integration of the new fields.""" 
     188        fields = self.get_ticket_fields() 
     189         
     190        # append the new ones 
     191        fields.extend([{'name': 'time', 'type': 'date', 'label': 'Created'}, 
     192                       {'name': 'changetime', 'type': 'date',  
     193                            'label': 'Modified'}]) 
     194         
     195        return fields 
     196 
    186197    def get_ticket_fields(self): 
    187198        """Returns the list of fields available for tickets.""" 
    188199        from trac.ticket import model 
  • trac/ticket/query.py

     
    4343from trac.wiki.api import IWikiSyntaxProvider, parse_args 
    4444from trac.wiki.macros import WikiMacroBase # TODO: should be moved in .api 
    4545 
     46is_op = lambda x: x in ['!', '<', '>'] 
     47 
    4648class QuerySyntaxError(Exception): 
    4749    """Exception raised when a ticket query cannot be parsed from a string.""" 
    4850 
     
    98100            rows = [] 
    99101        if verbose and 'description' not in rows: # 0.10 compatibility 
    100102            rows.append('description') 
    101         self.fields = TicketSystem(self.env).get_ticket_fields() 
     103        self.fields = TicketSystem(self.env).get_all_ticket_fields() 
    102104        field_names = [f['name'] for f in self.fields] 
    103105        self.cols = [c for c in cols or [] if c in field_names or  
    104106                     c in ('id', 'time', 'changetime')] 
     
    118120            self.group = None 
    119121 
    120122    def from_string(cls, env, string, **kw): 
     123        global is_op 
    121124        filters = string.split('&') 
    122125        kw_strs = ['order', 'group', 'page', 'max'] 
    123126        kw_arys = ['rows'] 
     
    137140            if field[-1] in ('~', '^', '$'): 
    138141                mode = field[-1] 
    139142                field = field[:-1] 
    140             if field[-1] == '!': 
    141                 neg = '!' 
     143            if is_op(field[-1]): 
     144                neg = field[-1] 
    142145                field = field[:-1] 
    143146            processed_values = [] 
    144147            for val in values.split('|'): 
     
    368371 
    369372    def get_sql(self, req=None, cached_ids=None): 
    370373        """Return a (sql, params) tuple for the query.""" 
     374        global is_op 
    371375        self.get_columns() 
    372376 
    373377        enum_columns = ('resolution', 'priority', 'severity') 
     
    413417                       % (col, col, col)) 
    414418 
    415419        def get_constraint_sql(name, value, mode, neg): 
     420            # strip the operator from the value 
     421            value = value[len(mode) + is_op(neg):] 
     422            # convert the value for non string fields 
     423            current_field = {} 
     424            for field in self.fields  : 
     425                if field['name'] == name : 
     426                    current_field = field 
     427                    break 
     428            if current_field.has_key('type') \ 
     429                and current_field['type'] == 'date' : 
     430                    value = int(value)  
     431             
     432            # add the table alias to the field name 
    416433            if name not in custom_fields: 
    417434                name = 't.' + name 
    418435            else: 
     
    420437            value = value[len(mode) + neg:] 
    421438 
    422439            if mode == '': 
    423                 return ("COALESCE(%s,'')%s=%%s" % (name, neg and '!' or ''), 
    424                         value) 
     440                return ("COALESCE(%s,'')%s=%%s" % (name,  
     441                                is_op(neg) and neg or ''), value) 
    425442            if not value: 
    426443                return None 
    427444            db = self.env.get_db_cnx() 
     
    432449                value = value + '%' 
    433450            elif mode == '$': 
    434451                value = '%' + value 
    435             return ("COALESCE(%s,'') %s%s" % (name, neg and 'NOT ' or '', 
     452            return ("COALESCE(%s,'') %s%s" % (name, neg == '!' and 'NOT ' or '', 
    436453                                              db.like()), 
    437454                    value) 
    438455 
     
    441458        for k, v in self.constraints.items(): 
    442459            if req: 
    443460                v = [val.replace('$USER', req.authname) for val in v] 
    444             # Determine the match mode of the constraint (contains, 
    445             # starts-with, negation, etc.) 
    446             neg = v[0].startswith('!') 
     461            # get the first character of the value, determine later if it's an 
     462            # operation 
     463            neg = '' 
    447464            mode = '' 
    448             if len(v[0]) > neg and v[0][neg] in ('~', '^', '$'): 
    449                 mode = v[0][neg] 
     465            if v[0] != '' : 
     466                neg = v[0][0] 
     467            mode = '' 
     468            if len(v[0]) > 1 and is_op(neg) and v[0][is_op(neg)] in ('~', '^', '$'): 
     469                    mode = v[0][is_op(neg)] 
    450470 
    451471            # Special case id ranges 
    452472            if k == 'id': 
    453473                ranges = Ranges() 
    454474                for r in v: 
    455                     r = r.replace('!', '') 
     475                    for ch in ['!', '<', '>'] : 
     476                        r = r.replace(ch, '') 
    456477                    ranges.appendrange(r) 
    457478                ids = [] 
    458479                id_clauses = [] 
     
    466487                if ids: 
    467488                    id_clauses.append('id IN (%s)' % (','.join(ids))) 
    468489                if id_clauses: 
    469                     clauses.append('%s(%s)' % (neg and 'NOT ' or '', 
     490                    clauses.append('%s(%s)' % (neg == '!' and 'NOT ' or '', 
    470491                                               ' OR '.join(id_clauses))) 
    471492            # Special case for exact matches on multiple values 
    472493            elif not mode and len(v) > 1: 
     
    475496                else: 
    476497                    col = k + '.value' 
    477498                clauses.append("COALESCE(%s,'') %sIN (%s)" 
    478                                % (col, neg and 'NOT ' or '', 
     499                               % (col, neg == '!' and 'NOT ' or '', 
    479500                                  ','.join(['%s' for val in v]))) 
    480                 args += [val[neg:] for val in v] 
     501                args += [val[is_op(neg):] for val in v] 
    481502            elif len(v) > 1: 
    482503                constraint_sql = filter(None, 
    483504                                        [get_constraint_sql(k, val, mode, neg) 
    484505                                         for val in v]) 
    485506                if not constraint_sql: 
    486507                    continue 
    487                 if neg: 
     508                if is_op(neg): 
    488509                    clauses.append("(" + " AND ".join( 
    489510                        [item[0] for item in constraint_sql]) + ")") 
    490511                else: 
     
    562583 
    563584    def template_data(self, context, tickets, orig_list=None, orig_time=None, 
    564585                      req=None): 
     586        global is_op 
    565587        constraints = {} 
    566588        for k, v in self.constraints.items(): 
    567589            constraint = {'values': [], 'mode': ''} 
    568590            for val in v: 
    569                 neg = val.startswith('!') 
    570                 if neg: 
     591                neg = '' 
     592                mode = '' 
     593                if val != '' : 
     594                    neg = val[0] 
     595                if val != '' and is_op(neg): 
    571596                    val = val[1:] 
    572597                mode = '' 
    573                 if val[:1] in ('~', '^', '$'): 
     598                if val != '' and val[:1] in ('~', '^', '$'): 
    574599                    mode, val = val[:1], val[1:] 
    575                 constraint['mode'] = (neg and '!' or '') + mode 
     600                constraint['mode'] = (is_op(neg) and neg or '') + mode 
    576601                constraint['values'].append(val) 
    577602            constraints[k] = constraint 
    578603 
     
    605630            {'name': _("begins with"), 'value': "^"}, 
    606631            {'name': _("ends with"), 'value': "$"}, 
    607632            {'name': _("is"), 'value': ""}, 
    608             {'name': _("is not"), 'value': "!"} 
     633            {'name': _("is not"), 'value': "!"}, 
     634            {'name': _("greater"), 'value': ">"}, 
     635            {'name': _("lesser"), 'value': "<"} 
    609636        ] 
    610637        modes['select'] = [ 
    611638            {'name': _("is"), 'value': ""}, 
     
    811838    def _get_constraints(self, req): 
    812839        constraints = {} 
    813840        ticket_fields = [f['name'] for f in 
    814                          TicketSystem(self.env).get_ticket_fields()] 
     841                         TicketSystem(self.env).get_all_ticket_fields()] 
    815842        ticket_fields.append('id') 
    816843 
    817844        # For clients without JavaScript, we remove constraints here if 
Note: See TracBrowser for help on using the repository browser.