source:
trunk/plugins/dashboardreportsplugin/dashboardreports/patch/trac-query.7385.diff
@
391
| Revision 391, 8.5 KB checked in by aculapov, 5 years ago (diff) |
|---|
-
trac/ticket/api.py
183 183 valid_states.update(controller.get_all_status()) 184 184 return sorted(valid_states) 185 185 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 186 197 def get_ticket_fields(self): 187 198 """Returns the list of fields available for tickets.""" 188 199 from trac.ticket import model -
trac/ticket/query.py
43 43 from trac.wiki.api import IWikiSyntaxProvider, parse_args 44 44 from trac.wiki.macros import WikiMacroBase # TODO: should be moved in .api 45 45 46 is_op = lambda x: x in ['!', '<', '>'] 47 46 48 class QuerySyntaxError(Exception): 47 49 """Exception raised when a ticket query cannot be parsed from a string.""" 48 50 … … 98 100 rows = [] 99 101 if verbose and 'description' not in rows: # 0.10 compatibility 100 102 rows.append('description') 101 self.fields = TicketSystem(self.env).get_ ticket_fields()103 self.fields = TicketSystem(self.env).get_all_ticket_fields() 102 104 field_names = [f['name'] for f in self.fields] 103 105 self.cols = [c for c in cols or [] if c in field_names or 104 106 c in ('id', 'time', 'changetime')] … … 118 120 self.group = None 119 121 120 122 def from_string(cls, env, string, **kw): 123 global is_op 121 124 filters = string.split('&') 122 125 kw_strs = ['order', 'group', 'page', 'max'] 123 126 kw_arys = ['rows'] … … 137 140 if field[-1] in ('~', '^', '$'): 138 141 mode = field[-1] 139 142 field = field[:-1] 140 if field[-1] == '!':141 neg = '!'143 if is_op(field[-1]): 144 neg = field[-1] 142 145 field = field[:-1] 143 146 processed_values = [] 144 147 for val in values.split('|'): … … 368 371 369 372 def get_sql(self, req=None, cached_ids=None): 370 373 """Return a (sql, params) tuple for the query.""" 374 global is_op 371 375 self.get_columns() 372 376 373 377 enum_columns = ('resolution', 'priority', 'severity') … … 413 417 % (col, col, col)) 414 418 415 419 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 416 433 if name not in custom_fields: 417 434 name = 't.' + name 418 435 else: … … 420 437 value = value[len(mode) + neg:] 421 438 422 439 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) 425 442 if not value: 426 443 return None 427 444 db = self.env.get_db_cnx() … … 432 449 value = value + '%' 433 450 elif mode == '$': 434 451 value = '%' + value 435 return ("COALESCE(%s,'') %s%s" % (name, neg and 'NOT ' or '',452 return ("COALESCE(%s,'') %s%s" % (name, neg == '!' and 'NOT ' or '', 436 453 db.like()), 437 454 value) 438 455 … … 441 458 for k, v in self.constraints.items(): 442 459 if req: 443 460 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 = '' 447 464 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)] 450 470 451 471 # Special case id ranges 452 472 if k == 'id': 453 473 ranges = Ranges() 454 474 for r in v: 455 r = r.replace('!', '') 475 for ch in ['!', '<', '>'] : 476 r = r.replace(ch, '') 456 477 ranges.appendrange(r) 457 478 ids = [] 458 479 id_clauses = [] … … 466 487 if ids: 467 488 id_clauses.append('id IN (%s)' % (','.join(ids))) 468 489 if id_clauses: 469 clauses.append('%s(%s)' % (neg and 'NOT ' or '',490 clauses.append('%s(%s)' % (neg == '!' and 'NOT ' or '', 470 491 ' OR '.join(id_clauses))) 471 492 # Special case for exact matches on multiple values 472 493 elif not mode and len(v) > 1: … … 475 496 else: 476 497 col = k + '.value' 477 498 clauses.append("COALESCE(%s,'') %sIN (%s)" 478 % (col, neg and 'NOT ' or '',499 % (col, neg == '!' and 'NOT ' or '', 479 500 ','.join(['%s' for val in v]))) 480 args += [val[ neg:] for val in v]501 args += [val[is_op(neg):] for val in v] 481 502 elif len(v) > 1: 482 503 constraint_sql = filter(None, 483 504 [get_constraint_sql(k, val, mode, neg) 484 505 for val in v]) 485 506 if not constraint_sql: 486 507 continue 487 if neg:508 if is_op(neg): 488 509 clauses.append("(" + " AND ".join( 489 510 [item[0] for item in constraint_sql]) + ")") 490 511 else: … … 562 583 563 584 def template_data(self, context, tickets, orig_list=None, orig_time=None, 564 585 req=None): 586 global is_op 565 587 constraints = {} 566 588 for k, v in self.constraints.items(): 567 589 constraint = {'values': [], 'mode': ''} 568 590 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): 571 596 val = val[1:] 572 597 mode = '' 573 if val [:1] in ('~', '^', '$'):598 if val != '' and val[:1] in ('~', '^', '$'): 574 599 mode, val = val[:1], val[1:] 575 constraint['mode'] = ( neg and '!'or '') + mode600 constraint['mode'] = (is_op(neg) and neg or '') + mode 576 601 constraint['values'].append(val) 577 602 constraints[k] = constraint 578 603 … … 605 630 {'name': _("begins with"), 'value': "^"}, 606 631 {'name': _("ends with"), 'value': "$"}, 607 632 {'name': _("is"), 'value': ""}, 608 {'name': _("is not"), 'value': "!"} 633 {'name': _("is not"), 'value': "!"}, 634 {'name': _("greater"), 'value': ">"}, 635 {'name': _("lesser"), 'value': "<"} 609 636 ] 610 637 modes['select'] = [ 611 638 {'name': _("is"), 'value': ""}, … … 811 838 def _get_constraints(self, req): 812 839 constraints = {} 813 840 ticket_fields = [f['name'] for f in 814 TicketSystem(self.env).get_ ticket_fields()]841 TicketSystem(self.env).get_all_ticket_fields()] 815 842 ticket_fields.append('id') 816 843 817 844 # For clients without JavaScript, we remove constraints here if
Note: See TracBrowser
for help on using the repository browser.
