PostgresqlPatch: pgsql_patch_04.diff
| File pgsql_patch_04.diff, 49.5 kB (added by brad, 4 years ago) |
|---|
-
scripts/trac-admin
old new 29 29 import shlex 30 30 import sqlite 31 31 import StringIO 32 import traceback 32 33 33 34 from trac import util 34 35 from trac import sync … … 92 93 return 0 93 94 return 1 94 95 95 def env_create(self ):96 def env_create(self, db_str): 96 97 try: 97 self.__env = trac.Environment.Environment (self.envname, create=1)98 self.__env = trac.Environment.Environment (self.envname, 1, db_str) 98 99 return self.__env 99 100 except Exception, e: 100 101 print 'Failed to create environment.', e … … 111 112 112 113 def db_execsql (self, sql, cursor=None): 113 114 data = [] 115 row = None 114 116 if not cursor: 115 117 cnx=self.db_open() 116 118 cursor = cnx.cursor() … … 118 120 cnx = None 119 121 cursor.execute(sql) 120 122 while 1: 121 row = cursor.fetchone() 123 try: 124 row = cursor.fetchone() 125 except: 126 pass 122 127 if row == None: 123 128 break 124 129 data.append(row) … … 457 462 458 463 ## Initenv 459 464 _help_initenv = [('initenv', 'Create and initialize a new environment interactively'), 460 ('initenv <projectname> <repospath> <templatepath> ',465 ('initenv <projectname> <repospath> <templatepath> <dbms> [dbms options]', 461 466 'Create and initialize a new environment from arguments')] 462 467 463 468 def do_initdb(self, line): … … 490 495 dt = trac.siteconfig.__default_templates_dir__ 491 496 prompt = 'Templates directory [%s]> ' % dt 492 497 returnvals.append(raw_input(prompt) or dt) 498 print 499 print " Please enter the database in which you wish to store Trac data." 500 print " Default is 'sqlite', but others are supported:" 501 print " 'sqlite' - SQLite http://www.sqlite.org" 502 print " 'pgsql' - PostgreSQL http://www.postgresql.org" 503 print 504 ddb = "sqlite" 505 prompt = 'database system [%s]> ' % ddb 506 dbms = raw_input(prompt) or ddb 507 returnvals.append(dbms) 508 509 # PostgreSQL - additional questions 510 if dbms == "pgsql": 511 print 512 print " Please enter the host of your PostgreSQL database." 513 print " Default is 'localhost'" 514 print 515 host = "localhost" 516 prompt = "PostgreSQL host [%s]> " % host 517 returnvals.append(raw_input(prompt) or host) 518 519 print 520 print " Please enter the port of your PostgreSQL database." 521 print " Default is '5432'" 522 print 523 port = "5432" 524 prompt = "PostgreSQL port [%s]> " % port 525 returnvals.append(raw_input(prompt) or port) 526 527 print 528 print " Please enter the name of your PostgreSQL database." 529 print " Default is 'trac'" 530 print " Note: This database should not exist, as trac-admin will" \ 531 " attempt to create it." 532 print 533 name = "trac" 534 prompt = "PostgreSQL database [%s]> " % name 535 returnvals.append(raw_input(prompt) or name) 536 537 print 538 print " Please enter the user of your PostgreSQL database." 539 print " Default is 'trac'" 540 print 541 user = "trac" 542 prompt = "PostgreSQL user [%s]> " % user 543 returnvals.append(raw_input(prompt) or user) 544 545 print 546 print " Please enter the password of your PostgreSQL database." 547 print " Default is 'trac'" 548 print 549 password = "trac" 550 prompt = "PostgreSQL password [%s]> " % password 551 returnvals.append(raw_input(prompt) or password) 552 493 553 return returnvals 494 554 495 555 def do_initenv(self, line): … … 500 560 project_name = None 501 561 repository_dir = None 502 562 templates_dir = None 563 db_str = None 503 564 if len(arg) == 1: 504 565 returnvals = self.get_initenv_args() 505 566 project_name = returnvals[0] 506 567 repository_dir = returnvals[1] 507 568 templates_dir = returnvals[2] 508 elif len(arg)!= 3: 569 db_str = returnvals[3] 570 elif len(arg) < 4: 509 571 print 'Wrong number of arguments to initenv %d' % len(arg) 510 572 return 511 573 else: 512 574 project_name = arg[0] 513 575 repository_dir = arg[1] 514 576 templates_dir = arg[2] 577 db_str = arg[3] 578 579 # sqlite-specific stuff 580 if db_str.lower() == "sqlite": 581 db_str = 'sqlite:"db/trac.db",timeout=10000' 582 583 # postgres-specific stuff 584 if db_str.lower() == "pgsql": 585 if len(arg) == 1: 586 host = returnvals[4] 587 port = returnvals[5] 588 database = returnvals[6] 589 user = returnvals[7] 590 password = returnvals[8] 591 elif len(arg) != 9: 592 print 'Wrong number of arguments to initenv %d' % len(arg) 593 print 'For PostgreSQL (after pgsql): <host> <port> <database>' \ 594 ' <user> <password>' 595 return 596 else: 597 host = arg[4] 598 port = arg[5] 599 database = arg[6] 600 user = arg[7] 601 password = arg[8] 602 db_str = "pgsql:\"\",host='%s:%s',database='%s',user='%s'," \ 603 "password='%s'" \ 604 % (host, port, database, user, password) 605 createdb_str = "createdb --host=%s --port=%s --owner=%s " \ 606 "--username=%s %s\n" \ 607 % (host, port, user, user, database) 608 print createdb_str 609 try: 610 # TODO: this is not cross-platform. 611 # for Windows, look at win32pipe.popen() 612 os.popen(createdb_str) 613 except Exception, e: 614 print "Error creating PostgreSQL database: %s" % e 615 print "command: %s" % createdb_str 616 515 617 from svn import util, repos, core 516 618 core.apr_initialize() 517 619 pool = core.svn_pool_create(None) … … 530 632 return 531 633 try: 532 634 print 'Creating and Initializing Project' 533 self.env_create( )635 self.env_create(db_str) 534 636 cnx = self.__env.get_db_cnx() 535 637 print ' Inserting default data' 536 638 self.__env.insert_default_data() … … 669 771 self.do_help ('wiki') 670 772 except Exception, e: 671 773 print 'Wiki %s failed:' % arg[0], e 774 print traceback.print_exc() 775 672 776 673 777 def _do_wiki_list(self): 674 778 data = self.db_execsql('SELECT name,max(version),time' … … 694 798 data = data.replace("'", "''") # Escape ' for safe SQL 695 799 f.close() 696 800 697 sql = ("INSERT INTO wiki('version','name','time','author','ipnr','text') " 698 " SELECT 1+ifnull(max(version),0),'%(title)s','%(time)s','%(author)s'," 699 " '%(ipnr)s','%(text)s' FROM wiki WHERE name='%(title)s'" 801 sql = ("INSERT INTO wiki(version,name,time,author,ipnr,text) " 802 " SELECT 1+COALESCE(max(version),0),'%(title)s','%(time)s'," 803 "'%(author)s','%(ipnr)s','%(text)s' " 804 "FROM wiki WHERE name='%(title)s'" 700 805 % {'title':title, 701 806 'time':int(time.time()), 702 807 'author':'trac', … … 1007 1112 print "Upgrade: Backup of old database saved in " \ 1008 1113 "%s/db/trac.db.%i.bak" % (self.envname, curr) 1009 1114 else: 1010 print "Upgrade: Backup disabled. Non-exist ant warranty voided."1115 print "Upgrade: Backup disabled. Non-existent warranty voided." 1011 1116 self.__env.upgrade(do_backup) 1012 1117 else: 1013 1118 print "Upgrade: Database is up to date, no upgrade necessary." -
trac/db_default.py
old new 174 174 CREATE INDEX session_idx ON session(sid,var_name); 175 175 """ 176 176 177 schema_pgsql = """ 178 CREATE TABLE revision ( 179 rev integer, 180 time integer, 181 author text, 182 message text, 183 CONSTRAINT revision_pkey PRIMARY KEY (rev) 184 ) WITHOUT OIDS; 185 186 CREATE TABLE node_change ( 187 rev integer, 188 name text, 189 change char(1), 190 CONSTRAINT node_change_pkey PRIMARY KEY (rev, name, change) 191 ) WITHOUT OIDS; 192 193 CREATE TABLE auth_cookie ( 194 cookie text, 195 name text, 196 ipnr text, 197 time integer, 198 CONSTRAINT auth_cookie_pkey PRIMARY KEY(cookie, name, ipnr) 199 ) WITHOUT OIDS; 200 201 CREATE TABLE enum ( 202 type text, 203 name text, 204 value text, 205 CONSTRAINT enum_pkey PRIMARY KEY(name,type) 206 ) WITHOUT OIDS; 207 208 CREATE TABLE system ( 209 name text, 210 value text, 211 CONSTRAINT system_pkey PRIMARY KEY(name) 212 ) WITHOUT OIDS; 213 214 CREATE TABLE lock ( 215 name text, 216 owner text, 217 ipnr text, 218 time integer, 219 CONSTRAINT lock_pkey PRIMARY KEY(name) 220 ) WITHOUT OIDS; 221 222 CREATE TABLE ticket ( 223 id integer, 224 time integer, -- the time it was created 225 changetime integer, 226 component text, 227 severity text, 228 priority text, 229 owner text, -- who is this ticket assigned to 230 reporter text, 231 cc text, -- email addresses to notify 232 url text, -- url related to this ticket 233 version text, -- 234 milestone text, -- 235 status text, 236 resolution text, 237 summary text, -- one-line summary 238 description text, -- problem description (long) 239 keywords text, 240 CONSTRAINT ticket_pkey PRIMARY KEY(id) 241 ) WITHOUT OIDS; 242 243 CREATE TABLE ticket_change ( 244 ticket integer, 245 time integer, 246 author text, 247 field text, 248 oldvalue text, 249 newvalue text, 250 CONSTRAINT ticket_change_pkey PRIMARY KEY(ticket, time, field) 251 ) WITHOUT OIDS; 252 253 CREATE TABLE ticket_custom ( 254 ticket integer, 255 name text, 256 value text, 257 CONSTRAINT ticket_custom_pkey PRIMARY KEY(ticket,name) 258 ) WITHOUT OIDS; 259 260 CREATE TABLE report ( 261 id integer, 262 author text, 263 title text, 264 sql text, 265 description text, 266 CONSTRAINT report_pkey PRIMARY KEY(id) 267 ) WITHOUT OIDS; 268 269 CREATE TABLE permission ( 270 username text, -- 271 action text, -- allowable activity 272 CONSTRAINT permission_pkey PRIMARY KEY(username,action) 273 ) WITHOUT OIDS; 274 275 CREATE TABLE component ( 276 name text, 277 owner text, 278 CONSTRAINT component_pkey PRIMARY KEY(name) 279 ) WITHOUT OIDS; 280 281 CREATE TABLE milestone ( 282 name text, 283 due integer, -- Due date/time 284 completed integer, -- Completed date/time 285 description text, 286 CONSTRAINT milestone_pkey PRIMARY KEY(name) 287 ) WITHOUT OIDS; 288 289 CREATE TABLE version ( 290 name text, 291 time integer, 292 CONSTRAINT version_pkey PRIMARY KEY(name) 293 ) WITHOUT OIDS; 294 295 CREATE TABLE wiki ( 296 name text, 297 version integer, 298 time integer, 299 author text, 300 ipnr text, 301 text text, 302 comment text, 303 readonly integer, 304 CONSTRAINT wiki_pkey PRIMARY KEY(name,version) 305 ) WITHOUT OIDS; 306 307 CREATE TABLE attachment ( 308 type text, 309 id text, 310 filename text, 311 size integer, 312 time integer, 313 description text, 314 author text, 315 ipnr text, 316 CONSTRAINT attachment_pkey PRIMARY KEY(type,id,filename) 317 ) WITHOUT OIDS; 318 319 CREATE TABLE session ( 320 sid text, 321 username text, 322 var_name text, 323 var_value text, 324 CONSTRAINT session_pkey PRIMARY KEY(sid,var_name) 325 ) WITHOUT OIDS; 326 327 """ 328 177 329 ## 178 330 ## Default Reports 179 331 ## … … 413 565 (('trac', 'htdocs_location', '/trac/'), 414 566 ('trac', 'repository_dir', '/var/svn/myrep'), 415 567 ('trac', 'templates_dir', '/usr/lib/trac/templates'), 416 ('trac', 'database', 'sqlite: db/trac.db'),568 ('trac', 'database', 'sqlite:"db/trac.db",timeout=10000'), 417 569 ('trac', 'default_charset', 'iso-8859-15'), 418 570 ('logging', 'log_type', 'none'), 419 571 ('logging', 'log_file', 'trac.log'), -
trac/Milestone.py
old new 157 157 cursor = self.db.cursor() 158 158 self.log.debug("Creating new milestone '%s'" % name) 159 159 cursor.execute("INSERT INTO milestone (name,due,completed,description) " 160 "VALUES (%s,% d,%d,%s)", name, due, completed,160 "VALUES (%s,%s,%s,%s)", name, due, completed, 161 161 description) 162 162 self.db.commit() 163 163 self.req.redirect(self.env.href.milestone(name)) … … 196 196 'associated with milestone %s' % id) 197 197 cursor.execute("UPDATE ticket SET milestone = %s " 198 198 "WHERE milestone = %s", name, id) 199 cursor.execute("UPDATE milestone SET name = %s, due = % d, "200 "completed = % d, description = %s WHERE name = %s",199 cursor.execute("UPDATE milestone SET name = %s, due = %s, " 200 "completed = %s, description = %s WHERE name = %s", 201 201 name, due, completed, description, id) 202 202 self.db.commit() 203 203 self.req.redirect(self.env.href.milestone(name)) … … 209 209 groups = [] 210 210 if by in ['status', 'resolution', 'severity', 'priority']: 211 211 cursor.execute("SELECT name FROM enum WHERE type = %s " 212 "AND IFNULL(name,'') != '' ORDER BY value", by)212 "AND COALESCE(name,'') != '' ORDER BY value", by) 213 213 elif by in ['component', 'milestone', 'version']: 214 214 cursor.execute("SELECT name FROM %s " 215 "WHERE IFNULL(name,'') != '' ORDER BY name" % by)215 "WHERE COALESCE(name,'') != '' ORDER BY name" % by) 216 216 elif by == 'owner': 217 217 cursor.execute("SELECT DISTINCT owner AS name FROM ticket " 218 218 "ORDER BY owner") -
trac/Search.py
old new 117 117 118 118 cursor = self.db.cursor () 119 119 120 # ugly 'cast' hack for sqlite vs other dbms 121 # and UNION ALL requiring like column datatypes 122 data_changeset = 'rev' 123 data_tickets = 'a.id' 124 dbms = self.env.dbms 125 if dbms != 'sqlite': 126 data_changeset = 'cast(rev as text)' 127 data_tickets = 'cast(a.id as text)' 128 120 129 q = [] 121 130 if changeset: 122 131 q.append('SELECT 1 as type, message AS title, message, author, ' 123 ' \'\' AS keywords, revAS data, time,0 AS ver'132 ' \'\' AS keywords, %s AS data, time,0 AS ver' 124 133 ' FROM revision WHERE %s OR %s' % 125 (self.query_to_sql(query, 'message'), 134 (data_changeset, 135 self.query_to_sql(query, 'message'), 126 136 self.query_to_sql(query, 'author'))) 127 137 if tickets: 128 138 q.append('SELECT DISTINCT 2 as type, a.summary AS title, ' 129 139 ' a.description AS message, a.reporter AS author, ' 130 ' a.keywords as keywords, a.id AS data, a.time as time, 0 AS ver' 131 ' FROM ticket a LEFT JOIN ticket_change b ON a.id = b.ticket' 132 ' WHERE (b.field=\'comment\' AND %s ) OR' 133 ' %s OR %s OR %s OR %s OR %s' % 134 (self.query_to_sql(query, 'b.newvalue'), 140 ' a.keywords as keywords, %s AS data, a.time as time' 141 ' , 0 AS ver FROM ticket a LEFT JOIN ticket_change b' 142 ' ON a.id = b.ticket WHERE (b.field=\'comment\' AND %s )' 143 ' OR %s OR %s OR %s OR %s OR %s' % 144 (data_tickets, 145 self.query_to_sql(query, 'b.newvalue'), 135 146 self.query_to_sql(query, 'summary'), 136 147 self.query_to_sql(query, 'keywords'), 137 148 self.query_to_sql(query, 'description'), -
trac/Query.py
old new 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') tc" % (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') e" \ 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 time_col = col == 'milestone' and 'due' or 'time' 168 168 sql.append("\n LEFT OUTER JOIN (SELECT name AS %s_name, " \ 169 "%s AS %s_time FROM %s) " \169 "%s AS %s_time FROM %s) a" \ 170 170 " ON %s_name=%s" % (col, time_col, col, col, col, col)) 171 171 172 172 def get_constraint_sql(name, value, mode, neg): 173 173 value = sql_escape(value[len(mode and '!' or '' + mode):]) 174 174 if mode == '~' and value: 175 return " IFNULL(%s,'') %sLIKE '%%%s%%'" % (175 return "COALESCE(%s,'') %sLIKE '%%%s%%'" % ( 176 176 name, neg and 'NOT ' or '', value) 177 177 elif mode == '^' and value: 178 return " IFNULL(%s,'') %sLIKE '%s%%'" % (178 return "COALESCE(%s,'') %sLIKE '%s%%'" % ( 179 179 name, neg and 'NOT ' or '', value) 180 180 elif mode == '$' and value: 181 return " IFNULL(%s,'') %sLIKE '%%%s'" % (181 return "COALESCE(%s,'') %sLIKE '%%%s'" % ( 182 182 name, neg and 'NOT ' or '', value) 183 183 elif mode == '': 184 return " IFNULL(%s,'')%s='%s'" % (name, neg and '!' or '', value)184 return "COALESCE(%s,'')%s='%s'" % (name, neg and '!' or '', value) 185 185 186 186 clauses = [] 187 187 for k, v in self.constraints.items(): … … 195 195 # Special case for exact matches on multiple values 196 196 if not mode and len(v) > 1: 197 197 inlist = ",".join(["'" + sql_escape(val[neg and 1 or 0:]) + "'" for val in v]) 198 clauses.append(" IFNULL(%s,'') %sIN (%s)" % (k, neg and "NOT " or "", inlist))198 clauses.append("COALESCE(%s,'') %sIN (%s)" % (k, neg and "NOT " or "", inlist)) 199 199 elif len(v) > 1: 200 200 constraint_sql = [get_constraint_sql(k, val, mode, neg) for val in v] 201 201 if neg: … … 214 214 if self.group and self.group != self.order: 215 215 order_cols.insert(0, (self.group, self.groupdesc)) 216 216 for col, desc in order_cols: 217 if desc: 218 sql.append("IFNULL(%s,'')='' DESC," % col) 217 if col == 'id': 218 # TODO: this is a somewhat ugly hack. Can we also have the 219 # column type for this? If it's an integer, we do first 220 # one, if text, we do 'else' 221 if desc: 222 sql.append("COALESCE(%s,0)=0 DESC," % col) 223 else: 224 sql.append("COALESCE(%s,0)=0," % col) 219 225 else: 220 sql.append("IFNULL(%s,'')=''," % col) 226 if desc: 227 sql.append("COALESCE(%s,'')='' DESC," % col) 228 else: 229 sql.append("COALESCE(%s,'')=''," % col) 221 230 if col in ['status', 'resolution', 'priority', 'severity']: 222 231 if desc: 223 232 sql.append("%s_value DESC" % col) … … 225 234 sql.append("%s_value" % col) 226 235 elif col in ['milestone', 'version']: 227 236 if desc: 228 sql.append(" IFNULL(%s_time,0)=0 DESC,%s_time DESC,%s DESC"237 sql.append("COALESCE(%s_time,0)=0 DESC,%s_time DESC,%s DESC" 229 238 % (col, col, col)) 230 239 else: 231 sql.append(" IFNULL(%s_time,0)=0,%s_time,%s"240 sql.append("COALESCE(%s_time,0)=0,%s_time,%s" 232 241 % (col, col, col)) 233 242 else: 234 243 if desc: -
trac/Timeline.py
old new 142 142 if max_node != 0: 143 143 cursor_node = self.db.cursor () 144 144 cursor_node.execute("SELECT name, change " 145 "FROM node_change WHERE rev=% d" %item['idata'])145 "FROM node_change WHERE rev=%s", item['idata']) 146 146 node_list = '' 147 147 node_data = '' 148 148 node_count = 0; -
trac/Report.py
old new 140 140 141 141 # FIXME: fetchall should probably not be used. 142 142 info = cursor.fetchall() 143 cols = cursor. rs.col_defs143 cols = cursor.description 144 144 # Escape the values so that they are safe to have as html parameters 145 145 #info = map(lambda row: map(lambda x: escape(x), row), info) 146 146 -
trac/sync.py
old new 35 35 (util.SVN_VER_MAJOR, util.SVN_VER_MINOR, util.SVN_VER_MICRO) 36 36 37 37 cursor = db.cursor() 38 cursor.execute('SELECT ifnull(max(rev), 0) FROM revision')38 cursor.execute('SELECT COALESCE(max(rev), 0) FROM revision') 39 39 youngest_stored = int(cursor.fetchone()[0]) 40 40 max_rev = fs.youngest_rev(fs_ptr, pool) 41 41 num = max_rev - youngest_stored -
trac/util.py
old new 329 329 d[k] = v 330 330 return d 331 331 332 def get_next_key(db, table, key_column='id', cursor=None): 333 '''Provides a very basic way of getting the next available key for a 334 particular table.''' 332 335 336 # the currently implementation here is a hack, this should be upgraded to 337 # use something like a separate table to maintain next_key references, but 338 # even this hack should work fine unless millions of records are getting 339 # inserted simultaneously 340 341 if cursor == None: 342 cursor = db.cursor() 343 cursor.execute('select max(%s) + 1 as next_key from %s' % (key_column, table)) 344 row = cursor.fetchone() 345 next_key = row[0] 346 347 if next_key == None: 348 next_key = 1 349 350 return next_key 351 333 352 if __name__ == '__main__ ': 334 353 pass 335 354 #print pre -
trac/Session.py
old new 103 103 def get_session(self, sid): 104 104 self.sid = sid 105 105 curs = self.db.cursor() 106 curs.execute("SELECT username,var_name,var_value FROM session" 106 curs.execute("SELECT username,var_name,var_value FROM session" 107 107 " WHERE sid=%s", self.sid) 108 108 rows = curs.fetchall() 109 109 if (not rows # No session data yet … … 172 172 curs = self.db.cursor() 173 173 curs.execute("DELETE FROM session WHERE sid IN" 174 174 " (SELECT sid FROM session WHERE var_name='mod_time'" 175 " AND var_value < % i)", mintime)175 " AND var_value < %s)", mintime) 176 176 self.db.commit() 177 177 -
trac/Roadmap.py
old new 44 44 if show == 'all': 45 45 icalhref += '&show=all' 46 46 query = "SELECT name,due,completed,description FROM milestone " \ 47 "WHERE IFNULL(name,'')!='' " \48 "ORDER BY IFNULL(due,0)=0,due,name"47 "WHERE COALESCE(name,'')!='' " \ 48 "ORDER BY COALESCE(due,0)=0,due,name" 49 49 else: 50 50 self.req.hdf.setValue('roadmap.showall', '1') 51 51 query = "SELECT name,due,completed,description FROM milestone " \ 52 "WHERE IFNULL(name,'')!='' " \53 "AND IFNULL(completed,0)=0 " \54 "ORDER BY IFNULL(due,0)=0,due,name"52 "WHERE COALESCE(name,'')!='' " \ 53 "AND COALESCE(completed,0)=0 " \ 54 "ORDER BY COALESCE(due,0)=0,due,name" 55 55 56 56 if self.req.authname and self.req.authname != 'anonymous': 57 57 icalhref += '&user=' + self.req.authname … … 176 176 if ticket['status'] == 'closed': 177 177 cursor = self.db.cursor() 178 178 cursor.execute("SELECT time FROM ticket_change " 179 "WHERE ticket = % iAND field = 'status' "179 "WHERE ticket = %s AND field = 'status' " 180 180 "ORDER BY time desc LIMIT 1", ticket['id']) 181 181 row = cursor.fetchone() 182 182 if row: write_utctime('COMPLETED', localtime(row['time'])) -
trac/auth.py
old new 40 40 cursor = self.db.cursor () 41 41 cookie = util.hex_entropy() 42 42 cursor.execute ("INSERT INTO auth_cookie (cookie, name, ipnr, time)" + 43 "VALUES (%s, %s, %s, % d)",43 "VALUES (%s, %s, %s, %s)", 44 44 cookie, req.remote_user, req.remote_addr, 45 45 int(time.time())); 46 46 self.db.commit () -
trac/Environment.py
old new 46 46 A Trac environment consists of a directory structure containing 47 47 among other things: 48 48 * a configuration file. 49 * a sqlitedatabase (stores tickets, wiki pages...)49 * a database (stores tickets, wiki pages...) 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 … … 64 64 pass 65 65 self.setup_log() 66 66 self.setup_mimeviewer() 67 self.dbms = self.get_dbms() 67 68 68 69 def verify(self): 69 70 """Verifies that self.path is a compatible trac environment""" … … 71 72 assert fd.read(26) == 'Trac Environment Version 1' 72 73 fd.close() 73 74 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 75 def get_dbms(self): 76 db_str = self.get_config('trac', 'database') 77 if not db_str: 78 return 'sqlite' 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 dbms = db_str[:pos] 86 return dbms 87 88 89 def get_db_cnx(self, check_exists=1): 90 db_str = self.get_config('trac', 91 'database', 92 'sqlite:"db/trac.db",timeout=10000') 93 94 pos = db_str.find(':') 95 if pos == -1: 96 raise EnvironmentError, 'Connection param must be of form ' \ 97 '(db_module_name):(db_connect_params), the value "%s ' \ 98 'does not match' % db_str 99 100 module_name = db_str[:pos] 101 connect_params = db_str[pos+1:].split(',') 102 103 # following is very crude code for parsing the arguments in the 104 # db_connect_params string 105 kargs = {} 106 arg_list = [] 107 for x in connect_params: 108 pos1 = x.find('=') 109 pos2 = x.find('"') 110 pos3 = x.find("'") 111 if pos1 > -1: 112 if pos2 > -1 and pos2 < pos1: 113 arg_list.append(eval(x)) 114 elif pos3 > -1 and pos3 < pos1: 115 arg_list.append(eval(x)) 116 else: 117 name = x[:pos1].strip() 118 value = eval(x[pos1+1:].strip()) 119 kargs[name] = value 120 else: 121 # self.log.debug("Environment - get_db_cnx - x: %s" % x) 122 arg_list.append(eval(x)) 123 args = tuple(arg_list) 124 125 import_str = 'import %s' % module_name 89 126 90 def create(self): 127 # since Trac has a slightly closer relationship with sqlite than 128 # other db's, there's a special case setup here so that when the 129 # path to the sqlite db is specified, its relative to TRAC_ENV 130 if module_name == 'sqlite': 131 db_name = os.path.join(self.path, args[0]) 132 args = list(args) 133 args[0] = '%s' % db_name 134 args = tuple(args) 135 if check_exists == 1 and not os.access(db_name, os.F_OK): 136 raise EnvironmentError, 'Database "%s" not found.' % db_name 137 138 directory = os.path.dirname(db_name) 139 if (check_exists == 1 and not os.access(db_name, os.R_OK + os.W_OK)) \ 140 or not os.access(directory, os.R_OK + os.W_OK): 141 raise EnvironmentError, \ 142 'The web server user requires read _and_ write permission\n' \ 143 'to the database %s and the directory this file is located in.' % db_name 144 145 # handle weird import for PostgreSQL module 146 if module_name.lower() == 'pgsql': 147 import_str = "from pyPgSQL import PgSQL" 148 module_name = "PgSQL" 149 150 exec import_str 151 m = eval(module_name) 152 153 # self.log.debug("Connecting to database module [%s] with: args=%s, " \ 154 # "kargs=%s" % (module_name, str(args), str(kargs))) 155 conn = m.connect(*args, **kargs) 156 return conn 157 158 159 def create(self, db_str=None): 91 160 def _create_file(fname, data=None): 92 161 fd = open(fname, 'w') 93 162 if data: fd.write(data) … … 128 197 """) 129 198 # Create default database 130 199 os.mkdir(os.path.join(self.path, 'db')) 131 cnx = sqlite.connect(os.path.join(self.path, 'db', 'trac.db')) 200 self.load_config() 201 self.setup_default_config() 202 if db_str: 203 self.cfg.set('trac', 'database', db_str) 204 self.save_config() 205 cnx = self.get_db_cnx(check_exists=0) 132 206 cursor = cnx.cursor() 133 cursor.execute(db_default.schema) 207 208 # get right db schema based on db_str 209 dbschema = db_default.schema 210 if db_str: 211 pos = db_str.find(':') 212 if pos == -1: 213 raise EnvironmentError, 'Connection param must be of form ' \ 214 '(db_module_name):(db_connect_params), the value "%s ' \ 215 'does not match' % db_str 216 module_name = db_str[:pos] 217 if module_name.lower() == "pgsql": 218 dbschema = db_default.schema_pgsql 219 cursor.execute(dbschema) 134 220 cnx.commit() 135 221 136 222 def insert_default_data(self): … … 138 224 if v == None: 139 225 return 'NULL' 140 226 else: 141 return '"%s"' % v 227 prepped = v 228 if type(v) == str: 229 prepped = prepped.replace("'", "''") 230 return "'%s'" % prepped 142 231 cnx = self.get_db_cnx() 143 232 cursor = cnx.cursor() 144 233 … … 149 238 values = ','.join(map(prep_value, row)) 150 239 sql = "INSERT INTO %s (%s) VALUES(%s);" % (table, cols, values) 151 240 cursor.execute(sql) 241 cnx.commit() 242 243 def setup_default_config(self): 152 244 for s,n,v in db_default.default_config: 153 245 if not self.cfg.has_section(s): 154 246 self.cfg.add_section(s) 155 247 self.cfg.set(s, n, v) 156 self.save_config()157 cnx.commit()158 248 159 249 def get_version(self): 160 250 cnx = self.get_db_cnx() … … 290 380 291 381 def backup(self, dest=None): 292 382 """Simple SQLite-specific backup. Copy the database file.""" 293 db_str = self.get_config('trac', 'database', 'sqlite:db/trac.db') 383 db_str = self.get_config('trac', 'database', 384 'sqlite:"db/trac.db",timeout=10000') 294 385 if db_str[:7] != 'sqlite:': 295 raise EnvironmentError, 'Can only backup sqlite databases' 386 print 'BACKUP FAILED: Can only backup sqlite databases.' 387 &
