PostgresqlPatch: pgsql_patch_01.diff
| File pgsql_patch_01.diff, 61.2 kB (added by brad, 7 years ago) |
|---|
-
trac/core.py
old new 1 1 # -*- coding: iso8859-1 -*- 2 2 # 3 3 # Copyright (C) 2003, 2004 Edgewall Software 4 # Copyright (C) 2003, 2004 Jonas Borgstr öm <jonas@edgewall.com>4 # Copyright (C) 2003, 2004 Jonas Borgstr?m <jonas@edgewall.com> 5 5 # 6 6 # Trac is free software; you can redistribute it and/or 7 7 # modify it under the terms of the GNU General Public License as … … 17 17 # along with this program; if not, write to the Free Software 18 18 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 19 # 20 # Author: Jonas Borgstr öm <jonas@edgewall.com>20 # Author: Jonas Borgstr?m <jonas@edgewall.com> 21 21 22 22 import os 23 23 import re -
trac/db_default.py
old new 414 414 (('trac', 'htdocs_location', '/trac/'), 415 415 ('trac', 'repository_dir', '/var/svn/myrep'), 416 416 ('trac', 'templates_dir', '/usr/lib/trac/templates'), 417 ('trac', 'database', 'sqlite: db/trac.db'),417 ('trac', 'database', 'sqlite:"db/trac.db",timeout=10000'), 418 418 ('trac', 'default_charset', 'iso-8859-15'), 419 419 ('logging', 'log_type', 'none'), 420 420 ('logging', 'log_file', 'trac.log'), -
trac/Milestone.py
old new 200 200 groups = [] 201 201 if by in ['status', 'resolution', 'severity', 'priority']: 202 202 cursor.execute("SELECT name FROM enum WHERE type = %s " 203 "AND IFNULL(name,'') != '' ORDER BY value", by)203 "AND COALESCE(name,'') != '' ORDER BY value", by) 204 204 elif by in ['component', 'milestone', 'version']: 205 205 cursor.execute("SELECT name FROM %s " 206 "WHERE IFNULL(name,'') != '' ORDER BY name" % by)206 "WHERE COALESCE(name,'') != '' ORDER BY name" % by) 207 207 elif by == 'owner': 208 208 cursor.execute("SELECT DISTINCT owner AS name FROM ticket " 209 209 "ORDER BY owner") -
trac/Query.py
old new 1 1 # -*- coding: iso8859-1 -*- 2 2 # 3 3 # Copyright (C) 2003, 2004 Edgewall Software 4 # Copyright (C) 2003, 2004 Jonas Borgstr öm <jonas@edgewall.com>4 # Copyright (C) 2003, 2004 Jonas Borgstr?m <jonas@edgewall.com> 5 5 # 6 6 # Trac is free software; you can redistribute it and/or 7 7 # modify it under the terms of the GNU General Public License as … … 17 17 # along with this program; if not, write to the Free Software 18 18 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 19 # 20 # Author: Jonas Borgstr öm <jonas@edgewall.com>20 # Author: Jonas Borgstr?m <jonas@edgewall.com> 21 21 22 22 from __future__ import nested_scopes 23 23 from time import gmtime, localtime, strftime … … 154 154 sql.append("\nFROM ticket") 155 155 for k in [k for k in cols if k in custom_fields]: 156 156 sql.append("\n LEFT OUTER JOIN ticket_custom AS %s ON " \ 157 "(id=%s.ticket AND %s.name='%s') " % (k, k, k, k))157 "(id=%s.ticket AND %s.name='%s') subq" % (k, k, k, k)) 158 158 159 159 for col in [c for c in ['status', 'resolution', 'priority', 'severity'] 160 160 if c == self.order or c == self.group]: 161 161 sql.append("\n LEFT OUTER JOIN (SELECT name AS %s_name, " \ 162 162 "value AS %s_value " \ 163 "FROM enum WHERE type='%s') " \163 "FROM enum WHERE type='%s') subq" \ 164 164 " ON %s_name=%s" % (col, col, col, col, col)) 165 165 for col in [c for c in ['milestone', 'version'] 166 166 if c == self.order or c == self.group]: 167 167 sql.append("\n LEFT OUTER JOIN (SELECT name AS %s_name, " \ 168 "time AS %s_time FROM %s) " \168 "time AS %s_time FROM %s) subq" \ 169 169 " ON %s_name=%s" % (col, col, col, col, col)) 170 170 171 171 def get_constraint_sql(name, value, mode, neg): 172 172 value = sql_escape(value[len(mode and '!' or '' + mode):]) 173 173 if mode == '~' and value: 174 return " IFNULL(%s,'') %sLIKE '%%%s%%'" % (174 return "COALESCE(%s,'') %sLIKE '%%%s%%'" % ( 175 175 name, neg and 'NOT ' or '', value) 176 176 elif mode == '^' and value: 177 return " IFNULL(%s,'') %sLIKE '%s%%'" % (177 return "COALESCE(%s,'') %sLIKE '%s%%'" % ( 178 178 name, neg and 'NOT ' or '', value) 179 179 elif mode == '$' and value: 180 return " IFNULL(%s,'') %sLIKE '%%%s'" % (180 return "COALESCE(%s,'') %sLIKE '%%%s'" % ( 181 181 name, neg and 'NOT ' or '', value) 182 182 elif mode == '': 183 return " IFNULL(%s,'')%s='%s'" % (name, neg and '!' or '', value)183 return "COALESCE(%s,'')%s='%s'" % (name, neg and '!' or '', value) 184 184 185 185 clauses = [] 186 186 for k, v in self.constraints.items(): … … 194 194 # Special case for exact matches on multiple values 195 195 if not mode and len(v) > 1: 196 196 inlist = ",".join(["'" + sql_escape(val[neg and 1 or 0:]) + "'" for val in v]) 197 clauses.append(" IFNULL(%s,'') %sIN (%s)" % (k, neg and "NOT " or "", inlist))197 clauses.append("COALESCE(%s,'') %sIN (%s)" % (k, neg and "NOT " or "", inlist)) 198 198 elif len(v) > 1: 199 199 constraint_sql = [get_constraint_sql(k, val, mode, neg) for val in v] 200 200 if neg: … … 214 214 order_cols.insert(0, (self.group, self.groupdesc)) 215 215 for col, desc in order_cols: 216 216 if desc: 217 sql.append(" IFNULL(%s,'')='' DESC," % col)217 sql.append("COALESCE(%s,'')='' DESC," % col) 218 218 else: 219 sql.append(" IFNULL(%s,'')=''," % col)219 sql.append("COALESCE(%s,'')=''," % col) 220 220 if col in ['status', 'resolution', 'priority', 'severity']: 221 221 if desc: 222 222 sql.append("%s_value DESC" % col) … … 224 224 sql.append("%s_value" % col) 225 225 elif col in ['milestone', 'version']: 226 226 if desc: 227 sql.append(" IFNULL(%s_time,0)=0 DESC,%s_time DESC,%s DESC"227 sql.append("COALESCE(%s_time,0)=0 DESC,%s_time DESC,%s DESC" 228 228 % (col, col, col)) 229 229 else: 230 sql.append(" IFNULL(%s_time,0)=0,%s_time,%s"230 sql.append("COALESCE(%s_time,0)=0,%s_time,%s" 231 231 % (col, col, col)) 232 232 else: 233 233 if desc: -
trac/Timeline.py
old new 1 1 # -*- coding: iso8859-1 -*- 2 2 # 3 3 # Copyright (C) 2003, 2004 Edgewall Software 4 # Copyright (C) 2003, 2004 Jonas Borgstr öm <jonas@edgewall.com>4 # Copyright (C) 2003, 2004 Jonas Borgstr?m <jonas@edgewall.com> 5 5 # 6 6 # Trac is free software; you can redistribute it and/or 7 7 # modify it under the terms of the GNU General Public License as … … 17 17 # along with this program; if not, write to the Free Software 18 18 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 19 # 20 # Author: Jonas Borgstr öm <jonas@edgewall.com>20 # Author: Jonas Borgstr?m <jonas@edgewall.com> 21 21 22 22 import time 23 23 import string -
trac/Report.py
old new 1 1 # -*- coding: iso8859-1 -*- 2 2 # 3 3 # Copyright (C) 2003, 2004 Edgewall Software 4 # Copyright (C) 2003, 2004 Jonas Borgstr öm <jonas@edgewall.com>4 # Copyright (C) 2003, 2004 Jonas Borgstr?m <jonas@edgewall.com> 5 5 # 6 6 # Trac is free software; you can redistribute it and/or 7 7 # modify it under the terms of the GNU General Public License as … … 17 17 # along with this program; if not, write to the Free Software 18 18 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 19 # 20 # Author: Jonas Borgstr öm <jonas@edgewall.com>20 # Author: Jonas Borgstr?m <jonas@edgewall.com> 21 21 22 22 import os 23 23 import re … … 95 95 sql = 'SELECT id AS report, title FROM report ORDER BY report' 96 96 description = 'This is a list of reports available.' 97 97 else: 98 cursor.execute('SELECT title, sql, description from report ' 99 ' WHERE id=%s', id) 98 sql = "SELECT title, sql, description from report " \ 99 "WHERE id=%s" % id 100 cursor.execute(sql) 100 101 row = cursor.fetchone() 101 102 if not row: 102 103 raise util.TracError('Report %d does not exist.' % id, … … 133 134 sql = self.sql_sub_vars(sql, args) 134 135 if not sql: 135 136 raise util.TracError('Report %s has no SQL query.' % id) 137 self.env.log.debug("sql: %s" % sql) 136 138 cursor.execute(sql) 137 139 138 140 if sql.find('__group__') == -1: … … 140 142 141 143 # FIXME: fetchall should probably not be used. 142 144 info = cursor.fetchall() 143 cols = cursor.rs.col_defs 145 cols = cursor.description 146 144 147 # Escape the values so that they are safe to have as html parameters 145 148 #info = map(lambda row: map(lambda x: escape(x), row), info) 146 149 -
trac/sync.py
old new 1 1 # -*- coding: iso8859-1 -*- 2 2 # 3 3 # Copyright (C) 2003, 2004 Edgewall Software 4 # Copyright (C) 2003, 2004 Jonas Borgstr öm <jonas@edgewall.com>4 # Copyright (C) 2003, 2004 Jonas Borgstr?m <jonas@edgewall.com> 5 5 # 6 6 # Trac is free software; you can redistribute it and/or 7 7 # modify it under the terms of the GNU General Public License as … … 17 17 # along with this program; if not, write to the Free Software 18 18 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 19 # 20 # Author: Jonas Borgstr öm <jonas@edgewall.com>20 # Author: Jonas Borgstr?m <jonas@edgewall.com> 21 21 22 22 from svn import fs, util, delta, repos, core 23 from util import sql_escape 23 24 24 25 import posixpath 25 26 … … 35 36 (util.SVN_VER_MAJOR, util.SVN_VER_MINOR, util.SVN_VER_MICRO) 36 37 37 38 cursor = db.cursor() 38 cursor.execute('SELECT ifnull(max(rev), 0) FROM revision') 39 youngest_stored = int(cursor.fetchone()[0]) 39 cursor.execute('SELECT max(rev) FROM revision') 40 row = cursor.fetchone() 41 youngest_stored = 0 42 if row and row[0] != None: 43 youngest_stored = int(row[0]) 44 40 45 max_rev = fs.youngest_rev(fs_ptr, pool) 41 46 num = max_rev - youngest_stored 42 47 offset = youngest_stored + 1 … … 52 57 53 58 date = util.svn_time_from_cstring(date, subpool) / 1000000 54 59 55 cursor.execute ('INSERT INTO revision (rev, time, author, message) ' 56 'VALUES (%s, %s, %s, %s)', rev + offset, date, 57 author, message) 60 sql = "INSERT INTO revision (rev, time, author, message) " \ 61 "VALUES (%s, %s, '%s', '%s')" \ 62 % ( rev + offset, date, sql_escape(author), sql_escape(message) ) 63 cursor.execute (sql) 58 64 insert_change (subpool, fs_ptr, rev + offset, cursor) 59 65 core.svn_pool_clear(subpool) 60 66 -
trac/Session.py
old new 21 21 22 22 import sys 23 23 import time 24 from util import hex_entropy, add_dict_to_hdf, TracError 24 from util import hex_entropy, add_dict_to_hdf, TracError, sql_escape 25 25 26 26 class Session: 27 27 """Basic session handling and per-session storage.""" … … 104 104 self.sid = sid 105 105 curs = self.db.cursor() 106 106 curs.execute("SELECT username,var_name,var_value FROM session" 107 " WHERE sid= %s",self.sid)107 " WHERE sid='%s'" % self.sid) 108 108 rows = curs.fetchall() 109 109 if (not rows # No session data yet 110 110 or rows[0][0] == 'anonymous' # Anon session … … 136 136 if currval == None: 137 137 if key == 'last_visit': # Limit the frequency of purging 138 138 self.purge_expired() 139 curs.execute('INSERT INTO session(sid,username,var_name,var_value)' 140 ' VALUES(%s,%s,%s,%s)', 141 self.sid, self.req.authname, key, val) 139 sql = "INSERT INTO session(sid,username,var_name,var_value) " \ 140 "VALUES('%s','%s','%s','%s')" \ 141 % ( 142 sql_escape(self.sid), sql_escape(self.req.authname), 143 sql_escape(key), sql_escape(val) 144 ) 145 curs.execute(sql) 142 146 else: 143 curs.execute('UPDATE session SET username=%s,var_value=%s' 144 ' WHERE sid=%s AND var_name=%s', 145 self.req.authname, val, self.sid, key) 147 sql = "UPDATE session SET username='%s',var_value='%s' " \ 148 "WHERE sid='%s' AND var_name='%s'" \ 149 % (sql_escape(self.req.authname), 150 sql_escape(str(val)), 151 sql_escape(self.sid), 152 sql_escape(key) 153 ) 154 curs.execute(sql) 146 155 self.db.commit() 147 156 self.vars[key] = val 148 157 -
trac/Roadmap.py
old new 51 51 self.env.href.roadmap()) 52 52 query = "SELECT name, time, descr FROM milestone " \ 53 53 "WHERE name != '' " \ 54 "ORDER BY ( IFNULL(time, 0) = 0) ASC, time ASC, name"54 "ORDER BY (COALESCE(time, 0) = 0) ASC, time ASC, name" 55 55 else: 56 56 self.req.hdf.setValue('roadmap.showall', '1') 57 57 self.req.hdf.setValue('roadmap.href.list', … … 59 59 query = "SELECT name, time, descr FROM milestone " \ 60 60 "WHERE name != '' " \ 61 61 "AND (time IS NULL OR time = 0 OR time > %d) " \ 62 "ORDER BY ( IFNULL(time, 0) = 0) ASC, time ASC, name" % time()62 "ORDER BY (COALESCE(time, 0) = 0) ASC, time ASC, name" % time() 63 63 64 64 if self.req.authname and self.req.authname != 'anonymous': 65 65 icalhref += '&user=' + self.req.authname -
trac/db_default_pgsql.py
old new 1 # -*- coding: iso8859-1 -*- 2 # 3 # Copyright (C) 2003, 2004 Edgewall Software 4 # Copyright (C) 2003, 2004 Daniel Lundin <daniel@edgewall.com> 5 # 6 # Trac is free software; you can redistribute it and/or 7 # modify it under the terms of the GNU General Public License as 8 # published by the Free Software Foundation; either version 2 of the 9 # License, or (at your option) any later version. 10 # 11 # Trac is distributed in the hope that it will be useful, 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 # General Public License for more details. 15 # 16 # You should have received a copy of the GNU General Public License 17 # along with this program; if not, write to the Free Software 18 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 # 20 # Author: Daniel Lundin <daniel@edgewall.com> 21 22 23 # Database version identifier. Used for automatic upgrades. 24 db_version = 7 25 26 def __mkreports(reps): 27 """Utility function used to create report data in same syntax as the 28 default data. This extra step is done to simplify editing the default 29 reports.""" 30 result = [] 31 i = 1 32 for r in reps: 33 result.append ((i, None, r[0], r[2], r[1])) 34 i = i + 1 35 return result 36 37 38 ## 39 ## Default data 40 ## 41 42 schema = """ 43 CREATE TABLE revision ( 44 rev integer, 45 time integer, 46 author text, 47 message text, 48 CONSTRAINT revision_pkey PRIMARY KEY (rev) 49 ) WITHOUT OIDS; 50 51 CREATE TABLE node_change ( 52 rev integer, 53 name text, 54 change char(1), 55 CONSTRAINT node_change_pkey PRIMARY KEY (rev, name, change) 56 ) WITHOUT OIDS; 57 58 CREATE TABLE auth_cookie ( 59 cookie text, 60 name text, 61 ipnr text, 62 time integer, 63 CONSTRAINT auth_cookie_pkey PRIMARY KEY(cookie, name, ipnr) 64 ) WITHOUT OIDS; 65 66 CREATE TABLE enum ( 67 type text, 68 name text, 69 value text, 70 CONSTRAINT enum_pkey PRIMARY KEY(name,type) 71 ) WITHOUT OIDS; 72 73 CREATE TABLE system ( 74 name text, 75 value text, 76 CONSTRAINT system_pkey PRIMARY KEY(name) 77 ) WITHOUT OIDS; 78 79 CREATE TABLE lock ( 80 name text, 81 owner text, 82 ipnr text, 83 time integer, 84 CONSTRAINT lock_pkey PRIMARY KEY(name) 85 ) WITHOUT OIDS; 86 87 CREATE TABLE ticket ( 88 id integer, 89 time integer, -- the time it was created 90 changetime integer, 91 component text, 92 severity text, 93 priority text, 94 owner text, -- who is this ticket assigned to 95 reporter text, 96 cc text, -- email addresses to notify 97 url text, -- url related to this ticket 98 version text, -- 99 milestone text, -- 100 status text, 101 resolution text, 102 summary text, -- one-line summary 103 description text, -- problem description (long) 104 keywords text, 105 CONSTRAINT ticket_pkey PRIMARY KEY(id) 106 ) WITHOUT OIDS; 107 108 CREATE TABLE ticket_change ( 109 ticket integer, 110 time integer, 111 author text, 112 field text, 113 oldvalue text, 114 newvalue text, 115 CONSTRAINT ticket_change_pkey PRIMARY KEY(ticket, time, field) 116 ) WITHOUT OIDS; 117 118 CREATE TABLE ticket_custom ( 119 ticket integer, 120 name text, 121 value text, 122 CONSTRAINT ticket_custom_pkey PRIMARY KEY(ticket,name) 123 ) WITHOUT OIDS; 124 125 CREATE TABLE report ( 126 id integer, 127 author text, 128 title text, 129 sql text, 130 description text, 131 CONSTRAINT report_pkey PRIMARY KEY(id) 132 ) WITHOUT OIDS; 133 134 CREATE TABLE permission ( 135 username text, -- 136 action text, -- allowable activity 137 CONSTRAINT permission_pkey PRIMARY KEY(username,action) 138 ) WITHOUT OIDS; 139 140 CREATE TABLE component ( 141 name text, 142 owner text, 143 CONSTRAINT component_pkey PRIMARY KEY(name) 144 ) WITHOUT OIDS; 145 146 CREATE TABLE milestone ( 147 id integer, 148 name text, 149 time integer, 150 descr text, 151 CONSTRAINT milestone_pkey PRIMARY KEY(name) 152 ) WITHOUT OIDS; 153 154 CREATE TABLE version ( 155 name text, 156 time integer, 157 CONSTRAINT version_pkey PRIMARY KEY(name) 158 ) WITHOUT OIDS; 159 160 CREATE TABLE wiki ( 161 name text, 162 version integer, 163 time integer, 164 author text, 165 ipnr text, 166 text text, 167 comment text, 168 readonly integer, 169 CONSTRAINT wiki_pkey PRIMARY KEY(name,version) 170 ) WITHOUT OIDS; 171 172 CREATE TABLE attachment ( 173 type text, 174 id text, 175 filename text, 176 size integer, 177 time integer, 178 description text, 179 author text, 180 ipnr text, 181 CONSTRAINT attachment_pkey PRIMARY KEY(type,id,filename) 182 ) WITHOUT OIDS; 183 184 CREATE TABLE session ( 185 sid text, 186 username text, 187 var_name text, 188 var_value text, 189 CONSTRAINT session_pkey PRIMARY KEY(sid,var_name) 190 ) WITHOUT OIDS; 191 192 """ 193 194 #CREATE INDEX node_change_idx ON node_change(rev); 195 #CREATE INDEX ticket_change_idx ON ticket_change(ticket, time); 196 #CREATE INDEX wiki_idx ON wiki(name,version); 197 #CREATE INDEX session_idx ON session(sid,var_name); 198 199 ## 200 ## Default Reports 201 ## 202 203 reports = ( 204 ('Active Tickets', 205 """ 206 * List all active tickets by priority. 207 * Color each row based on priority. 208 * If a ticket has been accepted, a '*' is appended after the owner's name 209 """, 210 """ 211 SELECT p.value AS __color__, 212 id AS ticket, summary, component, version, milestone, severity, 213 (CASE status WHEN 'assigned' THEN owner||' *' ELSE owner END) AS owner, 214 time AS created, 215 changetime AS _changetime, description AS _description, 216 reporter AS _reporter 217 FROM ticket t, enum p 218 WHERE status IN ('new', 'assigned', 'reopened') 219 AND p.name = t.priority AND p.type = 'priority' 220 ORDER BY p.value, milestone, severity, time 221 """), 222 #---------------------------------------------------------------------------- 223 ('Active Tickets by Version', 224 """ 225 This report shows how to color results by priority, 226 while grouping results by version. 227 228 Last modification time, description and reporter are included as hidden fields 229 for useful RSS export. 230 """, 231 """ 232 SELECT p.value AS __color__, 233 version AS __group__, 234 id AS ticket, summary, component, version, severity, 235 (CASE status WHEN 'assigned' THEN owner||' *' ELSE owner END) AS owner, 236 time AS created, 237 changetime AS _changetime, description AS _description, 238 reporter AS _reporter 239 FROM ticket t, enum p 240 WHERE status IN ('new', 'assigned', 'reopened') 241 AND p.name = t.priority AND p.type = 'priority' 242 ORDER BY (version IS NULL),version, p.value, severity, time 243 """), 244 #---------------------------------------------------------------------------- 245 ('All Tickets by Milestone', 246 """ 247 This report shows how to color results by priority, 248 while grouping results by milestone. 249 250 Last modification time, description and reporter are included as hidden fields 251 for useful RSS export. 252 """, 253 """ 254 SELECT p.value AS __color__, 255 milestone||' Release' AS __group__, 256 id AS ticket, summary, component, version, severity, 257 (CASE status WHEN 'assigned' THEN owner||' *' ELSE owner END) AS owner, 258 time AS created, 259 changetime AS _changetime, description AS _description, 260 reporter AS _reporter 261 FROM ticket t, enum p 262 WHERE status IN ('new', 'assigned', 'reopened') 263 AND p.name = t.priority AND p.type = 'priority' 264 ORDER BY (milestone IS NULL),milestone, p.value, severity, time 265 """), 266 #---------------------------------------------------------------------------- 267 ('Assigned, Active Tickets by Owner', 268 """ 269 List assigned tickets, group by ticket owner, sorted by priority. 270 """, 271 """ 272 273 SELECT p.value AS __color__, 274 owner AS __group__, 275 id AS ticket, summary, component, milestone, severity, time AS created, 276 changetime AS _changetime, description AS _description, 277 reporter AS _reporter 278 FROM ticket t,enum p 279 WHERE status = 'assigned' 280 AND p.name=t.priority AND p.type='priority' 281 ORDER BY owner, p.value, severity, time 282 """), 283 #---------------------------------------------------------------------------- 284 ('Assigned, Active Tickets by Owner (Full Description)', 285 """ 286 List tickets assigned, group by ticket owner. 287 This report demonstrates the use of full-row display. 288 """, 289 """ 290 SELECT p.value AS __color__, 291 owner AS __group__, 292 id AS ticket, summary, component, milestone, severity, time AS created, 293 description AS _description_, 294 changetime AS _changetime, reporter AS _reporter 295 FROM ticket t, enum p 296 WHERE status = 'assigned' 297 AND p.name = t.priority AND p.type = 'priority' 298 ORDER BY owner, p.value, severity, time 299 """), 300 #---------------------------------------------------------------------------- 301 ('All Tickets By Milestone (Including closed)', 302 """ 303 A more complex example to show how to make advanced reports. 304 """, 305 """ 306 SELECT p.value AS __color__, 307 t.milestone AS __group__, 308 (CASE status 309 WHEN 'closed' THEN 'color: #777; background: #ddd; border-color: #ccc;' 310 ELSE 311 (CASE owner WHEN '$USER' THEN 'font-weight: bold' END) 312 END) AS __style__, 313 id AS ticket, summary, component, status, 314 resolution,version, severity, priority, owner, 315 changetime AS modified, 316 time AS _time,reporter AS _reporter 317 FROM ticket t,enum p 318 WHERE p.name=t.priority AND p.type='priority' 319 ORDER BY (milestone IS NULL), milestone DESC, (status = 'closed'), 320 (CASE status WHEN 'closed' THEN modified ELSE -p.value END) DESC 321 """), 322 #---------------------------------------------------------------------------- 323 ('My Tickets', 324 """ 325 This report demonstrates the use of the automatically set 326 $USER dynamic variable, replaced with the username of the 327 logged in user when executed. 328 """, 329 """ 330 SELECT p.value AS __color__, 331 (CASE status WHEN 'assigned' THEN 'Assigned' ELSE 'Owned' END) AS __group__, 332 id AS ticket, summary, component, version, milestone, 333 severity, priority, time AS created, 334 changetime AS _changetime, description AS _description, 335 reporter AS _reporter 336 FROM ticket t, enum p 337 WHERE t.status IN ('new', 'assigned', 'reopened') 338 AND p.name = t.priority AND p.type = 'priority' AND owner = '$USER' 339 ORDER BY (status = 'assigned') DESC, p.value, milestone, severity, time 340 """), 341 #---------------------------------------------------------------------------- 342 ('Active Tickets, Mine first', 343 """ 344 * List all active tickets by priority. 345 * Show all tickets owned by the logged in user in a group first. 346 """, 347 """ 348 SELECT p.value AS __color__, 349 (CASE owner 350 WHEN '$USER' THEN 'My Tickets' 351 ELSE 'Active Tickets' 352 END) AS __group__, 353 id AS ticket, summary, component, version, milestone, severity, 354 (CASE status WHEN 'assigned' THEN owner||' *' ELSE owner END) AS owner, 355 time AS created, 356 changetime AS _changetime, description AS _description, 357 reporter AS _reporter 358 FROM ticket t, enum p 359 WHERE status IN ('new', 'assigned', 'reopened') 360 AND p.name = t.priority AND p.type = 'priority' 361 ORDER BY (owner = '$USER') DESC, p.value, milestone, severity, time 362 """)) 363 364 365 ## 366 ## Default database values 367 ## 368 369 # (table, (column1, column2), ((row1col1, row1col2), (row2col1, row2col2))) 370 data = (('component', 371 ('name', 'owner'), 372 (('component1', 'somebody'), 373 ('component2', 'somebody'))), 374 ('milestone', 375 ('name', 'time'), 376 (('', 0), 377 ('milestone1', 0), 378 ('milestone2', 0), 379 ('milestone3', 0), 380 ('milestone4', 0))), 381 ('version', 382 ('name', 'time'), 383 (('', 0), 384 ('1.0', 0), 385 ('2.0', 0))), 386 ('enum', 387 ('type', 'name', 'value'), 388 (('status', 'new', 1), 389 ('status', 'assigned', 2), 390 ('status', 'reopened', 3), 391 ('status', 'closed', 4), 392 ('resolution', 'fixed', 1), 393 ('resolution', 'invalid', 2), 394 ('resolution', 'wontfix', 3), 395 ('resolution', 'duplicate', 4), 396 ('resolution', 'worksforme', 5), 397 ('severity', 'blocker', 1), 398 ('severity', 'critical', 2), 399 ('severity', 'major', 3), 400 ('severity', 'normal', 4), 401 ('severity', 'minor', 5), 402 ('severity', 'trivial', 6), 403 ('severity', 'enhancement', 7), 404 ('priority', 'highest', 1), 405 ('priority', 'high', 2), 406 ('priority', 'normal', 3), 407 ('priority', 'low', 4), 408 ('priority', 'lowest', 5))), 409 ('permission', 410 ('username', 'action'), 411 (('anonymous', 'LOG_VIEW'), 412 ('anonymous', 'FILE_VIEW'), 413 ('anonymous', 'WIKI_VIEW'), 414 ('anonymous', 'WIKI_CREATE'), 415 ('anonymous', 'WIKI_MODIFY'), 416 ('anonymous', 'SEARCH_VIEW'), 417 ('anonymous', 'REPORT_VIEW'), 418 ('anonymous', 'REPORT_SQL_VIEW'), 419 ('anonymous', 'TICKET_VIEW'), 420 ('anonymous', 'TICKET_CREATE'), 421 ('anonymous', 'TICKET_MODIFY'), 422 ('anonymous', 'BROWSER_VIEW'), 423 ('anonymous', 'TIMELINE_VIEW'), 424 ('anonymous', 'CHANGESET_VIEW'), 425 ('anonymous', 'ROADMAP_VIEW'), 426 ('anonymous', 'MILESTONE_VIEW'))), 427 ('system', 428 ('name', 'value'), 429 (('database_version', str(db_version)),)), 430 ('report', 431 ('id', 'author', 'title', 'sql', 'description'), 432 __mkreports(reports))) 433 434 default_config = \ 435 (('trac', 'htdocs_location', '/trac/'), 436 ('trac', 'repository_dir', '/var/svn/myrep'), 437 ('trac', 'templates_dir', '/usr/lib/trac/templates'), 438 ('trac', 'database', 'pgdb:"",host="localhost:5432",database="trac",' \ 439 'user="trac",password="trac"'), 440 ('trac', 'default_charset', 'iso-8859-15'), 441 ('logging', 'log_type', 'none'), 442 ('logging', 'log_file', 'trac.log'), 443 ('logging', 'log_level', 'DEBUG'), 444 ('project', 'name', 'My Project'), 445 ('project', 'descr', 'My example project'), 446 ('project', 'url', 'http://example.com/'), 447 ('project', 'icon', 'trac.ico'), 448 ('project', 'footer', 449 ' Visit the Trac open source project at<br />' 450 '<a href="http://trac.edgewall.com/">http://trac.edgewall.com/</a>'), 451 ('ticket', 'default_version', ''), 452 ('ticket', 'default_severity', 'normal'), 453 ('ticket', 'default_priority', 'normal'), 454 ('ticket', 'default_milestone', ''), 455 ('ticket', 'default_component', 'component1'), 456 ('header_logo', 'link', 'http://trac.edgewall.com/'), 457 ('header_logo', 'src', 'trac_banner.png'), 458 ('header_logo', 'alt', 'Trac'), 459 ('header_logo', 'width', '236'), 460 ('header_logo', 'height', '73'), 461 ('attachment', 'max_size', '262144'), 462 ('diff', 'tab_width', '8'), 463 ('mimeviewer', 'enscript_path', 'enscript'), 464 ('notification', 'smtp_enabled', 'false'), 465 ('notification', 'smtp_server', 'localhost'), 466 ('notification', 'smtp_always_cc', ''), 467 ('notification', 'always_notify_reporter', 'false'), 468 ('notification', 'smtp_from', 'trac@localhost'), 469 ('notification', 'smtp_replyto', 'trac@localhost'), 470 ('timeline', 'changeset_show_files', '0')) 471 -
trac/auth.py
old new 1 1 # -*- coding: iso8859-1 -*- 2 2 # 3 3 # Copyright (C) 2003, 2004 Edgewall Software 4 # Copyright (C) 2003, 2004 Jonas Borgstr öm <jonas@edgewall.com>4 # Copyright (C) 2003, 2004 Jonas Borgstr?m <jonas@edgewall.com> 5 5 # 6 6 # Trac is free software; you can redistribute it and/or 7 7 # modify it under the terms of the GNU General Public License as … … 17 17 # along with this program; if not, write to the Free Software 18 18 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 19 # 20 # Author: Jonas Borgstr öm <jonas@edgewall.com>20 # Author: Jonas Borgstr?m <jonas@edgewall.com> 21 21 22 22 import time 23 23 import util … … 30 30 if req.incookie.has_key('trac_auth'): 31 31 cursor = db.cursor () 32 32 cookie = req.incookie['trac_auth'].value 33 cursor.execute ("SELECT name FROM auth_cookie " 34 "WHERE cookie=%s AND ipnr=%s" 35 ,cookie, req.remote_addr) 33 sql = "SELECT name FROM auth_cookie " \ 34 "WHERE cookie='%s' AND ipnr='%s'" \ 35 % ( cookie, req.remote_addr ) 36 cursor.execute(sql) 36 37 if cursor.rowcount >= 1: 37 38 self.authname = cursor.fetchone()[0] 38 39 39 40 def login(self, req): 40 41 cursor = self.db.cursor () 41 42 cookie = util.hex_entropy() 42 cursor.execute ("INSERT INTO auth_cookie (cookie, name, ipnr, time)" + 43 "VALUES (%s, %s, %s, %d)", 44 cookie, req.remote_user, req.remote_addr, 45 int(time.time())); 43 sql = "INSERT INTO auth_cookie (cookie, name, ipnr, time)" \ 44 "VALUES ('%s', '%s', '%s', %d)" \ 45 % ( cookie, req.remote_user, req.remote_addr, int(time.time()) ) 46 cursor.execute(sql); 47 48 # cursor.execute ("INSERT INTO auth_cookie (cookie, name, ipnr, time)" + 49 # "VALUES (%s, %s, %s, %d)", 50 # cookie, req.remote_user, req.remote_addr, 51 # int(time.time())); 46 52 self.db.commit () 47 53 self.authname = req.remote_user 48 54 req.outcookie['trac_auth'] = cookie -
trac/Wiki.py
old new 1 1 # -*- coding: iso8859-1 -*- 2 2 # 3 3 # Copyright (C) 2003, 2004 Edgewall Software 4 # Copyright (C) 2003, 2004 Jonas Borgstr öm <jonas@edgewall.com>4 # Copyright (C) 2003, 2004 Jonas Borgstr?m <jonas@edgewall.com> 5 5 # 6 6 # Trac is free software; you can redistribute it and/or 7 7 # modify it under the terms of the GNU General Public License as … … 17 17 # along with this program; if not, write to the Free Software 18 18 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 19 # 20 # Author: Jonas Borgstr öm <jonas@edgewall.com>20 # Author: Jonas Borgstr?m <jonas@edgewall.com> 21 21 22 22 import os 23 23 import time … … 27 27 28 28 import perm 29 29 from Module import Module 30 from util import escape, TracError, get_reporter_id 30 from util import escape, TracError, get_reporter_id, sql_escape 31 31 from Session import Session 32 32 from WikiFormatter import * 33 33 … … 56 56 self.name = name 57 57 self.perm = perm 58 58 cursor = self.db.cursor () 59 sql = "SELECT version, text, readonly FROM wiki " 59 60 if version: 60 cursor.execute ('SELECT version, text, readonly FROM wiki ' 61 'WHERE name=%s AND version=%s', 62 name, version) 61 sql += "WHERE name='%s' AND version=%s" % (name, version) 63 62 else: 64 cursor.execute ('SELECT version, text, readonly FROM wiki '65 'WHERE name=%s ORDER BY version DESC LIMIT 1', name)63 sql += "WHERE name='%s' ORDER BY version DESC LIMIT 1" % name 64 cursor.execute(sql) 66 65 row = cursor.fetchone() 67 66 if row: 68 67 self.new = 0 … … 102 101 self.db.commit () 103 102 self.old_readonly = self.readonly 104 103 elif self.modified: 105 cursor.execute ('INSERT INTO WIKI ' 106 '(name, version, time, author, ipnr, text, comment, readonly) ' 107 'VALUES (%s, %s, %s, %s, %s, %s, %s, %s)', 108 self.name, self.version, int(time.time()), 109 author, remote_addr, self.text, comment, self.readonly) 104 sql = "INSERT INTO WIKI " \ 105 "(name, version, time, author, ipnr, text, comment, readonly) " \ 106 "VALUES ('%s', %s, %s, '%s', '%s', '%s', '%s', %s)" \ 107 % ( 108 sql_escape(self.name), self.version, int(time.time()), 109 sql_escape(author), sql_escape(remote_addr), 110 sql_escape(self.text), sql_escape(comment), self.readonly 111 ) 112 cursor.execute (sql) 110 113 self.db.commit () 111 114 self.old_readonly = self.readonly 112 115 self.modified = 0 … … 124 127 This information is used to present a changelog/history for a given page 125 128 """ 126 129 cursor = self.db.cursor () 127 cursor.execute ('SELECT version, time, author, comment, ipnr FROM wiki ' 128 'WHERE name=%s ORDER BY version DESC', pagename) 130 sql = "SELECT version, time, author, comment, ipnr FROM wiki " \ 131 "WHERE name='%s' ORDER BY version DESC" % pagename 132 cursor.execute (sql) 129 133 i = 0 130 134 while 1: 131 135 row = cursor.fetchone() … … 155 159 self.req.redirect(self.env.href.wiki(pagename, version, 1)) 156 160 157 161 cursor = self.db.cursor() 158 cursor.execute ('SELECT text,author,comment,time FROM wiki ' 159 'WHERE name=%s AND (version=%s or version=%s)' 160 'ORDER BY version ASC', pagename, version - 1, version) 162 sql = "SELECT text,author,comment,time FROM wiki " \ 163 "WHERE name='%s' AND (version=%s or version=%s) " \ 164 "ORDER BY version ASC" % (pagename, version - 1, version) 165 cursor.execute (sql) 161 166 res = cursor.fetchall() 162 167 if not res: 163 168 raise TracError('Version %d of page "%s" not found.' 164 169 % (version, pagename), 165 170 'Page Not Found') 166 171 167 172 if len(res) == 1: 168 173 old = '' 169 174 else: -
trac/Environment.py
old new 1 1 # -*- coding: iso8859-1 -*- 2 2 # 3 3 # Copyright (C) 2003, 2004 Edgewall Software 4 # Copyright (C) 2003, 2004 Jonas Borgstr öm <jonas@edgewall.com>4 # Copyright (C) 2003, 2004 Jonas Borgstr?m <jonas@edgewall.com> 5 5 # 6 6 # Trac is free software; you can redistribute it and/or 7 7 # modify it under the terms of the GNU General Public License as … … 17 17 # along with this program; if not, write to the Free Software 18 18 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 19 # 20 # Author: Jonas Borgstr öm <jonas@edgewall.com>20 # Author: Jonas Borgstr?m <jonas@edgewall.com> 21 21 # 22 22 # Todo: Move backup and upgrade from db.py 23 23 # … … 50 50 * Project specific templates and wiki macros. 51 51 * wiki and ticket attachments. 52 52 """ 53 def __init__(self, path, create=0 ):53 def __init__(self, path, create=0, db_str=None): 54 54 self.path = path 55 55 if create: 56 self.create( )56 self.create(db_str) 57 57 self.verify() 58 58 self.load_config() 59 59 try: # Use binary I/O on Windows … … 71 71 assert fd.read(26) == 'Trac Environment Version 1' 72 72 fd.close() 73 73 74 def get_db_cnx(self): 75 db_str = self.get_config('trac', 'database', 'sqlite:db/trac.db') 76 assert db_str[:7] == 'sqlite:' 77 db_name = os.path.join(self.path, db_str[7:]) 78 if not os.access(db_name, os.F_OK): 79 raise EnvironmentError, 'Database "%s" not found.' % db_name 74 def get_db_cnx(self, check_exists=1): 75 db_str = self.get_config('trac', 76 'database', 77 'sqlite:"db/trac.db",timeout=10000') 78 79 pos = db_str.find(':') 80 if pos == -1: 81 raise EnvironmentError, 'Connection param must be of form ' \ 82 '(db_module_name):(db_connect_params), the value "%s ' \ 83 'does not match' % db_str 80 84 81 directory = os.path.dirname(db_name) 82 if not os.access(db_name, os.R_OK + os.W_OK) or \ 83 not os.access(directory, os.R_OK + os.W_OK): 84 raise EnvironmentError, \ 85 'The web server user requires read _and_ write permission\n' \ 86 'to the database %s and the directory this file is located in.' % db_name 87 return sqlite.connect(os.path.join(self.path, db_str[7:]), 88 timeout=10000) 85 module_name = db_str[:pos] 86 connect_params = db_str[pos+1:].split(',') 87 88 # following is very crude code for parsing the arguments in the 89 # db_connect_params string 90 kargs = {} 91 arg_list = [] 92 for x in connect_params: 93 pos1 = x.find('=') 94 pos2 = x.find('"') 95 pos3 = x.find("'") 96 if pos1 > -1: 97 if pos2 > -1 and pos2 < pos1: 98 arg_list.append(eval(x)) 99 elif pos3 > -1 and pos3 < pos1: 100 arg_list.append(eval(x)) 101 else: 102 name = x[:pos1].strip() 103 value = eval(x[pos1+1:].strip()) 104 kargs[name] = value 105 else: 106 # self.log.debug("Environment - get_db_cnx - x: %s" % x) 107 arg_list.append(eval(x)) 108 args = tuple(arg_list) 109 110 import_str = 'import %s' % module_name 89 111 90 def create(self): 112 # since Trac has a slightly closer relationship with sqlite than 113 # other db's, there's a special case setup here so that when the 114 # path to the sqlite db is specified, its relative to TRAC_ENV 115 if module_name == 'sqlite': 116 db_name = os.path.join(self.path, args[0]) 117 args = list(args) 118 args[0] = '%s' % db_name 119 args = tuple(args) 120 if check_exists == 1 and not os.access(db_name, os.F_OK): 121 raise EnvironmentError, 'Database "%s" not found.' % db_name 122 123 directory = os.path.dirname(db_name) 124 if (check_exists == 1 and not os.access(db_name, os.R_OK + os.W_OK)) \ 125 or not os.access(directory, os.R_OK + os.W_OK): 126 raise EnvironmentError, \ 127 'The web server user requires read _and_ write permission\n' \ 128 'to the database %s and the directory this file is located in.' % db_name 129 130 # handle weird import for PostgreSQL module 131 if module_name == 'PgSQL': 132 import_str = "from pyPgSQL import PgSQL" 133 134 exec import_str 135 m = eval(module_name) 136 137 # self.log.debug("Connecting to database module [%s] with: args=%s, " \ 138 # "kargs=%s" % (module_name, str(args), str(kargs))) 139 conn = m.connect(*args, **kargs) 140 return conn 141 142 143 def create(self, db_str=None): 91 144 def _create_file(fname, data=None): 92 145 fd = open(fname, 'w') 93 146 if data: fd.write(data) … … 128 181 """) 129 182 # Create default database 130 183 os.mkdir(os.path.join(self.path, 'db')) 131 cnx = sqlite.connect(os.path.join(self.path, 'db', 'trac.db')) 184 self.load_config() 185 self.setup_default_config() 186 if db_str: 187 self.cfg.set('trac', 'database', db_str) 188 self.save_config() 189 cnx = self.get_db_cnx(check_exists=0) 132 190 cursor = cnx.cursor() 133 191 cursor.execute(db_default.schema) 134 192 cnx.commit() … … 138 196 if v == None: 139 197 return 'NULL' 140 198 else: 141 return '"%s"' % v 199 prepped = v 200 if type(v) == str: 201 prepped = prepped.replace("'", "''") 202 return "'%s'" % prepped 142 203 cnx = self.get_db_cnx() 143 204 cursor = cnx.cursor() 144 205 … … 149 210 values = ','.join(map(prep_value, row)) 150 211 sql = "INSERT INTO %s (%s) VALUES(%s);" % (table, cols, values) 151 212 cursor.execute(sql) 213 cnx.commit() 214 215 def setup_default_config(self): 152 216 for s,n,v in db_default.default_config: 153 217 if not self.cfg.has_section(s): 154 218 self.cfg.add_section(s) 155 219 self.cfg.set(s, n, v) 156 self.save_config()157 cnx.commit()158 220 159 221 def get_version(self): 160 222 cnx = self.get_db_cnx() … … 216 278 217 279 def get_attachments(self, cnx, type, id): 218 280 cursor = cnx.cursor() 219 cursor.execute('SELECT filename,description,type,size,time,author,ipnr ' 220 'FROM attachment ' 221 'WHERE type=%s AND id=%s ORDER BY time', type, id) 281 sql = "SELECT filename,description,type,size,time,author,ipnr " \ 282 "FROM attachment " \ 283 "WHERE type='%s' AND id='%s' ORDER BY time" % (type, id) 284 cursor.execute(sql) 222 285 return cursor.fetchall() 223 286 224 287 def get_attachments_hdf(self, cnx, type, id, hdf, prefix): -
trac/Ticket.py
old new 1 1 # -*- coding: iso8859-1 -*- 2 2 # 3 3 # Copyright (C) 2003, 2004 Edgewall Software 4 # Copyright (C) 2003, 2004 Jonas Borgstr öm <jonas@edgewall.com>4 # Copyright (C) 2003, 2004 Jonas Borgstr?m <jonas@edgewall.com> 5 5 # 6 6 # Trac is free software; you can redistribute it and/or 7 7 # modify it under the terms of the GNU General Public License as … … 17 17 # along with this program; if not, write to the Free Software 18 18 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 19 # 20 # Author: Jonas Borgstr öm <jonas@edgewall.com>20 # Author: Jonas Borgstr?m <jonas@edgewall.com> 21 21 22 22 import re 23 23 import time … … 73 73 self[Ticket.std_fields[i]] = row[i] or '' 74 74 75 75 cursor = db.cursor () 76 cursor.execute('SELECT name,value FROM ticket_custom WHERE ticket=%i', id) 76 sql = "SELECT name,value FROM ticket_custom WHERE ticket=%s" % id 77 cursor.execute(sql) 77 78 rows = cursor.fetchall() 78 79 if rows: 79 80 for r in rows: … … 134 135 # is updated accordingly. (#623). 135 136 if self['status'] == 'new' and self._old.has_key('component') and \ 136 137 not self._old.has_key('owner'): 137 cursor.execute('SELECT owner FROM component ' 138 'WHERE name=%s', self._old['component']) 138 sql = "SELECT owner FROM component " \ 139 "WHERE name=%s" % self._old['component'] 140 cursor.execute(sql) 139 141 old_owner = cursor.fetchone()[0] 140 142 if self['owner'] == old_owner: 141 cursor.execute('SELECT owner FROM component ' 142 'WHERE name=%s', self['component']) 143 sql = "SELECT owner FROM component " \ 144 "WHERE name=%s" % self['component'] 145 cursor.execute(sql) 143 146 self['owner'] = cursor.fetchone()[0] 144 147 145 148 146 149 for name in self._old.keys(): 147 150 if name[:7] == 'custom_': 148 151 fname = name[7:] 149 cursor.execute('REPLACE INTO ticket_custom(ticket,name,value)' 150 ' VALUES(%s, %s, %s)', id, fname, self[name]) 152 sql = "REPLACE INTO ticket_custom(ticket,name,value) " \ 153 "VALUES(%s, '%s', '%s')" \ 154 % (id, util.sql_escape(fname), util.sql_escape(self[name])) 155 cursor.execute(sql) 151 156 else: 152 157 fname = name 153 cursor.execute ('UPDATE ticket SET %s=%s WHERE id=%s', 154 fname, self[name], id) 155 156 cursor.execute ('INSERT INTO ticket_change ' 157 '(ticket, time, author, field, oldvalue, newvalue) ' 158 'VALUES (%s, %s, %s, %s, %s, %s)', 159 id, when, author, fname, self._old[name], self[name]) 158 sql = "UPDATE ticket SET %s='%s' WHERE id=%s" \ 159 % (fname, util.sql_escape(self[name]), id) 160 cursor.execute (sql) 161 162 sql = "INSERT INTO ticket_change " \ 163 "(ticket, time, author, field, oldvalue, newvalue) " \ 164 "VALUES (%s, %s, '%s', '%s', '%s', '%s')" \ 165 % ( 166 id, when, util.sql_escape(author), util.sql_escape(fname), 167 util.sql_escape(self._old[name]), util.sql_escape(self[name]) 168 ) 169 cursor.execute (sql) 160 170 if comment: 161 cursor.execute ('INSERT INTO ticket_change ' 162 '(ticket,time,author,field,oldvalue,newvalue) ' 163 "VALUES (%s, %s, %s, 'comment', '', %s)", 164 id, when, author, comment) 171 sql = "INSERT INTO ticket_change " \ 172 "(ticket,time,author,field,oldvalue,newvalue) " \ 173 "VALUES (%s, %s, '%s', 'comment', '', '%s')" \ 174 % ( id, when, util.sql_escape(author), util.sql_escape(comment) ) 175 cursor.execute (sql) 165 176 166 cursor.execute ('UPDATE ticket SET changetime=%s WHERE id=%s', when, id) 177 sql = "UPDATE ticket SET changetime=%s WHERE id=%s" % (when, id) 178 cursor.execute (sql) 167 179 db.commit() 168 180 self._forget_changes() 169 181 170 182 def get_changelog(self, db, when=0): 171 183 """Returns the changelog as a list of dictionaries""" 172 184 cursor = db.cursor() 185 when_clause = "" 173 186 if when: 174 cursor.execute('SELECT time, author, field, oldvalue, newvalue ' 175 'FROM ticket_change ' 176 'WHERE ticket=%s AND time=%s' 177 'UNION ' 178 'SELECT time, author, "attachment", null, filename ' 179 'FROM attachment ' 180 'WHERE id=%s AND time=%s ' 181 'ORDER BY time', self['id'], when, self['id'], when) 182 else: 183 cursor.execute('SELECT time, author, field, oldvalue, newvalue ' 184 'FROM ticket_change ' 185 'WHERE ticket=%s ' 186 'UNION ' 187 'SELECT time, author, "attachment", null,filename ' 188 'FROM attachment ' 189 'WHERE id = %s ' 190 'ORDER BY time', self['id'], self['id']) 187 when_clause = " AND time=%s " % when 188 sql = "SELECT time, author, field, oldvalue, newvalue " \ 189 "FROM ticket_change " \ 190 "WHERE ticket=%s %s " \ 191 "UNION " \ 192 "SELECT time, author, 'attachment', null, filename " \ 193 "FROM attachment " \ 194 "WHERE id=%s %s " \ 195 "ORDER BY time" \ 196 % (self['id'], when_clause, self['id'], when_clause) 197 # raise util.TracError(sql) 198 cursor.execute(sql) 191 199 log = [] 192 200 while 1: 193 201 row = cursor.fetchone() -
contrib/create_pgdb.sql
old new 1 CREATE TABLE revision ( 2 rev integer, 3 time integer, 4 author text, 5 message text, 6 CONSTRAINT revision_pkey PRIMARY KEY (rev) 7 ) WITHOUT OIDS; 8 9 CREATE TABLE node_change ( 10 rev integer, 11 name text, 12 change char(1), 13 CONSTRAINT node_change_pkey PRIMARY KEY (rev, name, change) 14 ) WITHOUT OIDS; 15 16 CREATE TABLE auth_cookie ( 17 cookie text, 18 name text, 19 ipnr text, 20 time integer, 21 CONSTRAINT auth_cookie_pkey PRIMARY KEY(cookie, name, ipnr) 22 ) WITHOUT OIDS; 23 24 CREATE TABLE enum ( 25 type text, 26 name text, 27 value text, 28 CONSTRAINT enum_pkey PRIMARY KEY(name,type) 29 ) WITHOUT OIDS; 30 31 CREATE TABLE system ( 32 name text, 33 value text, 34 CONSTRAINT system_pkey PRIMARY KEY(name) 35 ) WITHOUT OIDS; 36 37 CREATE TABLE lock ( 38 name text, 39 owner text, 40 ipnr text, 41 time integer, 42 CONSTRAINT lock_pkey PRIMARY KEY(name) 43 ) WITHOUT OIDS; 44 45 CREATE TABLE ticket ( 46 id integer, 47 time integer, -- the time it was created 48 changetime integer, 49 component text, 50 severity text, 51 priority text, 52 owner text, -- who is this ticket assigned to 53 reporter text, 54 cc text, -- email addresses to notify 55 url text, -- url related to this ticket 56 version text, -- 57 milestone text, -- 58 status text, 59 resolution text, 60 summary text, -- one-line summary 61 description text, -- problem description (long) 62 keywords text, 63 CONSTRAINT ticket_pkey PRIMARY KEY(id) 64 ) WITHOUT OIDS; 65 66 CREATE TABLE ticket_change ( 67 ticket integer, 68 time integer, 69 author text, 70 field text, 71 oldvalue text, 72 newvalue text, 73 CONSTRAINT ticket_change_pkey PRIMARY KEY(ticket, time, field) 74 ) WITHOUT OIDS; 75 76 CREATE TABLE ticket_custom ( 77 ticket integer, 78 name text, 79 value text, 80 CONSTRAINT ticket_custom_pkey PRIMARY KEY(ticket,name) 81 ) WITHOUT OIDS; 82 83 CREATE TABLE report ( 84 id integer, 85 author text, 86 title text, 87 sql text, 88 description text, 89 CONSTRAINT report_pkey PRIMARY KEY(id) 90 ) WITHOUT OIDS; 91 92 CREATE TABLE permission ( 93 username text, -- 94 action text, -- allowable activity 95 CONSTRAINT permission_pkey PRIMARY KEY(username,action) 96 ) WITHOUT OIDS; 97 98 CREATE TABLE component ( 99 name text, 100 owner text, 101 CONSTRAINT component_pkey PRIMARY KEY(name) 102 ) WITHOUT OIDS; 103 104 CREATE TABLE milestone ( 105 id integer, 106 name text, 107 time integer, 108 descr text, 109 CONSTRAINT milestone_pkey PRIMARY KEY(name) 110 ) WITHOUT OIDS; 111 112 CREATE TABLE version ( 113 name text, 114 time integer, 115 CONSTRAINT version_pkey PRIMARY KEY(name) 116 ) WITHOUT OIDS; 117 118 CREATE TABLE wiki ( 119 name text, 120 version integer, 121 time integer, 122 author text, 123 ipnr text, 124 text text, 125 comment text, 126 readonly integer, 127 CONSTRAINT wiki_pkey PRIMARY KEY(name,version) 128 ) WITHOUT OIDS; 129 130 CREATE TABLE attachment ( 131 type text, 132 id text, 133 filename text, 134 size integer, 135 time integer, 136 description text, 137 author text, 138 ipnr text, 139 CONSTRAINT attachment_pkey PRIMARY KEY(type,id,filename) 140 ) WITHOUT OIDS; 141 142 CREATE TABLE session ( 143 sid text, 144 username text, 145 var_name text, 146 var_value text, 147 CONSTRAINT session_pkey PRIMARY KEY(sid,var_name) 148 ) WITHOUT OIDS; -
contrib/tracdb-sqlite2pg.py
old new 1 #!/usr/bin/env python 2 3 """ 4 Import a Trac database from sqlite to postgresql. 5 6 Requires: Trac from http://trac.edgewall.com/ 7 Python 2.3 from http://www.python.org/ 8 PostgreSQL from http://www.postgresql.org/ 9 PySQLITE ? 10 others? 11 12 Author: Brad Anderson <brad@dsource.org> 13 14 15 """ 16 17 import sys, os 18 import sqlite 19 import pgdb 20 from trac.util import sql_escape 21 22 tables=['revision','node_change', 'auth_cookie', 'enum', 'system', 'lock', 23 'ticket', 'ticket_change', 'ticket_custom', 'report', 'permission', 24 'component', 'milestone', 'version', 'attachment', 'session', 'wiki', 25 'forums', 'topics', 'posts'] 26 27 # for debugging, one table at a time 28 # tables=['wiki'] 29 30 31 ## simple field translation mapping. if string not in 32 ## mapping, just return string, otherwise return value 33 #class FieldTranslator(dict): 34 # def __getitem__(self, item): 35 # if not dict.has_key(self, item): 36 # return item 37 # 38 # return dict.__getitem__(self, item) 39 40 41 42 def convert(_env, _host, _db, _user, _password, _force): 43 44 45 # init PostgreSQL environment 46 print "PostgreSQL('%s':'%s':'%s'): connecting..." \ 47 % (_host, _db, _user) 48 pg_con = pgdb.connect(host=_host, database=_db, 49 user=_user, password=_password) 50 pg_cur = pg_con.cursor() 51 52 # init Trac environment 53 print "Trac SQLite('%s'): connecting..." % (_env) 54 trac_con = sqlite.connect(os.path.join(_env, "db/trac.db"), 55 timeout=10000) 56 trac_cur = trac_con.cursor() 57 print 58 59 # fieldtypes = FieldTranslator() 60 # fieldtypes['0'] = 'int' 61 # fieldtypes['6'] = 'text' 62 63 # loop thru tables, converting them 64 for t in tables: 65 print 66 print "Converting Table: '%s'" % t 67 68 # clear out existing table 69 pg_cur.execute("truncate table %s;" % t) 70 71 # get table info 72 sql = "SELECT * FROM %s" % t 73 trac_cur.execute(sql) 74 cols = trac_cur.rs.col_defs 75 counter = 0 76 77 # loop thru rows, moving data from sqlite to pgsql 78 while 1: 79 row = trac_cur.fetchone() 80 counter += 1 81 if not row: 82 break 83 flds="" 84 vals="" 85 for c in cols: 86 field = c[0] 87 type = c[1] 88 value = row[field] 89 if value != None: 90 flds += ", %s" % field 91 if type in [6]: 92 value = "'%s'" % sql_escape(value) 93 vals += ", %s" % value 94 flds = flds[2:] 95 vals = vals[2:] 96 sql = "INSERT INTO %s " % t 97 sql += "(%s) " % flds 98 sql += "VALUES (%s);" % vals 99 100 pg_cur.execute(sql) 101 pg_con.commit() 102 103 if counter % 100 == 0: 104 print "%s rows" % counter 105 106 trac_cur.close() 107 trac_con.close() 108 pg_cur.close() 109 pg_con.close() 110 print 111 112 113 def usage(): 114 print "tracdb-sqlite2pg - Converts a Trac database from sqlite to postgresql." 115 print 116 print "Usage: tracdb-sqlite2pg.py [options]" 117 print 118 print "Available Options:" 119 print " -t | --tracenv /path/to/trac/env - full path to Trac environment" 120 print " -h | --host <pgsql hostname> - PostgreSQL hostname" 121 print " -db | --database <pgsql database> - PostgreSQL database name" 122 print " -u | --user <pgsql username> - PostgreSQL username" 123 print " -p | --passwd <pgsql password> - PostgreSQL password" 124 print " -c | --clean - clean out PG database before converting." 125 print " --help | help - this help info" 126 print 127 print "Additional configuration options can be defined directly in the script." 128 print 129 sys.exit(0) 130 131 def main(): 132 global TRAC_ENV, PG_HOST, PG_DB, PG_USER, PG_PASSWORD, PG_CLEAN 133 if len (sys.argv) > 1: 134 if sys.argv[1] in ['--help','help'] or len(sys.argv) < 4: 135 usage() 136 iter = 1 137 while iter < len(sys.argv): 138 if sys.argv[iter] in ['-t', '--tracenv'] and iter+1 < len(sys.argv): 139 TRAC_ENV = sys.argv[iter+1] 140 iter = iter + 1 141 elif sys.argv[iter] in ['-h', '--host'] and iter+1 < len(sys.argv): 142 PG_HOST = sys.argv[iter+1] 143 iter = iter + 1 144 elif sys.argv[iter] in ['-db', '--database'] and iter+1 < len(sys.argv): 145 PG_DB = sys.argv[iter+1] 146 iter = iter + 1 147 elif sys.argv[iter] in ['-u', '--user'] and iter+1 < len(sys.argv): 148 PG_USER = sys.argv[iter+1] 149 iter = iter + 1 150 elif sys.argv[iter] in ['-p', '--passwd'] and iter+1 < len(sys.argv): 151 PG_PASSWORD = sys.argv[iter+1] 152 iter = iter + 1 153 elif sys.argv[iter] in ['-c', '--clean']: 154 PG_CLEAN = 1 155 else: 156 print "Error: unknown parameter: " + sys.argv[iter] 157 sys.exit(0) 158 iter = iter + 1 159 else: 160 usage() 161 162 convert(TRAC_ENV, PG_HOST, PG_DB, PG_USER, PG_PASSWORD, PG_CLEAN) 163 164 165 if __name__ == '__main__': 166 main()
