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

Last change on this file was 16054, checked in by Jun Omae, 7 years ago

0.9dev: fix unit tests with Trac 1.0 on Python 2.5

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