#13078 closed defect (fixed)
TicketQuery for empty field of type time is incorrect
Reported by: | Ryan J Ollos | Owned by: | Jun Omae |
---|---|---|---|
Priority: | normal | Milestone: | 1.2.4 |
Component: | query system | Version: | |
Severity: | normal | Keywords: | postgresql ticketquery |
Cc: | Branch: | ||
Release Notes: |
Fix an error raised when custom field of type |
||
API Changes: | |||
Internal Changes: |
Description
The issue was raised in gdiscussion:trac-users:e7NvYuzgQKk. For a field of type time
(e.g. duedate
), [[TicketQuery(duedate=)]]
does not retrn the correct results.
It looks like the following patch might work:
-
trac/ticket/query.py
diff --git a/trac/ticket/query.py b/trac/ticket/query.py index c65f2bfc8..ca1f1d496 100644
a b class Query(object): 510 510 col = 'c.' + db.quote(name) 511 511 value = value[len(mode) + neg:] 512 512 513 if name in self.time_fields :513 if name in self.time_fields and value: 514 514 if '..' in value: 515 515 (start, end) = [each.strip() for each in 516 516 value.split('..', 1)]
Attachments (0)
Change History (9)
comment:1 by , 6 years ago
Keywords: | postgresql added |
---|
comment:3 by , 6 years ago
Owner: | set to |
---|---|
Status: | new → assigned |
Thanks for the testing. I'm going to push the changes.
comment:4 by , 6 years ago
The original reporter says nothing to see the log about the error but I confirm the following with ERROR level is logged.
12:26:18 PM Trac[formatter] ERROR: Macro TicketQuery(duedate=lastmonth..thismonth) failed for <Resource 'ticket'>: Traceback (most recent call last): File "/venv/trac/1.2.3/lib/python2.6/site-packages/trac/wiki/formatter.py", line 822, in _macro_formatter return macro.ensure_inline(macro.process(args), in_paragraph) File "/venv/trac/1.2.3/lib/python2.6/site-packages/trac/wiki/formatter.py", line 396, in process text = self.processor(text) File "/venv/trac/1.2.3/lib/python2.6/site-packages/trac/wiki/formatter.py", line 368, in _macro_processor text) File "/venv/trac/1.2.3/lib/python2.6/site-packages/trac/ticket/query.py", line 1410, in expand_macro tickets = query.execute(req) File "/venv/trac/1.2.3/lib/python2.6/site-packages/trac/ticket/query.py", line 303, in execute self.num_items = self._count(sql, args) File "/venv/trac/1.2.3/lib/python2.6/site-packages/trac/ticket/query.py", line 284, in _count % sql, args)[0][0] File "/venv/trac/1.2.3/lib/python2.6/site-packages/trac/db/api.py", line 122, in execute return db.execute(query, params) File "/venv/trac/1.2.3/lib/python2.6/site-packages/trac/db/util.py", line 128, in execute cursor.execute(query, params if params is not None else []) File "/venv/trac/1.2.3/lib/python2.6/site-packages/trac/db/util.py", line 61, in execute r = self.cursor.execute(sql_escape_percent(sql), args) DataError: invalid input syntax for integer: "" DataError: invalid input syntax for integer: ""
comment:5 by , 6 years ago
Release Notes: | modified (diff) |
---|---|
Resolution: | → fixed |
Status: | assigned → closed |
follow-up: 8 comment:7 by , 5 years ago
Another solution is using CASE ... END
and regular expression operator. I think we could make CAST(... AS int)
in PostgreSQL robust and same behavior in other databases.
trac=> SELECT (CASE trac(> WHEN value IS NULL THEN NULL trac(> WHEN value ~ '[-+]?[0-9]+$' THEN CAST(value AS int) trac(> ELSE 0 END) AS cast, trac-> value trac-> FROM unnest(ARRAY[NULL, '42', '+123', '-789', 'text', '']) AS value trac-> ; cast | value ------+------- | 42 | 42 123 | +123 -789 | -789 0 | text 0 | (6 rows)
-
trac/db/postgres_backend.py
diff --git a/trac/db/postgres_backend.py b/trac/db/postgres_backend.py index 3b5c9e92c..3775a9aa7 100644
a b class PostgreSQLConnection(ConnectionBase, ConnectionWrapper): 272 272 273 273 def cast(self, column, type): 274 274 # Temporary hack needed for the union of selects in the search module 275 return 'CAST(%s AS %s)' % (column, _type_map.get(type, type)) 275 if type in ('int', 'int64'): 276 fmt = "(CASE WHEN %(column)s IS NULL THEN NULL " \ 277 "WHEN %(column)s ~ '^[-+]?[0-9]+$' " \ 278 "THEN CAST(%(column)s AS %(type)s)" \ 279 "ELSE 0 END)" 280 else: 281 fmt = 'CAST(%(column)s AS %(type)s)' 282 return fmt % {'column': column, 'type': _type_map.get(type, type)} 276 283 277 284 def concat(self, *args): 278 285 return '||'.join(args)
follow-up: 9 comment:8 by , 5 years ago
Replying to Jun Omae:
Another solution is using
CASE ... END
and regular expression operator. I think we could makeCAST(... AS int)
in PostgreSQL robust and same behavior in other databases.
Looks interesting. Should we create a new ticket and target 1.4-stable?
comment:9 by , 5 years ago
Replying to Ryan J Ollos:
Looks interesting. Should we create a new ticket and target 1.4-stable?
⇒ #13279.
Root cause is that the error is raised when
CAST(... AS bigint)
is evaluated for non-integer text on PostgreSQL.We just have to prevent uses of
CAST()
for custom fields. Proposed changes in jomae.git@t13078+1.2-stable.