PostgresqlPatch: pgsql_patch_14.diff
| File pgsql_patch_14.diff, 35.7 kB (added by brad <brad@dsource.org>, 4 years ago) |
|---|
-
trac/env.py
old new 28 28 import shutil 29 29 import sys 30 30 import time 31 from types import * 31 32 import urllib 32 33 import unicodedata 33 34 … … 44 45 * Project specific templates and wiki macros. 45 46 * wiki and ticket attachments. 46 47 """ 47 def __init__(self, path, create=0 ):48 def __init__(self, path, create=0, db_str='sqlite:db/trac.db'): 48 49 self.path = path 49 50 if create: 50 self.create( )51 self.create(db_str) 51 52 self.verify() 52 53 self.load_config() 53 54 try: # Use binary I/O on Windows … … 81 82 repos = SubversionRepository(repos_dir, authz, self.log) 82 83 return CachedRepository(self.get_db_cnx(), repos, authz, self.log) 83 84 84 def create(self ):85 def create(self, db_str): 85 86 def _create_file(fname, data=None): 86 87 fd = open(fname, 'w') 87 88 if data: fd.write(data) … … 120 121 # Site CSS - Place custom CSS, including overriding styles here. 121 122 ?> 122 123 """) 123 # Create default database 124 import sqlite 125 os.mkdir(os.path.join(self.path, 'db')) 126 cnx = sqlite.connect(os.path.join(self.path, 'db', 'trac.db')) 127 cursor = cnx.cursor() 128 cursor.execute(db_default.schema) 129 cnx.commit() 124 # set up the config file 125 self.load_config() 126 self.setup_default_config() 127 self.config.set('trac', 'database', db_str) 128 self.config.save() 130 129 130 # Create default database by attempting to get connection 131 cnx = db.get_cnx(self, create=1) 132 cnx.close 133 131 134 def insert_default_data(self): 132 135 def prep_value(v): 133 136 if v == None: 134 137 return 'NULL' 135 138 else: 136 return '"%s"' % v 139 prepped = v 140 if type(v) is StringType: 141 prepped = util.sql_escape(prepped) 142 return "'%s'" % prepped 137 143 cnx = self.get_db_cnx() 138 144 cursor = cnx.cursor() 139 145 … … 144 150 values = ','.join(map(prep_value, row)) 145 151 sql = "INSERT INTO %s (%s) VALUES(%s);" % (table, cols, values) 146 152 cursor.execute(sql) 153 cnx.commit() 147 154 155 def setup_default_config(self): 148 156 for section,name,value in db_default.default_config: 149 157 self.config.set(section, name, value) 150 158 self.config.save() 151 159 152 cnx.commit()153 154 160 def get_version(self): 155 161 cnx = self.get_db_cnx() 156 162 cursor = cnx.cursor() -
trac/db_default.py
old new 37 37 ## Default data 38 38 ## 39 39 40 schema = """41 CREATE TABLE revision(42 rev text PRIMARY KEY,43 time integer,44 author text,45 message text46 ); 47 CREATE TABLE node_change(48 rev text,49 path text,50 kind char(1), -- 'D' for directory, 'F' for file51 change char(1),52 base_path text,53 base_rev text,54 UNIQUE(rev, path, change)55 ); 56 CREATE TABLE auth_cookie(57 cookie text,58 name text,59 ipnr text,60 time integer,61 UNIQUE(cookie, name, ipnr) 62 ); 63 CREATE TABLE enum ( 64 type text,65 name text, 66 value text,67 UNIQUE(name,type)68 ); 69 CREATE TABLE system ( 70 name text PRIMARY KEY,71 value text,72 UNIQUE(name)73 ); 74 CREATE TABLE ticket ( 75 id integer PRIMARY KEY,76 time integer, -- the time it was created77 changetime integer,78 component text,79 severity text,80 priority text,81 owner text, -- who is this ticket assigned to82 reporter text,83 cc text, -- email addresses to notify84 url text, -- url related to this ticket85 version text, --86 milestone text, -- 87 status text,88 resolution text,89 summary text, -- one-line summary90 description text, -- problem description (long)91 keywords text92 ); 93 CREATE TABLE ticket_change(94 ticket integer,95 time integer, 96 author text,97 field text,98 oldvalue text,99 newvalue text, 100 UNIQUE(ticket, time, field)101 ); 102 CREATE TABLE ticket_custom ( 103 ticket integer,104 name text,105 value text, 106 UNIQUE(ticket,name)107 ); 108 CREATE TABLE report(109 id integer PRIMARY KEY,110 author text,111 title text, 112 sql text,113 description text114 ); 115 CREATE TABLE permission ( 116 username text, -- 117 action text, -- allowable activity118 UNIQUE(username,action)119 ); 120 CREATE TABLE component(121 name text PRIMARY KEY,122 owner text123 ); 124 CREATE TABLE milestone ( 125 name text PRIMARY KEY,126 due integer,127 completed integer,128 description text129 ); 130 CREATE TABLE version ( 131 name text PRIMARY KEY, 132 time integer133 ); 134 CREATE TABLE wiki ( 135 name text,136 version integer,137 time integer,138 author text,139 ipnr text,140 text text, 141 comment text,142 readonly integer,143 UNIQUE(name,version)144 ); 145 CREATE TABLE attachment(146 type text,147 id text,148 filename text, 149 size integer,150 time integer, 151 description text, 152 author text, 153 ipnr text, 154 UNIQUE(type,id,filename) 155 ); 40 schema = ( 41 ('revision', ( 42 ('rev', 'text', '', 'u'), 43 ('time', 'int', '', ''), 44 ('author', 'text', '', ''), 45 ('message', 'text', '', ''))), 46 ('node_change', 47 ( 48 ('rev', 'text', '', 'u'), 49 ('path', 'text', '', 'u'), 50 ('kind', 'char', '1', ''), 51 ('change', 'text', '1', 'u'), 52 ('base_path', 'text', '', ''), 53 ('base_rev', 'text', '', '')), 54 ( 55 ('node_change_idx', ('rev',)), )), 56 ('auth_cookie', ( 57 ('cookie', 'text', '', 'u'), 58 ('name', 'text', '', 'u'), 59 ('ipnr', 'text', '', 'u'), 60 ('time', 'int', '', ''))), 61 ('enum', ( 62 ('type', 'text', '', 'u'), 63 ('name', 'text', '', 'u'), 64 ('value', 'text', '', ''))), 65 ('system', ( 66 ('name', 'text', '', 'u'), 67 ('value', 'text', '', ''))), 68 ('ticket', ( 69 ('id', 'auto', '', 'u'), 70 ('time', 'int', '', ''), 71 ('changetime', 'int', '', ''), 72 ('component', 'text', '', ''), 73 ('severity', 'text', '', ''), 74 ('priority', 'text', '', ''), 75 ('owner', 'text', '', ''), 76 ('reporter', 'text', '', ''), 77 ('cc', 'text', '', ''), 78 ('url', 'text', '', ''), 79 ('version', 'text', '', ''), 80 ('milestone', 'text', '', ''), 81 ('status', 'text', '', ''), 82 ('resolution', 'text', '', ''), 83 ('summary', 'text', '', ''), 84 ('description', 'text', '', ''), 85 ('keywords', 'text', '', ''))), 86 ('ticket_change', ( 87 ('ticket', 'int', '', 'u'), 88 ('time', 'int', '', 'u'), 89 ('author', 'text', '', ''), 90 ('field', 'text', '', 'u'), 91 ('oldvalue', 'text', '', ''), 92 ('newvalue', 'text', '', '')), 93 ( 94 ('ticket_change_idx', ('ticket', 'time')), )), 95 ('ticket_custom', ( 96 ('ticket', 'int', '', 'u'), 97 ('name', 'text', '', 'u'), 98 ('value', 'text', '', ''))), 99 ('report', ( 100 ('id', 'auto', '', 'u'), 101 ('author', 'text', '', ''), 102 ('title', 'text', '', ''), 103 ('sql', 'text', '', ''), 104 ('description', 'text', '', ''))), 105 ('permission', ( 106 ('username', 'text', '', 'u'), 107 ('action', 'text', '', 'u'))), 108 ('component', ( 109 ('name', 'text', '', 'u'), 110 ('owner', 'text', '', ''))), 111 ('milestone', ( 112 ('name', 'text', '', 'u'), 113 ('due', 'int', '', ''), 114 ('completed', 'int', '', ''), 115 ('description', 'text', '', ''))), 116 ('version', ( 117 ('name', 'text', '', 'u'), 118 ('time', 'int', '', ''))), 119 ('wiki', 120 ( 121 ('name', 'text', '', 'u'), 122 ('version', 'int', '', 'u'), 123 ('time', 'int', '', ''), 124 ('author', 'text', '', ''), 125 ('ipnr', 'text', '', ''), 126 ('text', 'text', '', ''), 127 ('comment', 'text', '', ''), 128 ('readonly', 'int', '', '')), 129 ( 130 ('wiki_idx', ('name', 'version')), )), 131 ('attachment', ( 132 ('type', 'text', '', 'u'), 133 ('id', 'text', '', 'u'), 134 ('filename', 'text', '', 'u'), 135 ('size', 'int', '', ''), 136 ('time', 'int', '', ''), 137 ('description', 'text', '', ''), 138 ('author', 'text', '', ''), 139 ('ipnr', 'text', '', ''))), 140 ('session', ( 141 ('sid', 'text', '', 'u'), 142 ('username', 'text', '', ''), 143 ('var_name', 'text', '', 'u'), 144 ('var_value', 'text', '', '')), 145 ( 146 ('session_idx', ('sid', 'var_name')), )) 147 148 ) 149 150 # TODO: do we need these, or will the u's above do? 151 #CREATE INDEX node_change_idx ON node_change(rev); 152 #CREATE INDEX ticket_change_idx ON ticket_change(ticket, time); 153 #CREATE INDEX wiki_idx ON wiki(name,version); 154 #CREATE INDEX session_idx ON session(sid,var_name); 155 #""" 156 156 157 CREATE TABLE session (158 sid text,159 username text,160 var_name text,161 var_value text,162 UNIQUE(sid,var_name)163 );164 157 165 CREATE INDEX node_change_idx ON node_change(rev);166 CREATE INDEX ticket_change_idx ON ticket_change(ticket, time);167 CREATE INDEX wiki_idx ON wiki(name,version);168 CREATE INDEX session_idx ON session(sid,var_name);169 """170 158 171 159 ## 172 160 ## Default Reports … … 289 277 FROM ticket t,enum p 290 278 WHERE p.name=t.priority AND p.type='priority' 291 279 ORDER BY (milestone IS NULL), milestone DESC, (status = 'closed'), 292 (CASE status WHEN 'closed' THEN modifiedELSE (-1)*p.value END) DESC280 (CASE status WHEN 'closed' THEN changetime ELSE (-1)*p.value END) DESC 293 281 """), 294 282 #---------------------------------------------------------------------------- 295 283 ('My Tickets', -
trac/scripts/admin.py
old new 28 28 import cmd 29 29 import shlex 30 30 import StringIO 31 import traceback 31 32 32 33 from trac import perm, util 33 34 from trac.env import Environment … … 95 96 return 0 96 97 return 1 97 98 98 def env_create(self ):99 def env_create(self, db_str): 99 100 try: 100 self.__env = Environment(self.envname, create=1)101 self.__env = Environment(self.envname, 1, db_str) 101 102 return self.__env 102 103 except Exception, e: 103 104 print 'Failed to create environment.', e 105 print traceback.print_exc() 104 106 sys.exit(1) 105 107 106 108 def db_open(self): … … 121 123 cnx = None 122 124 cursor.execute(sql) 123 125 while 1: 124 row = cursor.fetchone() 126 row = None; 127 try: 128 row = cursor.fetchone() 129 except Exception, e: 130 pass 125 131 if row == None: 126 132 break 127 133 data.append(row) … … 473 479 474 480 ## Initenv 475 481 _help_initenv = [('initenv', 'Create and initialize a new environment interactively'), 476 ('initenv <projectname> <repospath> <templatepath> ',482 ('initenv <projectname> <repospath> <templatepath> <dbstr>', 477 483 'Create and initialize a new environment from arguments')] 478 484 479 485 def do_initdb(self, line): … … 506 512 dt = trac.siteconfig.__default_templates_dir__ 507 513 prompt = 'Templates directory [%s]> ' % dt 508 514 returnvals.append(raw_input(prompt) or dt) 515 print 516 print ' Please specify the database connection string.' 517 print ' Default is for SQLite database.' 518 print ' Examples of current options:' 519 print " SQLite - sqlite:db/trac.db" 520 print " PostgreSQL - pypgsql:host='localhost',port='5432',database='trac',user='trac',password='trac'" 521 print 522 db = 'sqlite:db/trac.db' 523 # db = "pypgsql:host='localhost',port='5432',database='trac',user='trac',password='trac'" 524 prompt = 'Database connection string [%s]> ' % db 525 returnvals.append(raw_input(prompt) or db) 509 526 return returnvals 510 527 511 528 def do_initenv(self, line): … … 521 538 project_name = returnvals[0] 522 539 repository_dir = returnvals[1] 523 540 templates_dir = returnvals[2] 524 elif len(arg)!= 3: 541 db_str = returnvals[3] 542 elif len(arg)!= 4: 525 543 print 'Wrong number of arguments to initenv %d' % len(arg) 526 544 return 527 545 else: 528 546 project_name = arg[0] 529 547 repository_dir = arg[1] 530 548 templates_dir = arg[2] 549 db_str = arg[3] 531 550 532 551 if not os.access(os.path.join(templates_dir, 'browser.cs'), os.F_OK) \ 533 552 or not os.access(os.path.join(templates_dir, 'ticket.cs'), os.F_OK): … … 535 554 return 536 555 try: 537 556 print 'Creating and Initializing Project' 538 self.env_create( )557 self.env_create(db_str) 539 558 cnx = self.__env.get_db_cnx() 540 559 print ' Inserting default data' 541 560 self.__env.insert_default_data() … … 562 581 563 582 except Exception, e: 564 583 print 'Failed to initialize database.', e 584 print traceback.print_exc() 565 585 sys.exit(2) 566 586 567 587 -
trac/Search.py
old new 136 136 'Search Error') 137 137 138 138 cursor = self.db.cursor () 139 139 union_fields = self.db.get_union_fields('search') 140 140 141 q = [] 141 142 if changeset: 142 143 q.append("SELECT 1 as type, message AS title, message, author, " 143 "'' AS keywords, revAS data, time,0 AS ver "144 "'' AS keywords, %s AS data, time,0 AS ver " 144 145 "FROM revision WHERE %s OR %s" % 145 (self.query_to_sql(query, 'message'), 146 (union_fields['changeset'], 147 self.query_to_sql(query, 'message'), 146 148 self.query_to_sql(query, 'author'))) 147 149 if tickets: 148 150 q.append("SELECT DISTINCT 2 as type, a.summary AS title, " 149 151 "a.description AS message, a.reporter AS author, " 150 "a.keywords as keywords, a.idAS data, a.time as time, 0 AS ver "152 "a.keywords as keywords, %s AS data, a.time as time, 0 AS ver " 151 153 "FROM ticket a LEFT JOIN ticket_change b ON a.id = b.ticket " 152 154 "WHERE (b.field='comment' AND %s ) OR " 153 155 "%s OR %s OR %s OR %s OR %s" % 154 (self.query_to_sql(query, 'b.newvalue'), 156 (union_fields['ticket'], 157 self.query_to_sql(query, 'b.newvalue'), 155 158 self.query_to_sql(query, 'summary'), 156 159 self.query_to_sql(query, 'keywords'), 157 160 self.query_to_sql(query, 'description'), -
trac/Timeline.py
old new 20 20 # Author: Jonas Borgström <jonas@edgewall.com> 21 21 22 22 from trac import perm 23 from trac.util import enum, escape, shorten_line 23 from trac.util import enum, escape, shorten_line, TracError 24 24 from trac.Module import Module 25 25 from trac.versioncontrol.svn_authz import SubversionAuthorizer 26 26 from trac.web.main import add_link … … 43 43 if not filters: 44 44 return [] 45 45 46 sql, params = [], [] 46 sql = [] 47 union_fields = self.db.get_union_fields('timeline') 48 49 # sql being formatted for each query below is necessary for casts as 50 # string replacements. This doesn't work in cursor.execute() b/c it's 51 # a string replacement. You'd end up with select 'cast(a.id as text)' - 52 # with the undesirable quotes. 47 53 if 'changeset' in filters: 48 sql.append("SELECT time, rev,'','changeset',message,author"49 " FROM revision WHERE time>=%s AND time<=%s" )50 params += (start, stop)54 sql.append("SELECT time,%s,'','changeset',message,author" 55 " FROM revision WHERE time>=%s AND time<=%s" 56 % (union_fields['changeset'], start, stop) ) 51 57 if 'ticket' in filters: 52 sql.append("SELECT time, id,'','newticket',summary,reporter"53 " FROM ticket WHERE time>=%s AND time<=%s" )54 params += (start, stop)55 sql.append("SELECT time, ticket,'','reopenedticket','',author "58 sql.append("SELECT time,%s,'','newticket',summary,reporter" 59 " FROM ticket WHERE time>=%s AND time<=%s" 60 % (union_fields['ticket'], start, stop) ) 61 sql.append("SELECT time,%s,'','reopenedticket','',author " 56 62 "FROM ticket_change WHERE field='status' " 57 "AND newvalue='reopened' AND time>=%s AND time<=%s" )58 params += (start, stop)59 sql.append("SELECT t1.time, t1.ticket,t2.newvalue,'closedticket',"63 "AND newvalue='reopened' AND time>=%s AND time<=%s" 64 % (union_fields['ticket_change_1'], start, stop) ) 65 sql.append("SELECT t1.time,%s,t2.newvalue,'closedticket'," 60 66 "t3.newvalue,t1.author" 61 67 " FROM ticket_change t1" 62 68 " INNER JOIN ticket_change t2 ON t1.ticket = t2.ticket" … … 65 71 " AND t1.ticket = t3.ticket AND t3.field = 'comment'" 66 72 " WHERE t1.field = 'status' AND t1.newvalue = 'closed'" 67 73 " AND t2.field = 'resolution'" 68 " AND t1.time >= %s AND t1.time <= %s" )69 params += (start,stop)74 " AND t1.time >= %s AND t1.time <= %s" 75 % (union_fields['ticket_change_2'], start, stop) ) 70 76 if 'wiki' in filters: 71 sql.append("SELECT time, -1,name,'wiki',comment,author"72 " FROM wiki WHERE time>=%s AND time<=%s" )73 params += (start, stop)77 sql.append("SELECT time,'',name,'wiki',comment,author" 78 " FROM wiki WHERE time>=%s AND time<=%s" 79 % (start, stop) ) 74 80 if 'milestone' in filters: 75 sql.append("SELECT completed AS time, -1,name,'milestone','',''"76 " FROM milestone WHERE completed>=%s AND completed<=%s" )77 params += (start, stop)81 sql.append("SELECT completed AS time,'',name,'milestone','',''" 82 " FROM milestone WHERE completed>=%s AND completed<=%s" 83 % (start, stop) ) 78 84 79 85 sql = ' UNION ALL '.join(sql) + ' ORDER BY time DESC' 80 86 if maxrows: 81 sql += ' LIMIT %d' 82 params += (maxrows,) 83 87 sql += ' LIMIT %d' % maxrows 88 84 89 cursor = self.db.cursor() 85 cursor.execute(sql , params)86 90 cursor.execute(sql) 91 87 92 # Make the data more HDF-friendly 88 93 info = [] 89 94 for idx, row in enum(cursor): … … 95 100 'time': time.strftime('%H:%M', t), 96 101 'date': time.strftime('%x', t), 97 102 'datetime': time.strftime('%a, %d %b %Y %H:%M:%S GMT', gmt), 98 'idata': int(row[1]),103 'idata': row[1], 99 104 'tdata': escape(row[2]), 100 105 'type': row[3], 101 106 'message': row[4] or '', -
trac/Report.py
old new 110 110 cursor = self.db.cursor() 111 111 cursor.execute("INSERT INTO report (title,sql,description) " 112 112 "VALUES (%s,%s,%s)", (title, sql, description)) 113 id = self.db.get_last_id( )113 id = self.db.get_last_id("report", "id") 114 114 self.db.commit() 115 115 req.redirect(self.env.href.report(id)) 116 116 -
trac/db.py
old new 21 21 22 22 from __future__ import generators 23 23 24 from trac import db_default 24 25 from trac.util import TracError 25 26 26 27 import os 27 28 import os.path 29 import string 28 30 from threading import Condition, Lock 29 31 30 32 … … 76 78 77 79 __slots__ = ['cnx'] 78 80 79 def __init__(self, dbpath, timeout=10000):81 def __init__(self, dbpath, env, create=0, timeout=10000): 80 82 self.cnx = None 83 if create: 84 self.create_db(env.path, dbpath) 85 81 86 if dbpath != ':memory:': 82 87 if not os.access(dbpath, os.F_OK): 83 88 raise TracError, 'Database "%s" not found.' % dbpath … … 93 98 import sqlite 94 99 cnx = sqlite.connect(dbpath, timeout=timeout) 95 100 ConnectionWrapper.__init__(self, cnx) 96 97 def get_last_id(self): 101 102 def get_last_id(self, table, field): 103 # table, field needed in other dbms but not sqlite, so ignore them here. 98 104 return self.cnx.db.sqlite_last_insert_rowid() 99 105 106 def create_db(self, path, dbpath): 107 108 # make the directory to hold the database 109 os.mkdir(os.path.join(path, 'db')) 110 111 # create the database by getting a connection 112 import sqlite 113 cnx = sqlite.connect(dbpath, timeout=100) 114 115 # populate the default schema 116 schema = db_default.schema 117 sql = "" 118 119 120 for tables in schema: 121 table = tables[0] 122 fields = tables[1] 123 indices = None 124 if len(tables) > 2: 125 indices = tables[2] 126 127 sql_fields = [] 128 unique = [] 129 sql += "CREATE TABLE %s (\n" % table 130 131 for field in fields: 132 name = field[0] 133 type = field[1] 134 size = field[2] 135 pk = field[3] 136 137 if type == 'auto': 138 type = 'INTEGER PRIMARY KEY' 139 140 if pk == 'u': 141 unique.append(name) 142 143 sql_fields.append(" %s %s" % (name, type)) 144 145 if len(unique): 146 sql_fields.append(" UNIQUE(%s)" % ",".join(unique)) 147 sql += ",\n".join(sql_fields) 148 sql += "\n);\n\n" 149 150 if indices: 151 for index in indices: 152 iname = index[0] 153 ifields = index[1] 154 sql += "CREATE INDEX %s ON %s (%s);\n\n" \ 155 % (iname, table, ','.join(ifields)) 156 157 #print "%s \n------------------------" % sql 158 cursor = cnx.cursor() 159 cursor.execute(sql) 160 cnx.commit() 161 162 cursor.close() 163 cnx.close() 100 164 101 def get_cnx(env): 165 def get_union_fields(self, module): 166 if module == 'search': 167 return {'changeset' : 'rev', 168 'ticket' : 'a.id'} 169 elif module == 'timeline': 170 return {'changeset' : 'rev', 171 'ticket' : 'id', 172 'ticket_change_1' : 'ticket', 173 'ticket_change_2' : 't1.ticket'} 174 175 176 177 class PyPgSQLConnection(ConnectionWrapper): 178 """ 179 Connection wrapper for PostgreSQL using the PyPgSQL driver. 180 """ 181 182 __slots__ = ['cnx'] 183 184 def __init__(self, dbargs, env, create=0): 185 if create: 186 self.create_db(env.path, dbargs) 187 188 # TODO: check to see if db exists, or throw error (see sqlite cnx) 189 190 args = self.parse_args(dbargs) 191 192 from pyPgSQL import PgSQL 193 cnx = PgSQL.connect("", **args) 194 ConnectionWrapper.__init__(self, cnx) 195 196 def get_last_id(self, table, field): 197 cursor = self.cursor() 198 sql = "SELECT %s FROM %s " \ 199 "WHERE %s = CURRVAL('%s_%s_seq')" \ 200 % (field, table, field, table, field) 201 cursor.execute(sql) 202 id = cursor.fetchone()[0] 203 cursor.close() 204 return id 205 206 def create_db(self, path, dbargs): 207 208 from pyPgSQL import PgSQL 209 210 args = self.parse_args(dbargs) 211 createdb_str = "createdb --host=%s --port=%s --owner=%s " \ 212 "--username=%s %s\n" \ 213 % (args['host'], args['port'], args['user'], 214 args['user'], args['database']) 215 print createdb_str 216 try: 217 # TODO: this is not cross-platform. 218 # for Windows, look at win32pipe.popen() 219 os.popen(createdb_str) 220 except Exception, e: 221 print "Error creating PostgreSQL database: %s" % e 222 print "command: %s" % createdb_str 223 224 # get a connection 225 cnx = PgSQL.connect("", **args) 226 227 # populate the default schema 228 schema = db_default.schema 229 sql = "" 230 231 for tables in schema: 232 table = tables[0] 233 fields = tables[1] 234 indices = None 235 if len(tables) > 2: 236 indices = tables[2] 237 238 sql_fields = [] 239 unique = [] 240 sql += "CREATE TABLE %s (\n" % table 241 242 for field in fields: 243 name = field[0] 244 type = field[1] 245 size = field[2] 246 pk = field[3] 247 248 if type == 'auto': 249 type = 'serial' 250 251 if pk == 'u': 252 unique.append(name) 253 254 sql_fields.append(" %s %s" % (name, type)) 255 256 if len(unique): 257 sql_fields.append(" CONSTRAINT %s_pkey PRIMARY KEY(%s)" % 258 (table, ",".join(unique))) 259 sql += ",\n".join(sql_fields) 260 sql += "\n);\n\n" 261 262 if indices: 263 for index in indices: 264 iname = index[0] 265 ifields = index[1] 266 sql += "CREATE INDEX %s ON %s (%s);\n\n" \ 267 % (iname, table, ','.join(ifields)) 268 269 #print "%s \n------------------------" % sql 270 cursor = cnx.cursor() 271 cursor.execute(sql) 272 cnx.commit() 273 274 cursor.close() 275 cnx.close() 276 277 def parse_args(self, dbargs): 278 """very crude code for parsing the arguments in connect_params""" 279 280 kargs = {} 281 args = dbargs.split(",") 282 283 for arg in args: 284 pair = arg.split("=") 285 name = pair[0] 286 value = pair[1].strip("'") 287 kargs[name] = value 288 289 return kargs 290 291 def get_union_fields(self, module): 292 if module == 'search': 293 return {'changeset' : 'cast(rev as text)', 294 'ticket' : 'cast(a.id as text)'} 295 elif module == 'timeline': 296 return {'changeset' : 'cast(rev as text)', 297 'ticket' : 'cast(id as text)', 298 'ticket_change_1' : 'cast(ticket as text)', 299 'ticket_change_2' : 'cast(t1.ticket as text)'} 300 301 def get_cnx(env, create=0): 102 302 db_str = env.config.get('trac', 'database') 103 303 scheme, rest = db_str.split(':', 1) 104 304 105 305 if scheme == 'sqlite': 106 306 if not rest.startswith('/'): 107 307 rest = os.path.join(env.path, rest) 108 return SQLiteConnection(rest )308 return SQLiteConnection(rest, env, create) 109 309 310 if scheme == 'pypgsql': 311 return PyPgSQLConnection(rest, env, create) 312 110 313 raise TracError, 'Unsupported database type "%s"' % scheme 111 314 112 315 -
trac/Ticket.py
old new 106 106 % (','.join(std_fields), 107 107 ','.join(['%s'] * len(std_fields))), 108 108 map(lambda n, self=self: self[n], std_fields)) 109 id = db.get_last_id( )109 id = db.get_last_id("ticket", "id") 110 110 111 111 custom_fields = filter(lambda n: n[:7] == 'custom_', self.keys()) 112 112 for name in custom_fields: -
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 Note: Haven't maintained this for a while. Use very carefully. 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, _clean): 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 # if _clean == 1: 70 # pg_cur.execute("truncate table %s;" % t) 71 pg_cur.execute("truncate table %s;" % t) 72 73 # get table info 74 sql = "SELECT * FROM %s" % t 75 trac_cur.execute(sql) 76 cols = trac_cur.rs.col_defs 77 counter = 0 78 79 # loop thru rows, moving data from sqlite to pgsql 80 while 1: 81 row = trac_cur.fetchone() 82 counter += 1 83 if not row: 84 break 85 flds="" 86 vals="" 87 for c in cols: 88 field = c[0] 89 type = c[1] 90 value = row[field] 91 if value != None: 92 flds += ", %s" % field 93 if type in [6]: 94 value = "'%s'" % sql_escape(value) 95 vals += ", %s" % value 96 flds = flds[2:] 97 vals = vals[2:] 98 sql = "INSERT INTO %s " % t 99 sql += "(%s) " % flds 100 sql += "VALUES (%s);" % vals 101 102 pg_cur.execute(sql) 103 pg_con.commit() 104 105 if counter % 100 == 0: 106 print "%s rows" % counter 107 108 trac_cur.close() 109 trac_con.close() 110 pg_cur.close() 111 pg_con.close() 112 print 113 114 115 def usage(): 116 print "tracdb-sqlite2pg - Converts a Trac database from sqlite to " \ 117 "postgresql." 118 print 119 print "This script is designed to transfer an existing Trac SQLite " 120 print "database to an existing Trac PosgreSQL database. The two " 121 print "databases should be of the same version. Check in the 'system' " 122 print "table in each database to verify. This script runs on version 8 " 123 print "and above. This is for Trac pre 0.9 (revision 1169 and higher)." 124 print 125 print "Note: you can make a Trac PosgreSQL database with trac-admin " 126 print "(the version that accompanies this script)" 127 print 128 print "THIS WILL DESTROY ALL DATA IN THE POSTGRESQL DATABASE !! " 129 print 130 print 131 print "Usage: tracdb-sqlite2pg.py [options]" 132 print 133 print "Available Options:" 134 print " -t | --tracenv /path/to/trac/env - full path to Trac environment" 135
