Edgewall Software

Ticket #7392: 0002-db-distinguish-between-read-and-write-access.patch

File 0002-db-distinguish-between-read-and-write-access.patch, 97.2 KB (added by Axel Gembe, 6 months ago)

[PATCH 2/3] db: distinguish between read and write access

  • trac/admin/console.py

    From be47fc2da756e091f5da22b2dfd5ba1f2aa3d1d2 Mon Sep 17 00:00:00 2001
    From: Axel Gembe <ago@bastart.eu.org>
    Date: Thu, 26 Jun 2008 13:59:28 +0200
    Subject: [PATCH 2/3] db: distinguish between read and write access
    
    This makes the existing code use the .read and .write members of the database
    pair to distinguish between read and write access. Note that if no write
    database is specified, the same database connection as for reading will be used
    for writing. While this already passes all the automated tests, this is still a
    big patch and I'm not sure everything is 100% correct, so please help me test
    it if you can.
    
    Signed-off-by: Axel Gembe <ago@bastart.eu.org>
    ---
     trac/admin/console.py                   |   25 +++---
     trac/admin/tests/console.py             |    4 +-
     trac/attachment.py                      |   16 ++--
     trac/db_default.py                      |   16 ++--
     trac/env.py                             |   12 ++--
     trac/perm.py                            |   14 ++--
     trac/search/api.py                      |    4 +-
     trac/test.py                            |   15 +++-
     trac/tests/env.py                       |    2 +-
     trac/tests/perm.py                      |   12 ++--
     trac/ticket/admin.py                    |   10 +-
     trac/ticket/api.py                      |    2 +-
     trac/ticket/model.py                    |  133 ++++++++++++++++---------------
     trac/ticket/notification.py             |    2 +-
     trac/ticket/query.py                    |   14 ++--
     trac/ticket/report.py                   |   30 ++++----
     trac/ticket/roadmap.py                  |   16 ++--
     trac/ticket/tests/model.py              |   20 +++---
     trac/ticket/tests/report.py             |    5 +-
     trac/ticket/web_ui.py                   |    8 +-
     trac/upgrades/db18.py                   |    2 +-
     trac/versioncontrol/api.py              |    2 +-
     trac/versioncontrol/cache.py            |   32 ++++---
     trac/versioncontrol/svn_fs.py           |    2 +-
     trac/versioncontrol/tests/cache.py      |   17 ++--
     trac/versioncontrol/web_ui/changeset.py |    2 +-
     trac/web/auth.py                        |   10 +-
     trac/web/session.py                     |   18 +++--
     trac/web/tests/auth.py                  |   16 ++--
     trac/web/tests/session.py               |   38 ++++++---
     trac/wiki/api.py                        |    2 +-
     trac/wiki/macros.py                     |    2 +-
     trac/wiki/model.py                      |   14 ++--
     trac/wiki/tests/model.py                |   16 +++--
     trac/wiki/web_ui.py                     |    6 +-
     35 files changed, 288 insertions(+), 251 deletions(-)
    
    diff --git a/trac/admin/console.py b/trac/admin/console.py
    index 7bf11c6..dc00276 100755
    a b  
    167167    def db_query(self, sql, cursor=None, params=None): 
    168168        if not cursor: 
    169169            cnx = self.db_open() 
    170             cursor = cnx.cursor() 
     170            cursor = cnx.read.cursor() 
    171171        if params: 
    172172            cursor.execute(sql, params) 
    173173        else: 
     
    178178    def db_update(self, sql, cursor=None, params=None): 
    179179        if not cursor: 
    180180            cnx = self.db_open() 
    181             cursor = cnx.cursor() 
     181            cursor = cnx.write.cursor() 
    182182        else: 
    183183            cnx = None 
    184184        if params: 
     
    186186        else: 
    187187            cursor.execute(sql) 
    188188        if cnx: 
    189             cnx.commit() 
     189            cnx.write.commit() 
    190190 
    191191    ## 
    192192    ## Utility methods 
     
    563563            # Add a few default wiki pages 
    564564            print ' Installing default wiki pages' 
    565565            cnx = self.__env.get_db_cnx() 
    566             cursor = cnx.cursor() 
     566            cursor = cnx.write.cursor() 
    567567            pages_dir = pkg_resources.resource_filename('trac.wiki',  
    568568                                                        'default-pages')  
    569569            self._do_wiki_load(pages_dir, cursor) 
    570             cnx.commit() 
     570            cnx.write.commit() 
    571571 
    572572            if repository_dir: 
    573573                try: 
     
    635635        from trac.versioncontrol.cache import CACHE_METADATA_KEYS 
    636636        print 'Resyncing repository history... ' 
    637637        cnx = self.db_open() 
    638         cursor = cnx.cursor() 
     638        cursor = cnx.write.cursor() 
    639639        cursor.execute("DELETE FROM revision") 
    640640        cursor.execute("DELETE FROM node_change") 
    641641        cursor.executemany("DELETE FROM system WHERE name=%s", 
    642642                           [(k,) for k in CACHE_METADATA_KEYS]) 
    643643        cursor.executemany("INSERT INTO system (name, value) VALUES (%s, %s)", 
    644644                           [(k, '') for k in CACHE_METADATA_KEYS]) 
    645         cnx.commit() 
     645        cnx.write.commit() 
    646646        repos = env.get_repository().sync(self._resync_feedback) 
     647        cursor = cnx.read.cursor() 
    647648        cursor.execute("SELECT count(rev) FROM revision") 
    648649        for cnt, in cursor: 
    649650            print cnt, 'revisions cached.', 
     
    950951        sql = ("INSERT INTO enum(value,type,name) " 
    951952               " SELECT 1+COALESCE(max(%(cast)s),0),'%(type)s','%(name)s'" 
    952953               "   FROM enum WHERE type='%(type)s'"  
    953                % {'type':type, 'name':name, 'cast': cnx.cast('value', 'int')}) 
    954         cursor = cnx.cursor() 
     954               % {'type':type, 'name':name, 'cast': cnx.write.cast('value', 'int')}) 
     955        cursor = cnx.write.cursor() 
    955956        self.db_update(sql, cursor) 
    956         cnx.commit() 
     957        cnx.write.commit() 
    957958 
    958959    def _do_enum_change(self, type, name, newname): 
    959960        enum_cls = self._enum_map[type] 
     
    11511152 
    11521153        # Bogus statement to lock the database while copying files 
    11531154        cnx = self.db_open() 
    1154         cursor = cnx.cursor() 
     1155        cursor = cnx.write.cursor() 
    11551156        cursor.execute("UPDATE system SET name=NULL WHERE name IS NULL") 
    11561157 
    11571158        try: 
     
    11671168            copytree(self.__env.path, dest, symlinks=1, skip=skip) 
    11681169        finally: 
    11691170            # Unlock database 
    1170             cnx.rollback() 
     1171            cnx.write.rollback() 
    11711172 
    11721173        print 'Hotcopy done.' 
    11731174 
  • trac/admin/tests/console.py

    diff --git a/trac/admin/tests/console.py b/trac/admin/tests/console.py
    index 66418c8..5746c71 100644
    a b  
    2727from trac.config import Configuration 
    2828from trac.env import Environment 
    2929from trac.admin import console 
    30 from trac.test import InMemoryDatabase 
     30from trac.test import InMemoryDatabase, DatabasePair 
    3131from trac.util.datefmt import get_date_format_hint 
    3232 
    3333STRIP_TRAILING_SPACE = re.compile(r'( +)$', re.MULTILINE) 
     
    6262    def get_db_cnx(self): 
    6363        if not hasattr(self, '_db'): 
    6464            self._db = InMemoryDatabase() 
    65         return self._db 
     65        return DatabasePair(self._db, self._db) 
    6666 
    6767    def create(self, db_str=None): 
    6868        pass 
  • trac/attachment.py

    diff --git a/trac/attachment.py b/trac/attachment.py
    index 71723b8..976cb39 100644
    a b  
    132132    def _fetch(self, filename, db=None): 
    133133        if not db: 
    134134            db = self.env.get_db_cnx() 
    135         cursor = db.cursor() 
     135        cursor = db.read.cursor() 
    136136        cursor.execute("SELECT filename,description,size,time,author,ipnr " 
    137137                       "FROM attachment WHERE type=%s AND id=%s " 
    138138                       "AND filename=%s ORDER BY time", 
     
    172172        else: 
    173173            handle_ta = False 
    174174 
    175         cursor = db.cursor() 
     175        cursor = db.write.cursor() 
    176176        cursor.execute("DELETE FROM attachment WHERE type=%s AND id=%s " 
    177177                       "AND filename=%s", (self.parent_realm, self.parent_id, 
    178178                       self.filename)) 
     
    183183                self.env.log.error('Failed to delete attachment file %s', 
    184184                                   self.path, exc_info=True) 
    185185                if handle_ta: 
    186                     db.rollback() 
     186                    db.write.rollback() 
    187187                raise TracError(_('Could not delete attachment')) 
    188188 
    189189        self.env.log.info('Attachment removed: %s' % self.title) 
    190190        if handle_ta: 
    191             db.commit() 
     191            db.write.commit() 
    192192 
    193193        for listener in AttachmentModule(self.env).change_listeners: 
    194194            listener.attachment_deleted(self) 
     
    224224            basename = os.path.basename(path).encode('ascii') 
    225225            filename = unicode_unquote(basename) 
    226226 
    227             cursor = db.cursor() 
     227            cursor = db.write.cursor() 
    228228            cursor.execute("INSERT INTO attachment " 
    229229                           "VALUES (%s,%s,%s,%s,%s,%s,%s,%s)", 
    230230                           (self.parent_realm, self.parent_id, filename, 
     
    237237                              self.author) 
    238238 
    239239            if handle_ta: 
    240                 db.commit() 
     240                db.write.commit() 
    241241 
    242242            for listener in AttachmentModule(self.env).change_listeners: 
    243243                listener.attachment_added(self) 
     
    248248    def select(cls, env, parent_realm, parent_id, db=None): 
    249249        if not db: 
    250250            db = env.get_db_cnx() 
    251         cursor = db.cursor() 
     251        cursor = db.read.cursor() 
    252252        cursor.execute("SELECT filename,description,size,time,author,ipnr " 
    253253                       "FROM attachment WHERE type=%s AND id=%s ORDER BY time", 
    254254                       (parent_realm, unicode(parent_id))) 
     
    441441        """ 
    442442        # Traverse attachment directory 
    443443        db = self.env.get_db_cnx() 
    444         cursor = db.cursor() 
     444        cursor = db.read.cursor() 
    445445        cursor.execute("SELECT type, id, filename, time, description, author " 
    446446                       "  FROM attachment " 
    447447                       "  WHERE time > %s AND time < %s " 
  • trac/db_default.py

    diff --git a/trac/db_default.py b/trac/db_default.py
    index 01354fc..cfb6966 100644
    a b  
    180180  FROM ticket t 
    181181  LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority' 
    182182  WHERE status <> 'closed' 
    183   ORDER BY """ + db.cast('p.value', 'int') + """, milestone, t.type, time 
     183  ORDER BY """ + db.write.cast('p.value', 'int') + """, milestone, t.type, time 
    184184"""), 
    185185#---------------------------------------------------------------------------- 
    186186 ('Active Tickets by Version', 
     
    202202  FROM ticket t 
    203203  LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority' 
    204204  WHERE status <> 'closed' 
    205   ORDER BY (version IS NULL),version, """ + db.cast('p.value', 'int') + 
     205  ORDER BY (version IS NULL),version, """ + db.write.cast('p.value', 'int') + 
    206206  """, t.type, time 
    207207"""), 
    208208#---------------------------------------------------------------------------- 
     
    226226  LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority' 
    227227  WHERE status <> 'closed'  
    228228  ORDER BY (milestone IS NULL),milestone, %s, t.type, time 
    229 """ % (db.concat("'Milestone '", 'milestone'), db.cast('p.value', 'int'))), 
     229""" % (db.write.concat("'Milestone '", 'milestone'), db.write.cast('p.value', 'int'))), 
    230230#---------------------------------------------------------------------------- 
    231231('Accepted, Active Tickets by Owner', 
    232232""" 
     
    242242  FROM ticket t 
    243243  LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority' 
    244244  WHERE status = 'accepted' 
    245   ORDER BY owner, """ + db.cast('p.value', 'int') + """, t.type, time 
     245  ORDER BY owner, """ + db.write.cast('p.value', 'int') + """, t.type, time 
    246246"""), 
    247247#---------------------------------------------------------------------------- 
    248248('Accepted, Active Tickets by Owner (Full Description)', 
     
    259259  FROM ticket t 
    260260  LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority' 
    261261  WHERE status = 'accepted' 
    262   ORDER BY owner, """ + db.cast('p.value', 'int') + """, t.type, time 
     262  ORDER BY owner, """ + db.write.cast('p.value', 'int') + """, t.type, time 
    263263"""), 
    264264#---------------------------------------------------------------------------- 
    265265('All Tickets By Milestone  (Including closed)', 
     
    282282  LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority' 
    283283  ORDER BY (milestone IS NULL), milestone DESC, (status = 'closed'),  
    284284        (CASE status WHEN 'closed' THEN changetime ELSE (-1) * %s END) DESC 
    285 """ % db.cast('p.value', 'int')), 
     285""" % db.write.cast('p.value', 'int')), 
    286286#---------------------------------------------------------------------------- 
    287287('My Tickets', 
    288288""" 
     
    300300  FROM ticket t 
    301301  LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority' 
    302302  WHERE t.status <> 'closed' AND owner = $USER 
    303   ORDER BY (status = 'accepted') DESC, """ + db.cast('p.value', 'int') +  
     303  ORDER BY (status = 'accepted') DESC, """ + db.write.cast('p.value', 'int') + 
    304304  """, milestone, t.type, time 
    305305"""), 
    306306#---------------------------------------------------------------------------- 
     
    323323  FROM ticket t 
    324324  LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority' 
    325325  WHERE status <> 'closed'  
    326   ORDER BY (owner = $USER) DESC, """ + db.cast('p.value', 'int') +  
     326  ORDER BY (owner = $USER) DESC, """ + db.write.cast('p.value', 'int') + 
    327327  """, milestone, t.type, time 
    328328""")) 
    329329 
  • trac/env.py

    diff --git a/trac/env.py b/trac/env.py
    index 11a4314..6810171 100644
    a b  
    322322        """ 
    323323        if not db: 
    324324            db = self.get_db_cnx() 
    325         cursor = db.cursor() 
     325        cursor = db.read.cursor() 
    326326        cursor.execute("SELECT value FROM system " 
    327327                       "WHERE name='%sdatabase_version'" % 
    328328                       (initial and 'initial_' or '')) 
     
    380380        """ 
    381381        if not cnx: 
    382382            cnx = self.get_db_cnx() 
    383         cursor = cnx.cursor() 
     383        cursor = cnx.read.cursor() 
    384384        cursor.execute("SELECT DISTINCT s.sid, n.value, e.value " 
    385385                       "FROM session AS s " 
    386386                       " LEFT JOIN session_attribute AS n ON (n.sid=s.sid " 
     
    440440            self.backup(backup_dest) 
    441441        for participant in upgraders: 
    442442            participant.upgrade_environment(db) 
    443         db.commit() 
     443        db.write.commit() 
    444444 
    445445        # Database schema may have changed, so close all connections 
    446446        self.shutdown() 
     
    473473    def environment_created(self): 
    474474        """Insert default data into the database.""" 
    475475        db = self.env.get_db_cnx() 
    476         cursor = db.cursor() 
     476        cursor = db.write.cursor() 
    477477        for table, cols, vals in db_default.get_data(db): 
    478478            cursor.executemany("INSERT INTO %s (%s) VALUES (%s)" % (table, 
    479479                               ','.join(cols), ','.join(['%s' for c in cols])), 
    480480                               vals) 
    481         db.commit() 
     481        db.write.commit() 
    482482        self._update_sample_config() 
    483483 
    484484    def environment_needs_upgrade(self, db): 
     
    490490        return True 
    491491 
    492492    def upgrade_environment(self, db): 
    493         cursor = db.cursor() 
     493        cursor = db.write.cursor() 
    494494        dbver = self.env.get_version() 
    495495        for i in range(dbver + 1, db_default.db_version + 1): 
    496496            name  = 'db%i' % i 
  • trac/perm.py

    diff --git a/trac/perm.py b/trac/perm.py
    index 9b65827..0540b5a 100644
    a b  
    171171 
    172172        actions = set([]) 
    173173        db = self.env.get_db_cnx() 
    174         cursor = db.cursor() 
     174        cursor = db.read.cursor() 
    175175        cursor.execute("SELECT username,action FROM permission") 
    176176        rows = cursor.fetchall() 
    177177        while True: 
     
    198198        # The optimized loop we had before didn't.  This is very inefficient, 
    199199        # but it works. 
    200200        db = self.env.get_db_cnx() 
    201         cursor = db.cursor() 
     201        cursor = db.read.cursor() 
    202202        result = set() 
    203203        users = set([u[0] for u in self.env.get_known_users()]) 
    204204        for user in users: 
     
    214214        The permissions are returned as a list of (subject, action) 
    215215        formatted tuples.""" 
    216216        db = self.env.get_db_cnx() 
    217         cursor = db.cursor() 
     217        cursor = db.read.cursor() 
    218218        cursor.execute("SELECT username,action FROM permission") 
    219219        return [(row[0], row[1]) for row in cursor] 
    220220 
    221221    def grant_permission(self, username, action): 
    222222        """Grants a user the permission to perform the specified action.""" 
    223223        db = self.env.get_db_cnx() 
    224         cursor = db.cursor() 
     224        cursor = db.write.cursor() 
    225225        cursor.execute("INSERT INTO permission VALUES (%s, %s)", 
    226226                       (username, action)) 
    227227        self.log.info('Granted permission for %s to %s' % (action, username)) 
    228         db.commit() 
     228        db.write.commit() 
    229229 
    230230    def revoke_permission(self, username, action): 
    231231        """Revokes a users' permission to perform the specified action.""" 
    232232        db = self.env.get_db_cnx() 
    233         cursor = db.cursor() 
     233        cursor = db.write.cursor() 
    234234        cursor.execute("DELETE FROM permission WHERE username=%s AND action=%s", 
    235235                       (username, action)) 
    236236        self.log.info('Revoked permission for %s to %s' % (action, username)) 
    237         db.commit() 
     237        db.write.commit() 
    238238 
    239239 
    240240class DefaultPermissionGroupProvider(Component): 
  • trac/search/api.py

    diff --git a/trac/search/api.py b/trac/search/api.py
    index cfd80f1..1402af9 100644
    a b  
    4747    """ 
    4848    assert columns and terms 
    4949 
    50     likes = ['%s %s' % (i, db.like()) for i in columns] 
     50    likes = ['%s %s' % (i, db.read.like()) for i in columns] 
    5151    c = ' OR '.join(likes) 
    5252    sql = '(' + ') AND ('.join([c] * len(terms)) + ')' 
    5353    args = [] 
    5454    for t in terms: 
    55         args.extend(['%' + db.like_escape(t) + '%'] * len(columns)) 
     55        args.extend(['%' + db.read.like_escape(t) + '%'] * len(columns)) 
    5656    return sql, tuple(args) 
    5757 
    5858def shorten_result(text='', keywords=[], maxlen=240, fuzz=60): 
  • trac/test.py

    diff --git a/trac/test.py b/trac/test.py
    index f79d078..0a96371 100755
    a b  
    3636from trac.util import translation 
    3737 
    3838 
     39class DatabasePair(object): 
     40    """ 
     41    Holds two database connections, one for reading and one for writing. 
     42    """ 
     43    def __init__(self, db, dbwr): 
     44        self.read = db 
     45        self.write = dbwr 
     46 
    3947def Mock(bases=(), *initargs, **kw): 
    4048    """ 
    4149    Simple factory for dummy classes that can be used as replacement for the  
     
    172180        ComponentManager.__init__(self) 
    173181        Component.__init__(self) 
    174182        self.enabled_components = enable or ['trac.*'] 
    175         self.db = InMemoryDatabase() 
     183        ndb = InMemoryDatabase() 
     184        self.db = DatabasePair(ndb, ndb) 
    176185        self.systeminfo = [('Python', sys.version)] 
    177186 
    178187        import trac 
     
    195204 
    196205        from trac import db_default 
    197206        if default_data: 
    198             cursor = self.db.cursor() 
     207            cursor = self.db.write.cursor() 
    199208            for table, cols, vals in db_default.get_data(self.db): 
    200209                cursor.executemany("INSERT INTO %s (%s) VALUES (%s)" 
    201210                                   % (table, ','.join(cols), 
    202211                                      ','.join(['%s' for c in cols])), 
    203212                                   vals) 
    204             self.db.commit() 
     213            self.db.write.commit() 
    205214             
    206215        self.known_users = [] 
    207216        translation.activate(Locale and Locale('en', 'US')) 
  • trac/tests/env.py

    diff --git a/trac/tests/env.py b/trac/tests/env.py
    index 681fd52..98a40e0 100644
    a b  
    2626 
    2727    def test_get_known_users(self): 
    2828        """Testing env.get_known_users""" 
    29         cursor = self.db.cursor() 
     29        cursor = self.db.write.cursor() 
    3030        cursor.executemany("INSERT INTO session VALUES (%s,%s,0)", 
    3131                           [('123', 0),('tom', 1), ('joe', 1), ('jane', 1)]) 
    3232        cursor.executemany("INSERT INTO session_attribute VALUES (%s,%s,%s,%s)", 
  • trac/tests/perm.py

    diff --git a/trac/tests/perm.py b/trac/tests/perm.py
    index a5d1d92..d022e83 100644
    a b  
    1515 
    1616    def test_simple_actions(self): 
    1717        db = self.env.get_db_cnx() 
    18         cursor = db.cursor() 
     18        cursor = db.write.cursor() 
    1919        cursor.executemany("INSERT INTO permission VALUES (%s,%s)", [ 
    2020                           ('john', 'WIKI_MODIFY'), ('john', 'REPORT_ADMIN'), 
    2121                           ('kate', 'TICKET_CREATE')]) 
     
    2525 
    2626    def test_simple_group(self): 
    2727        db = self.env.get_db_cnx() 
    28         cursor = db.cursor() 
     28        cursor = db.write.cursor() 
    2929        cursor.executemany("INSERT INTO permission VALUES (%s,%s)", [ 
    3030                           ('dev', 'WIKI_MODIFY'), ('dev', 'REPORT_ADMIN'), 
    3131                           ('john', 'dev')]) 
     
    3434 
    3535    def test_nested_groups(self): 
    3636        db = self.env.get_db_cnx() 
    37         cursor = db.cursor() 
     37        cursor = db.write.cursor() 
    3838        cursor.executemany("INSERT INTO permission VALUES (%s,%s)", [ 
    3939                           ('dev', 'WIKI_MODIFY'), ('dev', 'REPORT_ADMIN'), 
    4040                           ('admin', 'dev'), ('john', 'admin')]) 
     
    4343 
    4444    def test_mixed_case_group(self): 
    4545        db = self.env.get_db_cnx() 
    46         cursor = db.cursor() 
     46        cursor = db.write.cursor() 
    4747        cursor.executemany("INSERT INTO permission VALUES (%s,%s)", [ 
    4848                           ('Dev', 'WIKI_MODIFY'), ('Dev', 'REPORT_ADMIN'), 
    4949                           ('Admin', 'Dev'), ('john', 'Admin')]) 
     
    5252 
    5353    def test_builtin_groups(self): 
    5454        db = self.env.get_db_cnx() 
    55         cursor = db.cursor() 
     55        cursor = db.write.cursor() 
    5656        cursor.executemany("INSERT INTO permission VALUES (%s,%s)", [ 
    5757                           ('authenticated', 'WIKI_MODIFY'), 
    5858                           ('authenticated', 'REPORT_ADMIN'), 
     
    6464 
    6565    def test_get_all_permissions(self): 
    6666        db = self.env.get_db_cnx() 
    67         cursor = db.cursor() 
     67        cursor = db.write.cursor() 
    6868        cursor.executemany("INSERT INTO permission VALUES (%s,%s)", [ 
    6969                           ('dev', 'WIKI_MODIFY'), ('dev', 'REPORT_ADMIN'), 
    7070                           ('john', 'dev')]) 
  • trac/ticket/admin.py

    diff --git a/trac/ticket/admin.py b/trac/ticket/admin.py
    index 5aef567..2b9ba87 100644
    a b  
    9898                    for name in sel: 
    9999                        comp = model.Component(self.env, name, db=db) 
    100100                        comp.delete(db=db) 
    101                     db.commit() 
     101                    db.write.commit() 
    102102                    req.redirect(req.href.admin(cat, page)) 
    103103 
    104104                # Set default component 
     
    196196                    for name in sel: 
    197197                        mil = model.Milestone(self.env, name, db=db) 
    198198                        mil.delete(db=db) 
    199                     db.commit() 
     199                    db.write.commit() 
    200200                    req.redirect(req.href.admin(cat, page)) 
    201201 
    202202                # Set default milestone 
     
    278278                    for name in sel: 
    279279                        ver = model.Version(self.env, name, db=db) 
    280280                        ver.delete(db=db) 
    281                     db.commit() 
     281                    db.write.commit() 
    282282                    req.redirect(req.href.admin(cat, page)) 
    283283 
    284284                # Set default version 
     
    358358                    for name in sel: 
    359359                        enum = self._enum_cls(self.env, name, db=db) 
    360360                        enum.delete(db=db) 
    361                     db.commit() 
     361                    db.write.commit() 
    362362                    req.redirect(req.href.admin(cat, page)) 
    363363 
    364364                # Appy changes 
     
    387387                        if new_value != enum.value: 
    388388                            enum.value = new_value 
    389389                            enum.update(db=db) 
    390                     db.commit() 
     390                    db.write.commit() 
    391391 
    392392                    req.redirect(req.href.admin(cat, page)) 
    393393 
  • trac/ticket/api.py

    diff --git a/trac/ticket/api.py b/trac/ticket/api.py
    index 42e98a0..184afaf 100644
    a b  
    321321                if Ticket.id_is_valid(num): 
    322322                    # TODO: watch #6436 and when done, attempt to retrieve  
    323323                    #       ticket directly (try: Ticket(self.env, num) ...) 
    324                     cursor = formatter.db.cursor()  
     324                    cursor = formatter.db.read.cursor() 
    325325                    cursor.execute("SELECT type,summary,status,resolution " 
    326326                                   "FROM ticket WHERE id=%s", (str(num),))  
    327327                    for type, summary, status, resolution in cursor: 
  • trac/ticket/model.py

    diff --git a/trac/ticket/model.py b/trac/ticket/model.py
    index a380d0b..8d60560 100644
    a b  
    5050            self.id = self.time_created = self.time_changed = None 
    5151        self._old = {} 
    5252 
    53     def _get_db(self, db): 
    54         return db or self.env.get_db_cnx() 
    55  
    56     def _get_db_for_write(self, db): 
    57         if db: 
    58             return (db, False) 
    59         else: 
    60             return (self.env.get_db_cnx(), True) 
    61  
    6253    exists = property(fget=lambda self: self.id is not None) 
    6354 
    6455    def _init_defaults(self, db=None): 
     
    8677    def _fetch_ticket(self, tkt_id, db=None): 
    8778        row = None 
    8879        if self.id_is_valid(tkt_id): 
    89             db = self._get_db(db) 
     80            if db is None: 
     81                db = self.env.get_db_cnx() 
    9082 
    9183            # Fetch the standard ticket fields 
    9284            std_fields = [f['name'] for f in self.fields if not f.get('custom')] 
    93             cursor = db.cursor() 
     85