source: timingandestimationplugin/branches/trac0.11-Permissions/timingandestimationplugin/reportmanager.py

Last change on this file was 5493, checked in by Russ Tyndall, 14 years ago

re #4184 ported changes to permissions branch and fixed a missing function ref in reportmanager

File size: 8.9 KB
Line 
1from trac.core import *
2
3
4
5class CustomReportManager:
6  """A Class to manage custom reports"""
7  version = 1
8  name = "custom_report_manager_version"
9  env = None
10  log = None
11  TimingAndEstimationKey = "Timing and Estimation Plugin"
12 
13  def __init__(self, env, log):
14    self.env = env
15    self.log = log
16    self.upgrade()
17 
18  def upgrade(self): 
19    # Check to see what version we have
20    db = self.env.get_db_cnx()
21    cursor = db.cursor()
22    cursor.execute("SELECT value FROM system WHERE name=%s", (self.name,))
23    try:
24      version = int(cursor.fetchone()[0])
25    except:
26      version = 0
27      cursor.execute("INSERT INTO system (name,value) VALUES(%s,%s)",
28                     (self.name, version))
29       
30    if version > self.version:
31      raise TracError("Fatal Error: You appear to be running two plugins with conflicting versions "
32                      "of the CustomReportManager class. Please ensure that '%s' is updated to "
33                      "version %s of the file reportmanager.py (currently using version %s)."
34                      % (__name__, str(version), str(self.version)))
35   
36    # Do the staged updates
37    try:
38      if version < 1:
39        cursor.execute("CREATE TABLE custom_report ("
40                       "id         INTEGER,"
41                       "uuid       VARCHAR(64),"
42                       "maingroup  VARCHAR(255),"
43                       "subgroup   VARCHAR(255),"
44                       "version    INTEGER,"
45                       "ordering   INTEGER)")
46     
47      #if version < 2:
48      #  cursor.execute("...")
49   
50      # Updates complete, set the version
51      cursor.execute("UPDATE system SET value=%s WHERE name=%s", 
52                     (self.version, self.name))
53      db.commit()
54      db.close()
55   
56    except Exception, e:
57      self.log.error("CustomReportManager Exception: %s" % (e,));
58      db.rollback()
59
60  def get_report_id_and_version (self, uuid):
61    sql = "SELECT custom_report.id, custom_report.version FROM custom_report "\
62        "JOIN report ON report.id = custom_report.id " \
63        "WHERE uuid=%s"
64    tpl = self.get_first_row(sql, uuid)
65    return tpl or (None, 0)
66   
67  def get_new_report_id (self):
68    """find the next available report id """
69    rtn = self.get_scalar("SELECT MAX(id) FROM report")
70    return (rtn and rtn+1) or 1
71   
72  def get_max_ordering(self, maingroup, subgroup):
73    """ Find the maximum ordering value used for this group of the custom_report table"""
74    return self.get_scalar("SELECT MAX(ordering) FROM custom_report WHERE maingroup=%s AND subgroup=%s",
75                           0, maingroup, subgroup) or 0
76 
77  def _insert_report (self, next_id, title, author, description, query,
78                      uuid, maingroup, subgroup, version, ordering):
79    """ Adds a row the custom_report_table """
80    self.log.debug("Inserting new report '%s' with uuid '%s'" % (title,uuid))
81    self.execute_in_trans(("DELETE FROM custom_report WHERE uuid=%s", (uuid,)), 
82                          ("INSERT INTO report (id, title, author, description, query) " \
83                           "VALUES (%s, %s, %s, %s, %s)",
84                           (next_id, title, author, description, query)),
85                          ("INSERT INTO custom_report (id, uuid, maingroup, subgroup, version, ordering) " \
86                           "VALUES (%s, %s, %s, %s, %s, %s)",
87                           (next_id, uuid, maingroup, subgroup, version, ordering)))
88    self.log.debug("Attempting to increment sequence (only works in postgres)")
89    try:
90      self.execute_in_trans(("SELECT nextval('report_id_seq');",[]));
91      self.log.debug("Sequence updated");
92    except:
93      self.log.debug("Sequence failed to update, perhaps you are not running postgres?");
94
95  def _update_report (self, id, title, author, description, query,
96                      maingroup, subgroup, version):
97    """Updates a report and its row in the custom_report table """
98    self.log.debug("Updating report '%s' with to version %s" % (title, version))
99    self.execute_in_trans(("UPDATE report SET title=%s, author=%s, description=%s, query=%s " \
100                           "WHERE id=%s", (title, author, description, query, id)),
101                          ("UPDATE custom_report SET version=%s, maingroup=%s, subgroup=%s "
102                           "WHERE id=%s", (version, maingroup, subgroup, id)))
103   
104  def add_report(self, title, author, description, query, uuid, version,
105                 maingroup, subgroup="", force=False):
106    """
107    We add/update a report to the system. We will not overwrite unchanged versions
108    unless force is set.
109    """
110    # First check to see if we can load an existing version of this report
111    (id, currentversion) = self.get_report_id_and_version(uuid)
112    self.log.debug("add_report %s (ver:%s) | id: %s currentversion: %s" % (uuid , version, id, currentversion))
113    try:
114      if not id:
115        next_id = self.get_new_report_id()
116        ordering = self.get_max_ordering(maingroup, subgroup) + 1
117        self._insert_report(next_id, title, author, description, query,
118                      uuid, maingroup, subgroup, version, ordering)
119        return True
120      if currentversion < version or force:
121        self._update_report(id, title, author, description, query,
122                            maingroup, subgroup, version)
123        return True
124    except Exception, e:
125      self.log.error("CustomReportManager.add_report Exception: %s, %s" % (e,(title, author, uuid, version,
126                 maingroup, subgroup, force)));
127    self.log.debug("report %s not upgraded (a better version already exists)" % uuid)
128    return False
129 
130  def get_report_by_uuid(self, uuid):
131    sql = "SELECT report.id,report.title FROM custom_report "\
132          "LEFT JOIN report ON custom_report.id=report.id "\
133          "WHERE custom_report.uuid=%s"
134    return self.get_first_row(sql,uuid)
135
136  def get_reports_by_group(self, group):
137    """Gets all of the reports for a given group"""
138    db = self.env.get_db_cnx()
139    cursor = db.cursor()
140    rv = {}
141    try:
142      cursor.execute("SELECT custom_report.subgroup,report.id,report.title, custom_report.version, custom_report.uuid "
143                     "FROM custom_report "
144                     "LEFT JOIN report ON custom_report.id=report.id "
145                     "WHERE custom_report.maingroup=%s "
146                     "ORDER BY custom_report.subgroup,custom_report.ordering", (group,))
147      for subgroup, id, title, version, uuid in cursor:
148        if not rv.has_key(subgroup):
149          rv[subgroup] = { "title": subgroup,
150                           "reports": [] }
151        rv[subgroup]["reports"].append( { "id": int(id), "title": title, "version":version, "uuid":uuid } )
152    except:
153      pass
154    return rv
155 
156  def get_version_hash_by_group(self, group):
157    """Gets all of the reports for a given group as a uuid=>version hash"""
158    db = self.env.get_db_cnx()
159    cursor = db.cursor()
160    rv = {}
161    try:
162      cursor.execute("SELECT custom_report.subgroup,report.id,report.title, custom_report.version, custom_report.uuid "
163                     "FROM custom_report "
164                     "LEFT JOIN report ON custom_report.id=report.id "
165                     "WHERE custom_report.maingroup=%s "
166                     "ORDER BY custom_report.subgroup,custom_report.ordering", (group,))
167      for subgroup, id, title, version, uuid in cursor:
168        rv[uuid] = version
169    except:
170      pass
171    return rv
172
173  # similar functions are found in dbhelper, but this file should be fairly
174  # stand alone so that it can be copied and pasted around
175  def get_first_row(self, sql,*params):
176    """ Returns the first row of the query results as a tuple of values (or None)"""
177    db = self.env.get_db_cnx()
178    cur = db.cursor()
179    data = None;
180    try:
181      cur.execute(sql, params)
182      data = cur.fetchone();
183      db.commit();
184    except Exception, e:
185      self.log.error('There was a problem executing sql:%s \n \
186      with parameters:%s\nException:%s'%(sql, params, e));
187      db.rollback()
188    try:
189      db.close()
190    except:
191      pass
192    return data;
193
194  def get_scalar(self, sql, col=0, *params):
195    """ Gets a single value (in the specified column) from the result set of the query"""
196    data = self.get_first_row(sql, *params);
197    if data:
198      return data[col]
199    else:
200      return None;
201
202  def execute_in_trans(self, *args):
203    success = True
204    db = self.env.get_db_cnx()
205    cur = db.cursor()
206    try:
207      for sql, params in args:
208        cur.execute(sql, params)
209      db.commit()
210    except Exception, e:
211      self.log.error('There was a problem executing sql:%s \n \
212      with parameters:%s\nException:%s'%(sql, params, e));
213      db.rollback();
214      success = False
215    try:
216      db.close()
217    except:
218      pass
219    return success
220
221   
Note: See TracBrowser for help on using the repository browser.