Edgewall Software

Ticket #986: trac_mysql_r2659.patch

File trac_mysql_r2659.patch, 27.2 kB (added by trac@…, 3 years ago)

new patch against [2659] because the updates in [2653] caused some conflicts

  • trac/db_default.py

     
    1818from trac.db import Table, Column, Index 
    1919 
    2020# Database version identifier. Used for automatic upgrades. 
    21 db_version = 16 
     21db_version = 17 
    2222 
    2323def __mkreports(reports): 
    2424    """Utility function used to create report data in same syntax as the 
     
    8383        Column('author'), 
    8484        Column('message'), 
    8585        Index(['time'])], 
    86     Table('node_change', key=('rev', 'path', 'change'))[ 
     86    Table('node_change', key=('rev', 'path', 'change_type'))[ 
    8787        Column('rev'), 
    8888        Column('path'), 
    89         Column('kind', size=1), 
    90         Column('change', size=1), 
     89        Column('node_type', size=1), 
     90        Column('change_type', size=1), 
    9191        Column('base_path'), 
    9292        Column('base_rev'), 
    9393        Index(['rev'])], 
     
    437437) 
    438438 
    439439default_components = ('trac.About', 'trac.attachment', 
     440                      'trac.db.mysql_backend', 
    440441                      'trac.db.postgres_backend', 'trac.db.sqlite_backend', 
    441442                      'trac.mimeview.enscript', 'trac.mimeview.patch', 
    442443                      'trac.mimeview.php', 'trac.mimeview.rst', 
  • trac/ticket/api.py

     
    167167            return 
    168168        db = self.env.get_db_cnx() 
    169169        sql, args = query_to_sql(db, query, 'b.newvalue') 
    170         sql2, args2 = query_to_sql(db, query, 'summary||keywords||description||reporter||cc') 
     170        search_fields = ['summary', 'keywords', 'description', 'reporter', 'cc'] 
     171        sql_seq = [] 
     172        for f in search_fields: 
     173            subsql, subarg = query_to_sql(db, query, f) 
     174            sql_seq.append(subsql) 
     175            args += subarg 
     176        sql2 = ' OR '.join(sql_seq) 
    171177        cursor = db.cursor() 
    172         cursor.execute("SELECT DISTINCT a.summary,a.description,a.reporter, " 
    173                        "a.keywords,a.id,a.time FROM ticket a " 
    174                        "LEFT JOIN ticket_change b ON a.id = b.ticket " 
    175                        "WHERE (b.field='comment' AND %s ) OR %s" % (sql, sql2), 
    176                        args + args2) 
     178        sql3 = "SELECT DISTINCT a.summary,a.description,a.reporter, " + \ 
     179                       "a.keywords,a.id,a.time FROM ticket a " +  \ 
     180                       "LEFT JOIN ticket_change b ON a.id = b.ticket " + \ 
     181                       "WHERE (b.field='comment' AND %s ) OR %s" % (sql, sql2) 
     182        cursor.execute(sql3, args) 
    177183        for summary,desc,author,keywords,tid,date in cursor: 
    178184            yield (self.env.href.ticket(tid), 
    179185                   '#%d: %s' % (tid, util.escape(util.shorten_line(summary))), 
  • trac/db/tests/api.py

     
    3939                                       'host': 'localhost', 'port': 9431, 
    4040                                       'path': '/trac'}), 
    4141                         _parse_db_str('postgres://john:letmein@localhost:9431/trac')) 
     42    def test_mysql_simple(self): 
     43        self.assertEqual(('mysql', {'host': 'localhost', 'path': '/trac'}), 
     44                         _parse_db_str('mysql://localhost/trac')) 
    4245 
    43  
     46    def test_mysql_with_creds(self): 
     47        self.assertEqual(('mysql', {'user': 'john', 'password': 'letmein', 
     48                                       'host': 'localhost', 'port': 3306, 
     49                                       'path': '/trac'}), 
     50                         _parse_db_str('mysql://john:letmein@localhost:3306/trac')) 
    4451def suite(): 
    4552    return unittest.makeSuite(ParseConnectionStringTestCase,'test') 
    4653 
  • 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# All rights reserved. 
     7# 
     8# This software is licensed as described in the file COPYING, which 
     9# you should have received as part of this distribution. The terms 
     10# are also available at http://trac.edgewall.com/license.html. 
     11# 
     12# This software consists of voluntary contributions made by many 
     13# individuals. For the exact contribution history, see the revision 
     14# history and logs, available at http://projects.edgewall.com/trac/. 
     15# 
     16# Derived from postgres_backend.py 
     17# Author: Christopher Lenz <cmlenz@gmx.de>  
     18# Author: Jeff Weiss <trac@jeffweiss.org> 
     19 
     20from trac.core import * 
     21from trac.db.api import IDatabaseConnector 
     22from trac.db.util import ConnectionWrapper 
     23 
     24import MySQLdb 
     25 
     26class MySQLConnector(Component): 
     27    """MySQL database support.  Still extremely experimental! 
     28Currently only supports database urls of the following formats: 
     29mysql://user:password@host/database 
     30mysql://user:password@host:port/database 
     31""" 
     32 
     33    implements(IDatabaseConnector) 
     34 
     35    def get_supported_schemes(self): 
     36        return [('mysql', 1)] 
     37 
     38    def get_connection(self, path, user=None, password=None, host=None, 
     39                       port=None, params={}): 
     40        return MySQLConnection(path, user, password, host, port, params) 
     41 
     42    def init_db(self, path, user=None, password=None, host=None, port=None, 
     43                params={}): 
     44        cnx = self.get_connection(path, user, password, host, port, params) 
     45        cursor = cnx.cursor() 
     46        from trac.db_default import schema 
     47        for table in schema: 
     48            for stmt in self.to_sql(table): 
     49                self.env.log.debug(stmt) 
     50                cursor.execute(stmt) 
     51        cnx.commit() 
     52 
     53    def to_sql(self, table): 
     54        sql = ["CREATE TABLE %s (" % table.name] 
     55        coldefs = [] 
     56        textkeys = [] 
     57        textcols = [] 
     58        mytablekey = [] 
     59        num_key_text = 0 
     60        for column in table.columns: 
     61            ctype = column.type 
     62            if column.auto_increment: 
     63                ctype = "INT AUTO_INCREMENT" 
     64                # Overide the column type because otherwise it will screw 
     65                # up the rest of the code for indexes and constraints 
     66                column.type = 'int' 
     67            if column.name in table.key: 
     68                mytablekey.append(column.name) 
     69                if column.type == 'text': 
     70                    num_key_text += 1 
     71                    textkeys.append(column.name) 
     72            if column.type == 'text': 
     73                textcols.append(column.name) 
     74            coldefs.append("    `%s` %s" % (column.name, ctype)) 
     75        if len(table.key) >= 1: 
     76            if num_key_text == 0: 
     77                num_key_text = 1 
     78            size = 767 / num_key_text 
     79            keysize = "(%s)" % size 
     80            for key in textkeys: 
     81                if key in mytablekey: 
     82                    mytablekey.remove(key) 
     83                sizedkey =  '`'+key+'`' + keysize 
     84                mytablekey.append(sizedkey) 
     85            coldefs.append("    CONSTRAINT %s_pk PRIMARY KEY (%s)" 
     86                           % (table.name, ','.join(mytablekey))) 
     87        sql.append(',\n'.join(coldefs) + '\n)') 
     88        yield '\n'.join(sql) 
     89# This does not work because what I need to do is not add something about 
     90# the index size for the text fields because MySQL apparrently can't index 
     91# on the entire length of the text field 
     92        for index in table.indices: 
     93            myidxcols = set([]) 
     94            processedidx = set([]) 
     95            for col in index.columns: 
     96                if col in textcols: 
     97                    myidxcols.add(col) 
     98            myidx = set(index.columns) - myidxcols 
     99            for col in myidx: 
     100               escaped_col = '`'+col+'`' 
     101               processedidx.add(escaped_col)  
     102            if len(myidxcols) > 0: 
     103                size = 767 / len(myidxcols) 
     104                idxsize  = "(%s)" % size 
     105                for col in myidxcols: 
     106                   sizedidx = '`'+col+'`'+idxsize 
     107                   processedidx.add(sizedidx)  
     108            yield "CREATE INDEX %s_%s_idx ON %s (%s)" % (table.name,  
     109                   '_'.join(index.columns), table.name, ','.join(processedidx)) 
     110 
     111 
     112class MySQLConnection(ConnectionWrapper): 
     113    """Connection wrapper for MySQL.""" 
     114 
     115    poolable = True 
     116 
     117    def __init__(self, path, usr=None, password=None, hst=None, prt=None, 
     118                 params={}): 
     119        if prt: 
     120            cnx = MySQLdb.connect(db=path[1:], user=usr, passwd=password, host=hst, port=prt) 
     121        else: 
     122            cnx = MySQLdb.connect(db=path[1:], user=usr, passwd=password, host=hst) 
     123 
     124        ConnectionWrapper.__init__(self, cnx) 
     125 
     126    def cast(self, column, type): 
     127        # Temporary hack needed for the union of selects in the search module 
     128        return 'CAST(%s AS %s)' % (column, type) 
     129 
     130    def like(self): 
     131        # Temporary hack needed for the case-insensitive string matching in the 
     132        # search module 
     133        return 'LIKE' 
     134 
     135    def get_last_id(self, cursor, table, column='id'): 
     136        sql = "SELECT MAX(%s) FROM %s" % (column, table) 
     137        cursor.execute(sql) 
     138        return cursor.fetchone()[0] 
  • trac/versioncontrol/api.py

     
    132132    DIRECTORY = "dir" 
    133133    FILE = "file" 
    134134 
    135     def __init__(self, path, rev, kind): 
    136         assert kind in (Node.DIRECTORY, Node.FILE), "Unknown node kind %s" % kind 
     135    def __init__(self, path, rev, node_type): 
     136        assert node_type in (Node.DIRECTORY, Node.FILE), "Unknown node node_type %s" % node_type 
    137137        self.path = str(path) 
    138138        self.rev = rev 
    139         self.kind = kind 
     139        self.node_type = node_type 
    140140 
    141141    def get_content(self): 
    142142        """ 
     
    187187        raise NotImplementedError 
    188188    last_modified = property(lambda x: x.get_last_modified()) 
    189189 
    190     isdir = property(lambda x: x.kind == Node.DIRECTORY) 
    191     isfile = property(lambda x: x.kind == Node.FILE) 
     190    isdir = property(lambda x: x.node_type == Node.DIRECTORY) 
     191    isfile = property(lambda x: x.node_type == Node.FILE) 
    192192 
    193193 
    194194class Changeset(object): 
     
    210210 
    211211    def get_changes(self): 
    212212        """ 
    213         Generator that produces a (path, kind, change, base_rev, base_path) 
     213        Generator that produces a (path, node_type, change_type, base_rev, base_path) 
    214214        tuple for every change in the changeset, where change can be one of 
    215215        Changeset.ADD, Changeset.COPY, Changeset.DELETE, Changeset.EDIT or 
    216         Changeset.MOVE, and kind is one of Node.FILE or Node.DIRECTORY. 
     216        Changeset.MOVE, and node_type is one of Node.FILE or Node.DIRECTORY. 
    217217        """ 
    218218        raise NotImplementedError 
    219219 
  • trac/versioncontrol/tests/svn_fs.py

     
    117117        node = self.repos.get_node('/trunk') 
    118118        self.assertEqual('trunk', node.name) 
    119119        self.assertEqual('/trunk', node.path) 
    120         self.assertEqual(Node.DIRECTORY, node.kind) 
     120        self.assertEqual(Node.DIRECTORY, node.node_type) 
    121121        self.assertEqual(14, node.rev) 
    122122        self.assertEqual(1133340423L, node.last_modified) 
    123123        node = self.repos.get_node('/trunk/README.txt') 
    124124        self.assertEqual('README.txt', node.name) 
    125125        self.assertEqual('/trunk/README.txt', node.path) 
    126         self.assertEqual(Node.FILE, node.kind) 
     126        self.assertEqual(Node.FILE, node.node_type) 
    127127        self.assertEqual(3, node.rev) 
    128128        self.assertEqual(1112361898, node.last_modified) 
    129129 
     
    131131        node = self.repos.get_node('/trunk', 1) 
    132132        self.assertEqual('trunk', node.name) 
    133133        self.assertEqual('/trunk', node.path) 
    134         self.assertEqual(Node.DIRECTORY, node.kind) 
     134        self.assertEqual(Node.DIRECTORY, node.node_type) 
    135135        self.assertEqual(1, node.rev) 
    136136        self.assertEqual(1112349652, node.last_modified) 
    137137        node = self.repos.get_node('/trunk/README.txt', 2) 
    138138        self.assertEqual('README.txt', node.name) 
    139139        self.assertEqual('/trunk/README.txt', node.path) 
    140         self.assertEqual(Node.FILE, node.kind) 
     140        self.assertEqual(Node.FILE, node.node_type) 
    141141        self.assertEqual(2, node.rev) 
    142142        self.assertEqual(1112361138, node.last_modified) 
    143143 
     
    370370        node = self.repos.get_node('/dir1') 
    371371        self.assertEqual('dir1', node.name) 
    372372        self.assertEqual('/dir1', node.path) 
    373         self.assertEqual(Node.DIRECTORY, node.kind) 
     373        self.assertEqual(Node.DIRECTORY, node.node_type) 
    374374        self.assertEqual(5, node.rev) 
    375375        self.assertEqual(1112372739, node.last_modified) 
    376376        node = self.repos.get_node('/README.txt') 
    377377        self.assertEqual('README.txt', node.name) 
    378378        self.assertEqual('/README.txt', node.path) 
    379         self.assertEqual(Node.FILE, node.kind) 
     379        self.assertEqual(Node.FILE, node.node_type) 
    380380        self.assertEqual(3, node.rev) 
    381381        self.assertEqual(1112361898, node.last_modified) 
    382382 
     
    384384        node = self.repos.get_node('/dir1', 4) 
    385385        self.assertEqual('dir1', node.name) 
    386386        self.assertEqual('/dir1', node.path) 
    387         self.assertEqual(Node.DIRECTORY, node.kind) 
     387        self.assertEqual(Node.DIRECTORY, node.node_type) 
    388388        self.assertEqual(4, node.rev) 
    389389        self.assertEqual(1112370155, node.last_modified) 
    390390        node = self.repos.get_node('/README.txt', 2) 
    391391        self.assertEqual('README.txt', node.name) 
    392392        self.assertEqual('/README.txt', node.path) 
    393         self.assertEqual(Node.FILE, node.kind) 
     393        self.assertEqual(Node.FILE, node.node_type) 
    394394        self.assertEqual(2, node.rev) 
    395395        self.assertEqual(1112361138, node.last_modified) 
    396396 
  • trac/versioncontrol/tests/cache.py

     
    6666        self.assertEquals(('0', 41000, '', ''), cursor.fetchone()) 
    6767        self.assertEquals(('1', 42000, 'joe', 'Import'), cursor.fetchone()) 
    6868        self.assertEquals(None, cursor.fetchone()) 
    69         cursor.execute("SELECT rev,path,kind,change,base_path,base_rev " 
     69        cursor.execute("SELECT rev,path,node_type,change_type,base_path,base_rev " 
    7070                       "FROM node_change") 
    7171        self.assertEquals(('1', 'trunk', 'D', 'A', None, None), 
    7272                          cursor.fetchone()) 
     
    8080                       "VALUES (0,41000,'','')") 
    8181        cursor.execute("INSERT INTO revision (rev,time,author,message) " 
    8282                       "VALUES (1,42000,'joe','Import')") 
    83         cursor.executemany("INSERT INTO node_change (rev,path,kind,change," 
     83        cursor.executemany("INSERT INTO node_change (rev,path,node_type,change_type," 
    8484                           "base_path,base_rev) VALUES ('1',%s,%s,%s,%s,%s)", 
    8585                           [('trunk', 'D', 'A', None, None), 
    8686                            ('trunk/README', 'F', 'A', None, None)]) 
     
    9999        cursor.execute("SELECT time,author,message FROM revision WHERE rev='2'") 
    100100        self.assertEquals((42042, 'joe', 'Update'), cursor.fetchone()) 
    101101        self.assertEquals(None, cursor.fetchone()) 
    102         cursor.execute("SELECT path,kind,change,base_path,base_rev " 
     102        cursor.execute("SELECT path,node_type,change_type,base_path,base_rev " 
    103103                       "FROM node_change WHERE rev='2'") 
    104104        self.assertEquals(('trunk/README', 'F', 'E', 'trunk/README', '1'), 
    105105                          cursor.fetchone()) 
     
    111111                       "VALUES (0,41000,'','')") 
    112112        cursor.execute("INSERT INTO revision (rev,time,author,message) " 
    113113                       "VALUES (1,42000,'joe','Import')") 
    114         cursor.executemany("INSERT INTO node_change (rev,path,kind,change," 
     114        cursor.executemany("INSERT INTO node_change (rev,path,node_type,change_type," 
    115115                           "base_path,base_rev) VALUES ('1',%s,%s,%s,%s,%s)", 
    116116                           [('trunk', 'D', 'A', None, None), 
    117117                            ('trunk/README', 'F', 'A', None, None)]) 
  • trac/versioncontrol/web_ui/changeset.py

     
    182182 
    183183        edits = [] 
    184184        idx = 0 
    185         for path, kind, change, base_path, base_rev in chgset.get_changes(): 
    186             info = {'change': change} 
     185        for path, node_type, change_type, base_path, base_rev in chgset.get_changes(): 
     186            info = {'change': change_type} 
    187187            if base_path: 
    188188                info['path.old'] = base_path 
    189189                info['rev.old'] = base_rev 
     
    194194                info['rev.new'] = chgset.rev 
    195195                info['browser_href.new'] = self.env.href.browser(path, 
    196196                                                                 rev=chgset.rev) 
    197             if change in (Changeset.COPY, Changeset.EDIT, Changeset.MOVE): 
    198                 edits.append((idx, path, kind, base_path, base_rev)) 
     197            if change_type in (Changeset.COPY, Changeset.EDIT, Changeset.MOVE): 
     198                edits.append((idx, path, node_type, base_path, base_rev)) 
    199199            req.hdf['changeset.changes.%d' % idx] = info 
    200200            idx += 1 
    201201 
     
    205205 
    206206        mimeview = Mimeview(self.env) 
    207207             
    208         for idx, path, kind, base_path, base_rev in edits: 
     208        for idx, path, node_type, base_path, base_rev in edits: 
    209209            old_node = repos.get_node(base_path or path, base_rev) 
    210210            new_node = repos.get_node(path, chgset.rev) 
    211211 
     
    227227                        del changed_props[k] 
    228228                req.hdf['changeset.changes.%d.props' % idx] = changed_props 
    229229 
    230             if kind == Node.DIRECTORY: 
     230            if node_type == Node.DIRECTORY: 
    231231                continue 
    232232 
    233233            # Content changes 
     
    269269        req.end_headers() 
    270270 
    271271        mimeview = Mimeview(self.env) 
    272  
    273         for path, kind, change, base_path, base_rev in chgset.get_changes(): 
    274             if change == Changeset.ADD: 
     272        for path, node_type, change_type, base_path, base_rev in chgset.get_changes(): 
     273            if change_type == Changeset.ADD: 
    275274                old_node = None 
    276275            else: 
    277276                old_node = repos.get_node(base_path or path, base_rev) 
    278             if change == Changeset.DELETE: 
     277            if change_type == Changeset.DELETE: 
    279278                new_node = None 
    280279            else: 
    281280                new_node = repos.get_node(path, chgset.rev) 
     
    283282            # TODO: Property changes 
    284283 
    285284            # Content changes 
    286             if kind == 'dir': 
     285            if node_type == 'dir': 
    287286                continue 
    288287 
    289288            new_content = old_content = '' 
     
    338337 
    339338        buf = StringIO() 
    340339        zipfile = ZipFile(buf, 'w', ZIP_DEFLATED) 
    341         for path, kind, change, base_path, base_rev in chgset.get_changes(): 
    342             if kind == Node.FILE and change != Changeset.DELETE: 
     340        for path, node_type, change_type, base_path, base_rev in chgset.get_changes(): 
     341            if node_type == Node.FILE and change_type != Changeset.DELETE: 
    343342                node = repos.get_node(path, chgset.rev) 
    344343                zipinfo = ZipInfo() 
    345344                zipinfo.filename = node.path 
     
    383382            return 
    384383        authzperm = SubversionAuthorizer(self.env, req.authname) 
    385384        db = self.env.get_db_cnx() 
    386         sql, args = query_to_sql(db, query, 'message||author') 
     385        query_fields = ['message', 'author'] 
     386        sql_seq = [] 
     387        args = [] 
     388        for f in query_fields: 
     389            subsql, subarg = query_to_sql(db, query, f) 
     390            sql_seq.append(subsql)  
     391            args += subarg 
     392        sql = ' OR '.join(sql_seq) 
    387393        cursor = db.cursor() 
    388394        cursor.execute("SELECT rev,time,author,message " 
    389395                       "FROM revision WHERE " + sql, args) 
  • trac/versioncontrol/cache.py

     
    1818from trac.versioncontrol import Changeset, Node, Repository, Authorizer 
    1919 
    2020 
    21 _kindmap = {'D': Node.DIRECTORY, 'F': Node.FILE} 
    22 _actionmap = {'A': Changeset.ADD, 'C': Changeset.COPY, 
     21_node_typemap = {'D': Node.DIRECTORY, 'F': Node.FILE} 
     22_change_typemap = {'A': Changeset.ADD, 'C': Changeset.COPY, 
    2323              'D': Changeset.DELETE, 'E': Changeset.EDIT, 
    2424              'M': Changeset.MOVE} 
    2525 
     
    6464            authz = self.repos.authz 
    6565            self.repos.authz = Authorizer() # remove permission checking 
    6666 
    67             kindmap = dict(zip(_kindmap.values(), _kindmap.keys())) 
    68             actionmap = dict(zip(_actionmap.values(), _actionmap.keys())) 
     67            node_typemap = dict(zip(_node_typemap.values(), _node_typemap.keys())) 
     68            change_typemap = dict(zip(_change_typemap.values(), _change_typemap.keys())) 
    6969            self.log.info("Syncing with repository (%s to %s)" 
    7070                          % (youngest_stored, self.repos.youngest_rev)) 
    7171            if youngest_stored: 
     
    7878                               "VALUES (%s,%s,%s,%s)", (str(current_rev), 
    7979                               changeset.date, changeset.author, 
    8080                               changeset.message)) 
    81                 for path,kind,action,base_path,base_rev in changeset.get_changes(): 
     81                for path,node_type,change_type,base_path,base_rev in changeset.get_changes(): 
    8282                    self.log.debug("Caching node change in [%s]: %s" 
    83                                    % (current_rev, (path, kind, action, 
     83                                   % (current_rev, (path, node_type, change_type, 
    8484                                      base_path, base_rev))) 
    85                     kind = kindmap[kind] 
    86                     action = actionmap[action] 
    87                     cursor.execute("INSERT INTO node_change (rev,path,kind," 
    88                                    "change,base_path,base_rev) " 
     85                    node_type = node_typemap[node_type] 
     86                    change_type = change_typemap[change_type] 
     87                    cursor.execute("INSERT INTO node_change (rev,path,node_type," 
     88                                   "change_type,base_path,base_rev) " 
    8989                                   "VALUES (%s,%s,%s,%s,%s,%s)", 
    90                                    (str(current_rev), path, kind, action, 
     90                                   (str(current_rev), path, node_type, change_type, 
    9191                                   base_path, base_rev)) 
    9292                current_rev = self.repos.next_rev(current_rev) 
    9393            self.db.commit() 
     
    141141 
    142142    def get_changes(self): 
    143143        cursor = self.db.cursor() 
    144         cursor.execute("SELECT path,kind,change,base_path,base_rev " 
     144        cursor.execute("SELECT path,node_type,change_type,base_path,base_rev " 
    145145                       "FROM node_change WHERE rev=%s " 
    146146                       "ORDER BY path", (self.rev,)) 
    147         for path, kind, change, base_path, base_rev in cursor: 
     147        for path, node_type, change_type, base_path, base_rev in cursor: 
    148148            if not self.authz.has_permission(path): 
    149149                # FIXME: what about the base_path? 
    150150                continue 
    151             kind = _kindmap[kind] 
    152             change = _actionmap[change] 
    153             yield path, kind, change, base_path, base_rev 
     151            node_type = _node_typemap[node_type] 
     152            change_type = _change_typemap[change_type] 
     153            yield path, node_type, change_type, base_path, base_rev 
  • trac/upgrades/db17.py

     
     1from trac.db import Table, Column, Index, DatabaseManager 
     2 
     3def do_upgrade(env, ver, cursor): 
     4    cursor.execute("CREATE TEMP TABLE node_change_old AS SELECT * FROM node_change") 
     5    cursor.execute("DROP TABLE node_change") 
     6 
     7    db = env.get_db_cnx() 
     8    node_change_table = Table('node_change', key=('rev', 'path', 'change_type'))[ 
     9        Column('rev'), 
     10        Column('path'), 
     11        Column('node_type', size=1), 
     12        Column('change_type', size=1), 
     13        Column('base_path'), 
     14        Column('base_rev'), 
     15        Index(['rev'])] 
     16    db_backend, _ = DatabaseManager(env)._get_connector() 
     17    for stmt in db_backend.to_sql(node_change_table): 
     18        cursor.execute(stmt) 
     19 
     20    cursor.execute("INSERT INTO node_change (rev,path,node_type,change_type,base_path,base_rev) " 
     21                   "SELECT rev,path,kind,change,base_path,base_rev " 
     22                   "FROM node_change_old") 
  • trac/web/session.py

     
    181181            # changed as to minimize the purging. 
    182182            mintime = now - PURGE_AGE 
    183183            self.env.log.debug('Purging old, expired, sessions.') 
    184             cursor.execute("DELETE FROM session WHERE authenticated=0 AND " 
    185                            "sid IN (SELECT sid FROM session WHERE " 
    186                            "var_name='last_visit' AND var_value < %s)", 
     184            # This is a temporary hack because MySQL doesn't support 
     185            # a delete statement with the subquery coming from the same 
     186            # table 
     187            cursor.execute("SELECT sid from session WHERE " 
     188                           "var_name='last_visit' AND var_value < %s", 
    187189                           (mintime,)) 
    188  
     190            sids = cursor.fetchall()  
     191            if sids and len(sids) >= 1: 
     192                vals = [] 
     193                sids_args = [] 
     194                for t in sids: 
     195                    vals.append(t[0]) 
     196                    sids_args.append("sid = %s") 
     197                sql = "DELETE FROM session WHERE authenticated = 0 AND (%s)" % ' OR '.join(sids_args) 
     198                cursor.execute(sql, vals) 
    189199            db.commit() 
  • templates/changeset.cs

     
    7070 </div> 
    7171</form><?cs /if ?> 
    7272 
    73 <?cs def:node_change(item,cl,kind) ?><?cs  
     73<?cs def:node_change(item,cl,node_type) ?><?cs  
    7474  set:ndiffs = len(item.diff) ?><?cs 
    7575  set:nprops = len(item.props) ?> 
    7676  <div class="<?cs var:cl ?>"></div><?cs  
     
    8181   <a title="Show entry in browser" href="<?cs 
    8282     var:item.browser_href.new ?>"><?cs var:item.path.new ?></a><?cs 
    8383  /if ?> 
    84   <span class="comment">(<?cs var:kind ?>)</span><?cs 
     84  <span class="comment">(<?cs var:node_type ?>)</span><?cs 
    8585  if:item.path.old && item.change == 'copy' || item.change == 'move' ?> 
    86    <small><em>(<?cs var:kind ?> from <a href="<?cs 
     86   <small><em>(<?cs var:node_type ?> from <a href="<?cs 
    8787    var:item.browser_href.old ?>" title="Show original file (rev. <?cs 
    8888    var:item.rev.old ?>)"><?cs var:item.path.old ?></a>)</em></small><?cs 
    8989  /if ?><?cs