Edgewall Software

Ticket #986: trac-mysql-r3030.patch

File trac-mysql-r3030.patch, 30.4 KB (added by amgad Mosleh <amgad.mosleh@…>, 6 years ago)

solved the problem of adding or viewing a ticket (the Illegal mix of collations )

  • new file trac/db/mysql_backend.py

    ------------------------------------------------------------
    revno: 40
    committer: Amgad Molseh <amgad.mosleh@rezayat.net>
    branch nick: trac-mysql
    timestamp: Tue 2006-04-04 14:30:36 -0500
    message:
      I fixed the select statement for retrieving the tickets by enforcing the use 
      of utf8 as the character set.
    ------------------------------------------------------------
    revno: 39
    committer: Andres Salomon <dilinger@lith>
    branch nick: trac-mysql
    timestamp: Tue 2006-03-21 19:28:36 -0500
    message:
      r37 was terribly broken; it stripped out quotes when it shouldn't have.
      This version only strips out quotes there's a variable in them.
    ------------------------------------------------------------
    revno: 38
    committer: Andres Salomon <dilinger@jack>
    branch nick: trac-mysql
    timestamp: Tue 2006-03-21 16:28:34 -0500
    message:
      Merge in upstream.
        ------------------------------------------------------------
        merged: dilinger@jack-20060321194024-7ec90d6fc8019b81
        committer: Andres Salomon <dilinger@jack>
        branch nick: trac.bzr
        timestamp: Tue 2006-03-21 14:40:24 -0500
        message:
           Updated to revision 3029.
    ------------------------------------------------------------
    revno: 37
    committer: Andres Salomon <dilinger@lith>
    branch nick: trac-mysql
    timestamp: Mon 2006-03-20 15:49:51 -0500
    message:
      replace a silly unnecessary concat that causes trouble w/ mysql4.1
    ------------------------------------------------------------
    revno: 36
    committer: Andres Salomon <dilinger@lith>
    branch nick: trac-mysql
    timestamp: Mon 2006-03-20 13:08:57 -0500
    message:
      Make the mysql client connection return results in unicode.  Note that the
      python-mysqldb docs mention two ways of doing this:
      
      use_unicode
      
          If True, CHAR and VARCHAR and TEXT columns are returned as Unicode strings, using the configured character set. It is best to set the default encoding in the server configuration, or client configuration (read with read_default_file). If you change the character set after connecting (MySQL-4.1 and later), you'll need to put the correct character set name in connection.charset.
      
          If False, text-like columns are returned as normal strings, but you can always write Unicode strings.
      
      charset
      
          If present, the connection character set will be changed to this character set, if they are not equal. Support for changing the character set requires MySQL-4.1 and later server; if the server is too old, UnsupportedError will be raised. This option implies use_unicode=True, but you can override this with use_unicode=False, though you probably shouldn't.
      
          If not present, the default character set is used.
      
      
      We stick w/ use_unicode for now, since it's supported by the version of
      python-mysqldb that's in debian sarge.
    ------------------------------------------------------------
    revno: 35
    committer: Andres Salomon <dilinger@lith>
    branch nick: trac-mysql
    timestamp: Mon 2006-03-20 11:50:55 -0500
    message:
      revert r29, as that was a mysql4.0 fix, and we're not going to bother
      supporting 4.0.
    ------------------------------------------------------------
    revno: 34
    committer: Andres Salomon <dilinger@lith>
    branch nick: trac-mysql
    timestamp: Mon 2006-03-20 11:18:06 -0500
    message:
      Add support for not specifying the password in the mysql url.  This should
      not be used in production, but it's handy for testing.
    ------------------------------------------------------------
    revno: 33
    committer: Andres Salomon <dilinger@jack>
    branch nick: trac-mysql
    timestamp: Mon 2006-03-20 10:51:54 -0500
    message:
      Merge in upstream.
        ------------------------------------------------------------
        merged: dilinger@jack-20060320155046-c8f36fca93bd45ce
        committer: Andres Salomon <dilinger@jack>
        branch nick: trac.bzr
        timestamp: Mon 2006-03-20 10:50:46 -0500
        message:
          Update to revision r3025.
    ------------------------------------------------------------
    revno: 32
    committer: Andres Salomon <dilinger@jack>
    branch nick: trac-mysql
    timestamp: Fri 2006-03-10 11:42:59 -0500
    message:
      arg, fix a buglet
    ------------------------------------------------------------
    revno: 31
    committer: Andres Salomon <dilinger@jack>
    branch nick: trac-mysql
    timestamp: Fri 2006-03-10 11:21:23 -0500
    message:
      mysql4.0 doesn't support the syntax "TEMP TABLE";
      use "TEMPORARY TABLE" instead.
    ------------------------------------------------------------
    revno: 30
    committer: Andres Salomon <dilinger@jack>
    branch nick: trac-mysql
    timestamp: Fri 2006-03-10 11:19:21 -0500
    message:
      sqlite doesn't support 'DROP TEMP TABLE'.
    ------------------------------------------------------------
    revno: 29
    committer: Andres Salomon <dilinger@jack>
    branch nick: trac-mysql
    timestamp: Fri 2006-03-10 11:15:51 -0500
    message:
      mysql 4.0 fix; use a temporary table instead of a subselect.
    ------------------------------------------------------------
    revno: 28
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Wed 2006-03-08 16:39:12 -0500
    message:
      Fix a sql query that works in sqlite but not in mysql.   Apparently, mysql
      cannot order by a function call; but it can order by results.  So, order by
      max(time) becomes max_time.
    ------------------------------------------------------------
    revno: 27
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Wed 2006-03-08 16:19:28 -0500
    message:
      Merge from upstream.
        ------------------------------------------------------------
        merged: dilinger@sticky-20060308210914-ae5799a553d22fdf
        committer: Andres Salomon <dilinger@sticky>
        branch nick: trac.bzr
        timestamp: Wed 2006-03-08 16:09:14 -0500
        message:
            Updated to revision 2975.
    ------------------------------------------------------------
    revno: 26
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Thu 2006-03-02 13:58:31 -0500
    message:
      bug fix; don't attempt to delete sessions if there are none that require
      deleting.
    ------------------------------------------------------------
    revno: 25
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Wed 2006-03-01 16:10:06 -0500
    message:
      Merge from upstream.
        ------------------------------------------------------------
        merged: dilinger@sticky-20060301183359-32fc32f3af06db89
        committer: Andres Salomon <dilinger@sticky>
        branch nick: trac.bzr
        timestamp: Wed 2006-03-01 13:33:59 -0500
        message:
          Updated to revision 2946.
    ------------------------------------------------------------
    revno: 24
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Wed 2006-03-01 15:57:02 -0500
    message:
      Update for mysql 4.0, which has different limits from 5.0.
    ------------------------------------------------------------
    revno: 23
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Wed 2006-03-01 02:43:02 -0500
    message:
      merge in wiki fix
        ------------------------------------------------------------
        merged: dilinger@sticky-20060301073759-1564545412d6e1b5
        committer: Andres Salomon <dilinger@sticky>
        branch nick: trac-wikicap
        timestamp: Wed 2006-03-01 02:37:59 -0500
        message:
          Fix a minor bug with a sql statement; the table name is 'wiki', not 'WIKI'.
    ------------------------------------------------------------
    revno: 22
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Wed 2006-03-01 02:28:27 -0500
    message:
      Fix an off-by-one error, and force the column type to 'int' if it's an
      auto_increment column.
    ------------------------------------------------------------
    revno: 21
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Wed 2006-03-01 02:14:57 -0500
    message:
      fix missing space between column name and attributes
    ------------------------------------------------------------
    revno: 20
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Wed 2006-03-01 02:14:24 -0500
    message:
      make the _collist() stuff more generic, and make it work for primary keys
      as well (since they use indexes internally)
    ------------------------------------------------------------
    revno: 19
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Wed 2006-03-01 01:50:13 -0500
    message:
      fix a minor typo; ',' instead of '.'.
    ------------------------------------------------------------
    revno: 18
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Wed 2006-03-01 01:45:51 -0500
    message:
      clean up the indices handling and other table-creation related stuff.
    ------------------------------------------------------------
    revno: 17
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Tue 2006-02-28 16:49:23 -0500
    message:
      fix a buglet in the sql rename
    ------------------------------------------------------------
    revno: 16
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Tue 2006-02-28 16:44:58 -0500
    message:
      Merge in 'sql' column rename.
        ------------------------------------------------------------
        merged: dilinger@sticky-20060228213408-099adca595b49c8f
        committer: Andres Salomon <dilinger@sticky>
        branch nick: trac-sqlcolfix
        timestamp: Tue 2006-02-28 16:34:08 -0500
        message:
          whoopsie, buglet
        ------------------------------------------------------------
        merged: dilinger@sticky-20060228210621-a9e71c84b349d7f5
        committer: Andres Salomon <dilinger@sticky>
        branch nick: trac-sqlcolfix
        timestamp: Tue 2006-02-28 16:06:21 -0500
        message:
          include the `sql` column rename in the db17 upgrade.
        ------------------------------------------------------------
        merged: dilinger@sticky-20060228205749-5743f07063ec2395
        committer: Andres Salomon <dilinger@sticky>
        branch nick: trac-sqlcolfix
        timestamp: Tue 2006-02-28 15:57:49 -0500
        message:
          Rename 'sql' column in report table to 'query', so it doesn't conflict w/
          mysql keyword.
    ------------------------------------------------------------
    revno: 15
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Tue 2006-02-28 14:20:39 -0500
    message:
      fix an issue w/ the port type; it requires an int, and was getting None.
    ------------------------------------------------------------
    revno: 14
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Tue 2006-02-28 02:40:33 -0500
    message:
      fix a string quoting issue in session stuff.
    ------------------------------------------------------------
    revno: 13
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Tue 2006-02-28 02:32:39 -0500
    message:
      fix quoting on sql query; oops!
    ------------------------------------------------------------
    revno: 12
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Tue 2006-02-28 01:59:23 -0500
    message:
      Merge from svn trunk.
        ------------------------------------------------------------
        merged: dilinger@sticky-20060227174735-49d5ae65e3431d91
        committer: Andres Salomon <dilinger@sticky>
        branch nick: trac.bzr
        timestamp: Mon 2006-02-27 12:47:35 -0500
        message:
          Updated to revision 2944.
        ------------------------------------------------------------
        merged: dilinger@sticky-20060227071606-94a113e7b55325fe
        committer: Andres Salomon <dilinger@sticky>
        branch nick: trac.bzr
        timestamp: Mon 2006-02-27 02:16:06 -0500
        message:
            Updated to revision 2943.
          
          This includes merges from my trac-search branch.
    ------------------------------------------------------------
    revno: 11
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Mon 2006-02-27 03:43:37 -0500
    message:
      oops, missed a spot for default args
    ------------------------------------------------------------
    revno: 10
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Mon 2006-02-27 03:41:55 -0500
    message:
      Clean up the connection function; expand names, specify a default host and
      port, etc.
    ------------------------------------------------------------
    revno: 9
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Mon 2006-02-27 03:29:42 -0500
    message:
      Add mysql to copyright file
    ------------------------------------------------------------
    revno: 8
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Mon 2006-02-27 03:28:58 -0500
    message:
      Only import MySQL python module if actually loading/initializing the trac
      mysql backend.
    ------------------------------------------------------------
    revno: 7
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Mon 2006-02-27 03:27:26 -0500
    message:
      Original implementation of get_last_id() was racy; if two db connections
      insert at the same time, one of the two will get the incorrect last id.
      This fixes it so that it's the last inserted id in the current connection,
      not globally.
    ------------------------------------------------------------
    revno: 6
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Mon 2006-02-27 03:21:21 -0500
    message:
      Begin w/ Jeff Weiss's mysql backend implementation.
    ------------------------------------------------------------
    revno: 5
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-mysql
    timestamp: Fri 2006-02-17 01:57:23 -0500
    message:
      Break apart a SQL query that includes a subselect that mysql doesn't support.
    ------------------------------------------------------------
    revno: 4
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-db-changes
    timestamp: Fri 2006-02-10 14:14:14 -0500
    message:
      svn update;
      Updated to revision 2894.
      
      Prior patch (revno 3) was merged into svn, but db17.py changes were not
      accepted.
    ------------------------------------------------------------
    revno: 3
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac-db-changes
    timestamp: Thu 2006-02-09 19:08:20 -0500
    message:
      Rename a few node_change column names, as documented in #986.  The problem
      is that 'changes' is a mysql keyword.
    ------------------------------------------------------------
    revno: 2
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac
    timestamp: Thu 2006-02-09 16:18:36 -0500
    message:
      svn update:
      Updated to revision 2881.
    ------------------------------------------------------------
    revno: 1
    committer: Andres Salomon <dilinger@sticky>
    branch nick: trac
    timestamp: Wed 2006-02-08 17:26:52 -0500
    message:
      SVN snapshot of trac;
      
      "Updated to revision 2880."
    === added file 'trac/db/mysql_backend.py'
    - +  
     1# -*- coding: iso8859-1 -*- 
     2# 
     3# Copyright (C) 2005 Edgewall Software 
     4# Copyright (C) 2005 Christopher Lenz <cmlenz@gmx.de> 
     5# Copyright (C) 2005 Jeff Weiss <trac@jeffweiss.org> 
     6# Copyright (C) 2006 Andres Salomon <dilinger@athenacr.com> 
     7# All rights reserved. 
     8# 
     9# This software is licensed as described in the file COPYING, which 
     10# you should have received as part of this distribution. The terms 
     11# are also available at http://trac.edgewall.com/license.html. 
     12# 
     13# This software consists of voluntary contributions made by many 
     14# individuals. For the exact contribution history, see the revision 
     15# history and logs, available at http://projects.edgewall.com/trac/. 
     16# 
     17# Derived from postgres_backend.py 
     18# Author: Christopher Lenz <cmlenz@gmx.de>  
     19# Author: Jeff Weiss <trac@jeffweiss.org> 
     20 
     21from trac.core import * 
     22from trac.db.api import IDatabaseConnector 
     23from trac.db.util import ConnectionWrapper 
     24 
     25class MySQLConnector(Component): 
     26    """MySQL database support for version 4.1 and greater. 
     27Database urls should be of the form: 
     28mysql://user[:password]@host[:port]/database 
     29""" 
     30 
     31    implements(IDatabaseConnector) 
     32 
     33    def get_supported_schemes(self): 
     34        return [('mysql', 1)] 
     35 
     36    def get_connection(self, path, user=None, password=None, host=None, 
     37                       port=None, params={}): 
     38        return MySQLConnection(path, user, password, host, port, params) 
     39 
     40    def init_db(self, path, user=None, password=None, host=None, port=None, 
     41                params={}): 
     42        cnx = self.get_connection(path, user, password, host, port, params) 
     43        cursor = cnx.cursor() 
     44        from trac.db_default import schema 
     45        for table in schema: 
     46            for stmt in self.to_sql(table): 
     47                self.env.log.debug(stmt) 
     48                cursor.execute(stmt) 
     49        cnx.commit() 
     50 
     51    def _collist(self, table, columns): 
     52        """ 
     53        Take a list of columns and impose limits on each so that indexing 
     54        works properly.  Some Versions of MySQL limit each index prefix to 
     55        500 bytes total, with a max of 255 bytes per column. 
     56        """ 
     57        cols = [] 
     58        limit = 500 / len(columns) 
     59        if limit > 255: 
     60            limit = 255 
     61        for c in columns: 
     62            name = '`%s`' % c 
     63            table_col = filter((lambda x: x.name == c), table.columns) 
     64            if len(table_col) == 1 and table_col[0].type.lower() == 'text': 
     65                name += '(%s)' % limit 
     66            # For non-text columns, we simply throw away the extra bytes. 
     67            # That could certainly be optimized better, but for now let's KISS. 
     68            cols.append(name) 
     69        return ','.join(cols) 
     70 
     71    def to_sql(self, table): 
     72        sql = ['CREATE TABLE %s (' % table.name] 
     73        coldefs = [] 
     74        for column in table.columns: 
     75            ctype = column.type 
     76            if column.auto_increment: 
     77                ctype = 'INT UNSIGNED NOT NULL AUTO_INCREMENT' 
     78                # Override the column type, as a text field cannot 
     79                # use auto_increment. 
     80                column.type = 'int' 
     81            coldefs.append('    `%s` %s' % (column.name, ctype)) 
     82        if len(table.key) > 0: 
     83            coldefs.append('    PRIMARY KEY (%s)' % 
     84                           self._collist(table, table.key)) 
     85        sql.append(',\n'.join(coldefs) + '\n)') 
     86        yield '\n'.join(sql) 
     87        for index in table.indices: 
     88            yield 'CREATE INDEX %s_%s_idx ON %s (%s);' % (table.name, 
     89                  '_'.join(index.columns), table.name, 
     90                  self._collist(table, index.columns)) 
     91 
     92class MySQLConnection(ConnectionWrapper): 
     93    """Connection wrapper for MySQL.""" 
     94 
     95    poolable = True 
     96 
     97    def __init__(self, path, user=None, password=None, host=None, 
     98                 port=None, params={}): 
     99        import MySQLdb 
     100 
     101        if path.startswith('/'): 
     102            path = path[1:] 
     103        if password == None: 
     104            password = '' 
     105        if port == None: 
     106            port = 3306 
     107        # XXX: or do we want "charset='UNICODE'"?  it's unsupported in debian 
     108        # 3.1's python-mysqldb 
     109        cnx = MySQLdb.connect(db=path, user=user, passwd=password, host=host, 
     110                              port=port, use_unicode=True) 
     111        ConnectionWrapper.__init__(self, cnx) 
     112 
     113    def cast(self, column, type): 
     114        # Temporary hack needed for the union of selects in the search module 
     115        return 'CAST(%s AS %s)' % (column, type) 
     116 
     117    def like(self): 
     118        # Temporary hack needed for the case-insensitive string matching in the 
     119        # search module 
     120        return 'LIKE' 
     121 
     122    def get_last_id(self, cursor, table, column='id'): 
     123        return self.cnx.insert_id() 
  • trac/db/tests/api.py

    === modified file 'trac/db/tests/api.py'
     
    4040                                       'path': '/trac'}), 
    4141                         _parse_db_str('postgres://john:letmein@localhost:9431/trac')) 
    4242 
     43    def test_mysql_simple(self): 
     44        self.assertEqual(('mysql', {'host': 'localhost', 'path': '/trac'}), 
     45                         _parse_db_str('mysql://localhost/trac')) 
     46 
     47    def test_mysql_with_creds(self): 
     48        self.assertEqual(('mysql', {'user': 'john', 'password': 'letmein', 
     49                                    'host': 'localhost', 'port': 3306, 
     50                                    'path': '/trac'}), 
     51                         _parse_db_str('mysql://john:letmein@localhost:3306/trac')) 
    4352 
    4453def suite(): 
    4554    return unittest.makeSuite(ParseConnectionStringTestCase,'test') 
  • trac/db_default.py

    === modified file 'trac/db_default.py'
     
    148148        Column('id', auto_increment=True), 
    149149        Column('author'), 
    150150        Column('title'), 
    151         Column('sql'), 
     151        Column('query'), 
    152152        Column('description')], 
    153153] 
    154154 
     
    379379             ('name', 'value'), 
    380380               (('database_version', str(db_version)),)), 
    381381           ('report', 
    382              ('author', 'title', 'sql', 'description'), 
     382             ('author', 'title', 'query', 'description'), 
    383383               __mkreports(reports))) 
    384384 
    385385default_config = \ 
     
    445445 
    446446default_components = ('trac.About', 'trac.attachment', 
    447447                      'trac.db.postgres_backend', 'trac.db.sqlite_backend', 
     448                      'trac.db.mysql_backend', 
    448449                      'trac.mimeview.enscript', 'trac.mimeview.patch', 
    449450                      'trac.mimeview.php', 'trac.mimeview.rst', 
    450451                      'trac.mimeview.silvercity', 'trac.mimeview.txtl', 
  • trac/ticket/report.py

    === modified file 'trac/ticket/report.py'
     
    122122            req.redirect(self.env.href.report()) 
    123123 
    124124        title = req.args.get('title', '') 
    125         sql = req.args.get('sql', '') 
     125        query = req.args.get('query', '') 
    126126        description = req.args.get('description', '') 
    127127        cursor = db.cursor() 
    128         cursor.execute("INSERT INTO report (title,sql,description) " 
    129                        "VALUES (%s,%s,%s)", (title, sql, description)) 
     128        cursor.execute("INSERT INTO report (title,query,description) " 
     129                       "VALUES (%s,%s,%s)", (title, query, description)) 
    130130        id = db.get_last_id(cursor, 'report') 
    131131        db.commit() 
    132132        req.redirect(self.env.href.report(id)) 
     
    150150 
    151151        if not req.args.has_key('cancel'): 
    152152            title = req.args.get('title', '') 
    153             sql = req.args.get('sql', '') 
     153            query = req.args.get('query', '') 
    154154            description = req.args.get('description', '') 
    155155            cursor = db.cursor() 
    156             cursor.execute("UPDATE report SET title=%s,sql=%s,description=%s " 
    157                            "WHERE id=%s", (title, sql, description, id)) 
     156            cursor.execute("UPDATE report SET title=%s,query=%s,description=%s " 
     157                           "WHERE id=%s", (title, query, description, id)) 
    158158            db.commit() 
    159159        req.redirect(self.env.href.report(id)) 
    160160 
     
    178178    def _render_editor(self, req, db, id, copy=False): 
    179179        if id == -1: 
    180180            req.perm.assert_permission('REPORT_CREATE') 
    181             title = sql = description = '' 
     181            title = query = description = '' 
    182182        else: 
    183183            req.perm.assert_permission('REPORT_MODIFY') 
    184184            cursor = db.cursor() 
    185             cursor.execute("SELECT title,description,sql FROM report " 
     185            cursor.execute("SELECT title,description,query FROM report " 
    186186                           "WHERE id=%s", (id,)) 
    187187            row = cursor.fetchone() 
    188188            if not row: 
     
    190190                                     'Invalid Report Number') 
    191191            title = row[0] or '' 
    192192            description = row[1] or '' 
    193             sql = row[2] or '' 
     193            query = row[2] or '' 
    194194 
    195195        if copy: 
    196196            title += ' (copy)' 
     
    207207        req.hdf['report.id'] = id 
    208208        req.hdf['report.mode'] = 'edit' 
    209209        req.hdf['report.title'] = title 
    210         req.hdf['report.sql'] = sql 
     210        req.hdf['report.sql'] = query 
    211211        req.hdf['report.description'] = description 
    212212 
    213213    def _render_view(self, req, db, id): 
     
    404404            description = 'This is a list of reports available.' 
    405405        else: 
    406406            cursor = db.cursor() 
    407             cursor.execute("SELECT title,sql,description from report " 
     407            cursor.execute("SELECT title,query,description from report " 
    408408                           "WHERE id=%s", (id,)) 
    409409            row = cursor.fetchone() 
    410410            if not row: 
     
    439439            req.hdf['report.var.' + aname] = arg 
    440440            values.append(arg) 
    441441 
    442         # simple parameter substitution outside literal 
     442        # simple parameter substitution 
    443443        def repl(match): 
    444444            add_value(match.group(1)) 
    445445            return '%s' 
    446446 
    447         # inside a literal break it and concatenate with the parameter 
    448         def repl_literal(match): 
    449             add_value(match.group(1)) 
    450             return "' || %s || '" 
    451  
    452         var_re = re.compile("[$]([A-Z]+)") 
     447        var_re = re.compile("'?[$]([A-Z]+)'?") 
    453448        sql_io = StringIO() 
    454449 
    455450        # break SQL into literals and non-literals to handle replacing 
    456451        # variables within them with query parameters 
    457452        for expr in re.split("('(?:[^']|(?:''))*')", sql): 
    458             if expr.startswith("'"): 
    459                 sql_io.write(var_re.sub(repl_literal, expr)) 
    460             else: 
    461                 sql_io.write(var_re.sub(repl, expr)) 
     453            sql_io.write(var_re.sub(repl, expr)) 
    462454        return sql_io.getvalue(), values 
    463455 
    464456    def _render_csv(self, req, cols, rows, sep=','): 
  • trac/upgrades/db17.py

    === modified file 'trac/upgrades/db17.py'
     
    22 
    33def do_upgrade(env, ver, cursor): 
    44    """Rename the columns `kind` and `change` in the `node_change` table for 
    5     compatibity with MySQL. 
     5    compatibity with MySQL, as well as the `sql` column in the `reports` table. 
    66    """ 
    7     cursor.execute("CREATE TEMP TABLE nc_old AS SELECT * FROM node_change") 
     7    db_connector, _ = DatabaseManager(env)._get_connector() 
     8 
     9    # alter node_change table 
     10    cursor.execute("CREATE TEMPORARY TABLE nc_old AS SELECT * FROM node_change") 
    811    cursor.execute("DROP TABLE node_change") 
    912 
    1013    table = Table('node_change', key=('rev', 'path', 'change_type'))[ 
     
    1619        Column('base_rev'), 
    1720        Index(['rev']) 
    1821    ] 
    19     db_connector, _ = DatabaseManager(env)._get_connector() 
    2022    for stmt in db_connector.to_sql(table): 
    2123        cursor.execute(stmt) 
    2224 
    2325    cursor.execute("INSERT INTO node_change (rev,path,node_type,change_type," 
    2426                   "base_path,base_rev) SELECT rev,path,kind,change," 
    2527                   "base_path,base_rev FROM nc_old") 
     28 
     29    # alter report table 
     30    cursor.execute("CREATE TEMPORARY TABLE report_old AS SELECT * FROM report") 
     31    cursor.execute("DROP TABLE report") 
     32 
     33    table = Table('report', key='id')[ 
     34        Column('id', auto_increment=True), 
     35        Column('author'), 
     36        Column('title'), 
     37        Column('query'), 
     38        Column('description') 
     39    ] 
     40    for stmt in db_connector.to_sql(table): 
     41        cursor.execute(stmt) 
     42 
     43    cursor.execute("INSERT INTO report (id,author,title,query,description) " 
     44                   "SELECT id,author,title,sql,description FROM report_old") 
  • trac/web/session.py

    === modified file 'trac/web/session.py'
     
    182182            # changed as to minimize the purging. 
    183183            mintime = now - PURGE_AGE 
    184184            self.env.log.debug('Purging old, expired, sessions.') 
    185             cursor.execute("DELETE FROM session WHERE authenticated=0 AND " 
    186                            "sid IN (SELECT sid FROM session WHERE " 
    187                            "var_name='last_visit' AND var_value < %s)", 
     185            cursor.execute("SELECT DISTINCT sid FROM session WHERE " 
     186                           "var_name='last_visit' AND var_value < %s", 
    188187                           (mintime,)) 
    189  
     188            args = cursor.fetchall() 
     189            if args: 
     190                sql = 'DELETE FROM session WHERE authenticated = 0 AND (' 
     191                sql += ' OR '.join(['sid = %s'] * len(args)) + ')' 
     192                cursor.execute(sql, args) 
    190193            db.commit() 
  • trac/wiki/macros.py

    === modified file 'trac/wiki/macros.py'
     
    9898        db = self.env.get_db_cnx() 
    9999        cursor = db.cursor() 
    100100 
    101         sql = 'SELECT name, max(time) FROM wiki' 
     101        sql = 'SELECT name, max(time) AS max_time FROM wiki' 
    102102        args = [] 
    103103        if prefix: 
    104104            sql += ' WHERE name LIKE %s' 
    105105            args.append(prefix + '%') 
    106         sql += ' GROUP BY name ORDER BY max(time) DESC' 
     106        sql += ' GROUP BY name ORDER BY max_time DESC' 
    107107        if limit: 
    108108            sql += ' LIMIT %s' 
    109109            args.append(limit) 
  • trac/ticket/model.py

    === modified file 'trac/ticket/model.py'
     
    251251       if when: 
    252252           cursor.execute("SELECT time,author,field,oldvalue,newvalue " 
    253253                          "FROM ticket_change WHERE ticket=%s AND time=%s " 
    254254                          "UNION " 
    255                           "SELECT time,author,'attachment',null,filename " 
     255                         "SELECT _utf8 'time' COLLATE utf8_general_ci,_utf8 'author' COLLATE utf8_general_ci,_utf8 'attachment' COLLATE utf8_general_ci,_utf8 'null' COLLATE utf8_general_ci,_utf8 'filename' COLLATE utf8_general_ci " 
    256256                          "FROM attachment WHERE id=%s AND time=%s " 
    257257                          "UNION " 
    258                           "SELECT time,author,'comment',null,description " 
     258                         "SELECT _utf8 'time' COLLATE utf8_general_ci,_utf8 'author' COLLATE utf8_general_ci,_utf8 'comment' COLLATE utf8_general_ci,_utf8 'null' COLLATE utf8_general_ci,_utf8 'description' COLLATE utf8_general_ci "