source: tagsplugin/tags/0.7/tractags/db.py

Last change on this file was 13432, checked in by Steffen Hoffmann, 10 years ago

TagsPlugin: Various fixes, refs #4503.

Thanks to Jun Omae for giving hints on the issues and for proposing patches.

File size: 5.0 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# Copyright (C) 2012 Steffen Hoffmann <hoff.st@web.de>
5#
6# This software is licensed as described in the file COPYING, which
7# you should have received as part of this distribution.
8
9from trac.core import Component, TracError, implements
10from trac.db.api import DatabaseManager
11from trac.env import IEnvironmentSetupParticipant
12
13from tractags import db_default
14from tractags.api import _
15from tractags.ticket import TicketTagProvider
16
17
18class TagSetup(Component):
19    """Plugin setup and upgrade handler."""
20
21    implements(IEnvironmentSetupParticipant)
22
23    # IEnvironmentSetupParticipant methods
24
25    def environment_created(self):
26        pass
27
28    def environment_needs_upgrade(self, db):
29        schema_ver = self.get_schema_version(db)
30        if schema_ver == db_default.schema_version:
31            return False
32        elif schema_ver > db_default.schema_version:
33            raise TracError(_("A newer plugin version has been installed "
34                              "before, but downgrading is unsupported."))
35        self.log.info("TracTags database schema version is %d, should be %d"
36                      % (schema_ver, db_default.schema_version))
37        return True
38
39    def upgrade_environment(self, db):
40        """Each schema version should have its own upgrade module, named
41        upgrades/dbN.py, where 'N' is the version number (int).
42        """
43        db_mgr = DatabaseManager(self.env)
44        schema_ver = self.get_schema_version(db)
45
46        cursor = db.cursor()
47        # Is this a new installation?
48        if not schema_ver:
49            # Perform a single-step install: Create plugin schema and
50            # insert default data into the database.
51            connector = db_mgr._get_connector()[0]
52            for table in db_default.schema:
53                for stmt in connector.to_sql(table):
54                    cursor.execute(stmt)
55            for table, cols, vals in db_default.get_data(db):
56                cursor.executemany("INSERT INTO %s (%s) VALUES (%s)" % (table,
57                                   ','.join(cols),
58                                   ','.join(['%s' for c in cols])), vals)
59        else:
60            # Perform incremental upgrades.
61            for i in range(schema_ver + 1, db_default.schema_version + 1):
62                name  = 'db%i' % i
63                try:
64                    upgrades = __import__('tractags.upgrades', globals(),
65                                          locals(), [name])
66                    script = getattr(upgrades, name)
67                except AttributeError:
68                    raise TracError(_("No upgrade module for version %(num)i "
69                                      "(%(version)s.py)", num=i, version=name))
70                script.do_upgrade(self.env, i, cursor)
71        cursor.execute("""
72            UPDATE system
73               SET value=%s
74             WHERE name='tags_version'
75            """, (db_default.schema_version,))
76        self.log.info("Upgraded TracTags db schema from version %d to %d"
77                      % (schema_ver, db_default.schema_version))
78
79        TicketTagProvider(self.env)._fetch_tkt_tags(db)
80        self.log.info("Synchronized ticket attributes to tags table")
81
82        db.commit()
83
84    # Internal methods
85
86    def get_schema_version(self, db=None):
87        """Return the current schema version for this plugin."""
88        if not db:
89            db = self.env.get_db_cnx()
90        cursor = db.cursor()
91        cursor.execute("""
92            SELECT value
93              FROM system
94             WHERE name='tags_version'
95        """)
96        row = cursor.fetchone()
97        if not (row and int(row[0]) > 2):
98            # Care for pre-tags-0.7 installations.
99            dburi = self.config.get('trac', 'database')
100            tables = self._get_tables(dburi, cursor)
101            if 'tags' in tables:
102                self.env.log.debug("TracTags needs to register schema version")
103                return 2
104            if 'wiki_namespace' in tables:
105                self.env.log.debug("TracTags needs to migrate old data")
106                return 1
107            # This is a new installation.
108            return 0
109        # The expected outcome for any up-to-date installation.
110        return row and int(row[0]) or 0
111
112    def _get_tables(self, dburi, cursor):
113        """Code from TracMigratePlugin by Jun Omae (see tracmigrate.admin)."""
114        if dburi.startswith('sqlite:'):
115            sql = """
116                SELECT name
117                  FROM sqlite_master
118                 WHERE type='table'
119                   AND NOT name='sqlite_sequence'
120            """
121        elif dburi.startswith('postgres:'):
122            sql = """
123                SELECT tablename
124                  FROM pg_tables
125                 WHERE schemaname = ANY (current_schemas(false))
126            """
127        elif dburi.startswith('mysql:'):
128            sql = "SHOW TABLES"
129        else:
130            raise TracError('Unsupported database type "%s"'
131                            % dburi.split(':')[0])
132        cursor.execute(sql)
133        return sorted([row[0] for row in cursor])
Note: See TracBrowser for help on using the repository browser.