Edgewall Software
Modify

Opened 5 years ago

#13279 new enhancement

Make cast method more robust

Reported by: Ryan J Ollos Owned by:
Priority: normal Milestone: next-major-releases
Component: database backend Version:
Severity: normal Keywords:
Cc: Branch:
Release Notes:
API Changes:
Internal Changes:

Description

Copied from 13078#comment:7:

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):  
    272272
    273273    def cast(self, column, type):
    274274        # 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)}
    276283
    277284    def concat(self, *args):
    278285        return '||'.join(args)

Attachments (0)

Change History (0)

Modify Ticket

Change Properties
Set your email in Preferences
Action
as new The ticket will remain with no owner.
The ticket will be disowned.
as The resolution will be set. Next status will be 'closed'.
The owner will be changed from (none) to anonymous. Next status will be 'assigned'.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.