PostgresqlPatch: pgsql_patch_08.diff
| File pgsql_patch_08.diff, 59.5 kB (added by brad <brad@dsource.org>, 7 years ago) |
|---|
-
scripts/trac-admin
old new 27 27 import time 28 28 import cmd 29 29 import shlex 30 import sqlite31 30 import StringIO 31 import traceback 32 32 33 33 from trac import util 34 34 from trac import sync … … 92 92 return 0 93 93 return 1 94 94 95 def env_create(self ):95 def env_create(self, db_str): 96 96 try: 97 self.__env = trac.Environment.Environment (self.envname, create=1)97 self.__env = trac.Environment.Environment (self.envname, 1, db_str) 98 98 return self.__env 99 99 except Exception, e: 100 100 print 'Failed to create environment.', e … … 111 111 112 112 def db_execsql (self, sql, cursor=None): 113 113 data = [] 114 row = None 114 115 if not cursor: 115 116 cnx=self.db_open() 116 117 cursor = cnx.cursor() … … 118 119 cnx = None 119 120 cursor.execute(sql) 120 121 while 1: 121 row = cursor.fetchone() 122 try: 123 row = cursor.fetchone() 124 except: 125 pass 122 126 if row == None: 123 127 break 124 128 data.append(row) … … 457 461 458 462 ## Initenv 459 463 _help_initenv = [('initenv', 'Create and initialize a new environment interactively'), 460 ('initenv <projectname> <repospath> <templatepath> ',464 ('initenv <projectname> <repospath> <templatepath> <dbms> [dbms options]', 461 465 'Create and initialize a new environment from arguments')] 462 466 463 467 def do_initdb(self, line): … … 490 494 dt = trac.siteconfig.__default_templates_dir__ 491 495 prompt = 'Templates directory [%s]> ' % dt 492 496 returnvals.append(raw_input(prompt) or dt) 497 print 498 print " Please enter the database in which you wish to store Trac data." 499 print " Default is 'sqlite', but others are supported:" 500 print " 'sqlite' - SQLite http://www.sqlite.org" 501 print " 'pgsql' - PostgreSQL http://www.postgresql.org" 502 print 503 ddb = "sqlite" 504 prompt = 'database system [%s]> ' % ddb 505 dbms = raw_input(prompt) or ddb 506 returnvals.append(dbms) 507 508 # PostgreSQL - additional questions 509 if dbms == "pgsql": 510 print 511 print " Please enter the host of your PostgreSQL database." 512 print " Default is 'localhost'" 513 print 514 host = "localhost" 515 prompt = "PostgreSQL host [%s]> " % host 516 returnvals.append(raw_input(prompt) or host) 517 518 print 519 print " Please enter the port of your PostgreSQL database." 520 print " Default is '5432'" 521 print 522 port = "5432" 523 prompt = "PostgreSQL port [%s]> " % port 524 returnvals.append(raw_input(prompt) or port) 525 526 print 527 print " Please enter the name of your PostgreSQL database." 528 print " Default is 'trac'" 529 print " Note: This database should not exist, as trac-admin will" \ 530 " attempt to create it." 531 print 532 name = "trac" 533 prompt = "PostgreSQL database [%s]> " % name 534 returnvals.append(raw_input(prompt) or name) 535 536 print 537 print " Please enter the user of your PostgreSQL database." 538 print " Default is 'trac'" 539 print 540 user = "trac" 541 prompt = "PostgreSQL user [%s]> " % user 542 returnvals.append(raw_input(prompt) or user) 543 544 print 545 print " Please enter the password of your PostgreSQL database." 546 print " Default is 'trac'" 547 print 548 password = "trac" 549 prompt = "PostgreSQL password [%s]> " % password 550 returnvals.append(raw_input(prompt) or password) 551 493 552 return returnvals 494 553 495 554 def do_initenv(self, line): … … 500 559 project_name = None 501 560 repository_dir = None 502 561 templates_dir = None 562 db_str = None 503 563 if len(arg) == 1: 504 564 returnvals = self.get_initenv_args() 505 565 project_name = returnvals[0] 506 566 repository_dir = returnvals[1] 507 567 templates_dir = returnvals[2] 508 elif len(arg)!= 3: 568 db_str = returnvals[3] 569 elif len(arg) < 4: 509 570 print 'Wrong number of arguments to initenv %d' % len(arg) 510 571 return 511 572 else: 512 573 project_name = arg[0] 513 574 repository_dir = arg[1] 514 575 templates_dir = arg[2] 576 db_str = arg[3] 577 578 # sqlite-specific stuff 579 if db_str.lower() == "sqlite": 580 db_str = 'sqlite:"db/trac.db",timeout=10000' 581 582 # postgres-specific stuff 583 if db_str.lower() == "pgsql": 584 if len(arg) == 1: 585 host = returnvals[4] 586 port = returnvals[5] 587 database = returnvals[6] 588 user = returnvals[7] 589 password = returnvals[8] 590 elif len(arg) != 9: 591 print 'Wrong number of arguments to initenv %d' % len(arg) 592 print 'For PostgreSQL (after pgsql): <host> <port> <database>' \ 593 ' <user> <password>' 594 return 595 else: 596 host = arg[4] 597 port = arg[5] 598 database = arg[6] 599 user = arg[7] 600 password = arg[8] 601 db_str = "pgsql:\"\",host='%s:%s',database='%s',user='%s'," \ 602 "password='%s'" \ 603 % (host, port, database, user, password) 604 createdb_str = "createdb --host=%s --port=%s --owner=%s " \ 605 "--username=%s %s\n" \ 606 % (host, port, user, user, database) 607 print createdb_str 608 try: 609 # TODO: this is not cross-platform. 610 # for Windows, look at win32pipe.popen() 611 os.popen(createdb_str) 612 except Exception, e: 613 print "Error creating PostgreSQL database: %s" % e 614 print "command: %s" % createdb_str 615 515 616 from svn import util, repos, core 516 617 core.apr_initialize() 517 618 pool = core.svn_pool_create(None) … … 530 631 return 531 632 try: 532 633 print 'Creating and Initializing Project' 533 self.env_create( )634 self.env_create(db_str) 534 635 cnx = self.__env.get_db_cnx() 535 636 print ' Inserting default data' 536 637 self.__env.insert_default_data() … … 669 770 self.do_help ('wiki') 670 771 except Exception, e: 671 772 print 'Wiki %s failed:' % arg[0], e 773 print traceback.print_exc() 774 672 775 673 776 def _do_wiki_list(self): 674 777 data = self.db_execsql('SELECT name,max(version),time' … … 799 902 self.print_listing(['Possible Values'], data) 800 903 801 904 def _do_enum_add(self, type, name): 905 802 906 sql = ("INSERT INTO enum(value,type,name) " 803 907 " SELECT 1+COALESCE(max(value),0),'%(type)s','%(name)s'" 804 908 " FROM enum WHERE type='%(type)s'" -
trac/db_default.py
old new 172 172 CREATE INDEX session_idx ON session(sid,var_name); 173 173 """ 174 174 175 schema_pgsql = """ 176 CREATE TABLE revision ( 177 rev integer, 178 time integer, 179 author text, 180 message text, 181 CONSTRAINT revision_pkey PRIMARY KEY (rev) 182 ); 183 184 CREATE TABLE node_change ( 185 rev integer, 186 name text, 187 change char(1), 188 CONSTRAINT node_change_pkey PRIMARY KEY (rev, name, change) 189 ); 190 191 CREATE TABLE auth_cookie ( 192 cookie text, 193 name text, 194 ipnr text, 195 time integer, 196 CONSTRAINT auth_cookie_pkey PRIMARY KEY(cookie, name, ipnr) 197 ); 198 199 CREATE TABLE enum ( 200 type text, 201 name text, 202 value integer, 203 CONSTRAINT enum_pkey PRIMARY KEY(name,type) 204 ); 205 206 CREATE TABLE system ( 207 name text, 208 value text, 209 CONSTRAINT system_pkey PRIMARY KEY(name) 210 ); 211 212 CREATE TABLE lock ( 213 name text, 214 owner text, 215 ipnr text, 216 time integer, 217 CONSTRAINT lock_pkey PRIMARY KEY(name) 218 ); 219 220 --CREATE SEQUENCE ticket_id_seq; 221 CREATE TABLE ticket ( 222 id serial, 223 time integer, -- the time it was created 224 changetime integer, 225 component text, 226 severity text, 227 priority text, 228 owner text, -- who is this ticket assigned to 229 reporter text, 230 cc text, -- email addresses to notify 231 url text, -- url related to this ticket 232 version text, -- 233 milestone text, -- 234 status text, 235 resolution text, 236 summary text, -- one-line summary 237 description text, -- problem description (long) 238 keywords text, 239 CONSTRAINT ticket_pkey PRIMARY KEY(id) 240 ); 241 242 CREATE TABLE ticket_change ( 243 ticket integer, 244 time integer, 245 author text, 246 field text, 247 oldvalue text, 248 newvalue text, 249 CONSTRAINT ticket_change_pkey PRIMARY KEY(ticket, time, field) 250 ); 251 252 CREATE TABLE ticket_custom ( 253 ticket integer, 254 name text, 255 value text, 256 CONSTRAINT ticket_custom_pkey PRIMARY KEY(ticket,name) 257 ); 258 259 --CREATE SEQUENCE report_id_seq; 260 CREATE TABLE report ( 261 id serial, 262 author text, 263 title text, 264 sql text, 265 description text, 266 CONSTRAINT report_pkey PRIMARY KEY(id) 267 ); 268 269 CREATE TABLE permission ( 270 username text, -- 271 action text, -- allowable activity 272 CONSTRAINT permission_pkey PRIMARY KEY(username,action) 273 ); 274 275 CREATE TABLE component ( 276 name text, 277 owner text, 278 CONSTRAINT component_pkey PRIMARY KEY(name) 279 ); 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 ); 288 289 CREATE TABLE version ( 290 name text, 291 time integer, 292 CONSTRAINT version_pkey PRIMARY KEY(name) 293 ); 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 ); 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 ); 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 ); 326 327 """ 328 175 329 ## 176 330 ## Default Reports 177 331 ## … … 293 447 FROM ticket t,enum p 294 448 WHERE p.name=t.priority AND p.type='priority' 295 449 ORDER BY (milestone IS NULL), milestone DESC, (status = 'closed'), 296 (CASE status WHEN 'closed' THEN modifiedELSE (-1)*p.value END) DESC450 (CASE status WHEN 'closed' THEN changetime ELSE (-1)*p.value END) DESC 297 451 """), 298 452 #---------------------------------------------------------------------------- 299 453 ('My Tickets', … … 411 565 (('trac', 'htdocs_location', '/trac/'), 412 566 ('trac', 'repository_dir', '/var/svn/myrep'), 413 567 ('trac', 'templates_dir', '/usr/lib/trac/templates'), 414 ('trac', 'database', 'sqlite: db/trac.db'),568 ('trac', 'database', 'sqlite:"db/trac.db",timeout=10000'), 415 569 ('trac', 'default_charset', 'iso-8859-15'), 416 570 ('logging', 'log_type', 'none'), 417 571 ('logging', 'log_file', 'trac.log'), -
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): -
trac/Report.py
old new 110 110 def create_report(self, req, title, description, sql): 111 111 self.perm.assert_permission(perm.REPORT_CREATE) 112 112 113 dbms = self.env.get_dbms() 113 114 cursor = self.db.cursor() 114 cursor.execute("INSERT INTO report (title, sql, description)" 115 " VALUES (%s, %s, %s)", title, sql, description) 116 id = self.db.db.sqlite_last_insert_rowid() 115 cursor.execute('INSERT INTO report (title, sql, description)' 116 'VALUES (%s, %s, %s)', (title, sql, description)) 117 # FIXME: move to connection object 118 if dbms == 'pgsql': 119 cursor.execute("SELECT id FROM report " \ 120 "WHERE id = CURRVAL('report_id_seq')") 121 id = cursor.fetchone()[0] 122 else: # sqlite way 123 id = self.db.db.sqlite_last_insert_rowid() 124 117 125 self.db.commit() 118 126 req.redirect(self.env.href.report(id)) 119 127 -
trac/tests/tracadmin-tests.txt
old new 1 1 ===== test_help_ok ===== 2 trac-admin - The Trac Administration Console %(version)s2 trac-admin - The Trac Administration Console 0.8 3 3 4 4 Usage: trac-admin </path/to/projenv> [command [subcommand] [option ...]] 5 5 6 6 Invoking trac-admin without command starts interactive mode. 7 7 8 about -- Shows information about trac-admin9 help -- Show documentation10 initenv -- Create and initialize a new environment interactively11 initenv <projectname> <repospath> <templatepath> -- Create and initialize a new environment from arguments12 hotcopy <backupdir> -- Make a hot backup copy of an environment13 resync -- Re-synchronize trac with the repository14 upgrade -- Upgrade database to current version15 wiki list -- List wiki pages16 wiki export <page> [file] -- Export wiki page to file or stdout17 wiki import <page> [file] -- Import wiki page from file or stdin18 wiki dump <directory> -- Export all wiki pages to files named by title19 wiki load <directory> -- Import all wiki pages from directory20 wiki upgrade -- Upgrade default wiki pages to current version21 permission list -- List permission rules22 permission add <user> <action> [action] [...] -- Add a new permission rule23 permission remove <user> <action> [action] [...] -- Remove permission rule24 component list -- Show available components25 component add <name> <owner> -- Add a new component26 component rename <name> <newname> -- Rename a component27 component remove <name> -- Remove/uninstall component28 component chown <name> <owner> -- Change component ownership29 priority list -- Show possible ticket priorities30 priority add <value> -- Add a priority value option31 priority change <value> <newvalue> -- Change a priority value32 priority remove <value> -- Remove priority value33 severity list -- Show possible ticket priorities34 severity add <value> -- Add a severity value option35 severity change <value> <newvalue> -- Change a severity value36 severity remove <value> -- Remove severity value37 version list -- Show versions38 version add <name> [time] -- Add version39 version rename <name> <newname> -- Rename version40 version time <name> <time> -- Set version date (Format: "%(date_format_hint)s" or "now")41 version remove <name> -- Remove version42 milestone list -- Show milestones43 milestone add <name> [due] -- Add milestone44 milestone rename <name> <newname> -- Rename milestone45 milestone due <name> <due> -- Set milestone due date (Format: "%(date_format_hint)s" or "now")46 milestone completed <name> <completed> -- Set milestone completed date (Format: "%(date_format_hint)s" or "now")47 milestone remove <name> -- Remove milestone8 about -- Shows information about trac-admin 9 help -- Show documentation 10 initenv -- Create and initialize a new environment interactively 11 initenv <projectname> <repospath> <templatepath> <dbms> [dbms options] -- Create and initialize a new environment from arguments 12 hotcopy <backupdir> -- Make a hot backup copy of an environment 13 resync -- Re-synchronize trac with the repository 14 upgrade -- Upgrade database to current version 15 wiki list -- List wiki pages 16 wiki export <page> [file] -- Export wiki page to file or stdout 17 wiki import <page> [file] -- Import wiki page from file or stdin 18 wiki dump <directory> -- Export all wiki pages to files named by title 19 wiki load <directory> -- Import all wiki pages from directory 20 wiki upgrade -- Upgrade default wiki pages to current version 21 permission list -- List permission rules 22 permission add <user> <action> [action] [...] -- Add a new permission rule 23 permission remove <user> <action> [action] [...] -- Remove permission rule 24 component list -- Show available components 25 component add <name> <owner> -- Add a new component 26 component rename <name> <newname> -- Rename a component 27 component remove <name> -- Remove/uninstall component 28 component chown <name> <owner> -- Change component ownership 29 priority list -- Show possible ticket priorities 30 priority add <value> -- Add a priority value option 31 priority change <value> <newvalue> -- Change a priority value 32 priority remove <value> -- Remove priority value 33 severity list -- Show possible ticket priorities 34 severity add <value> -- Add a severity value option 35 severity change <value> <newvalue> -- Change a severity value 36 severity remove <value> -- Remove severity value 37 version list -- Show versions 38 version add <name> [time] -- Add version 39 version rename <name> <newname> -- Rename version 40 version time <name> <time> -- Set version date (Format: "MM/DD/YY" or "now") 41 version remove <name> -- Remove version 42 milestone list -- Show milestones 43 milestone add <name> [due] -- Add milestone 44 milestone rename <name> <newname> -- Rename milestone 45 milestone due <name> <due> -- Set milestone due date (Format: "MM/DD/YY" or "now") 46 milestone completed <name> <completed> -- Set milestone completed date (Format: "MM/DD/YY" or "now") 47 milestone remove <name> -- Remove milestone 48 48 49 49 Visit the Trac Project at http://trac.edgewall.com/ 50 50 -
trac/tests/ticket.py
old new 18 18 assert ticket['reporter'] == 'santa' 19 19 assert ticket['summary'] == 'Foo' 20 20 assert ticket['custom_foo'] == 'This is a custom field' 21 ticket.insert(self.db )21 ticket.insert(self.db, self.dbms) 22 22 # Retrieving ticket 23 23 ticket2 = Ticket(self.db, 1) 24 24 assert ticket2['id'] == 1 -
trac/tests/environment.py
old new 10 10 self.env = Environment(self._get_envpath(), create=1) 11 11 self.env.insert_default_data() 12 12 self.db = self.env.get_db_cnx() 13 self.dbms = self.env.get_dbms() 13 14 14 15 def tearDown(self): 15 16 self.env = None … … 36 37 37 38 def test_config(self): 38 39 """Testing env.get/set_config""" 39 assert self.env.get_config('trac', 'database') == 'sqlite:db/trac.db' 40 # Any way to do this with multiple backends now supported? 41 # assert self.env.get_config('trac', 'database') == 'sqlite:db/trac.db' 40 42 self.env.set_config('foo', 'bar', 'baz') 41 43 self.env.save_config() 42 44 assert self.env.get_config('foo', 'bar') == 'baz' -
trac/tests/query.py
old new 35 35 self.assertEqual(sql, 36 36 """SELECT id,summary,status,owner,priority,milestone,component 37 37 FROM ticket 38 LEFT OUTER JOIN (SELECT name AS priority_name, value AS priority_value FROM enum WHERE type='priority') ON priority_name=priority38 LEFT OUTER JOIN (SELECT name AS priority_name, value AS priority_value FROM enum WHERE type='priority') e ON priority_name=priority 39 39 ORDER BY COALESCE(priority,'')='',priority_value,id""") 40 40 41 41 def test_all_ordered_by_priority_desc(self): … … 44 44 self.assertEqual(sql, 45 45 """SELECT id,summary,status,owner,priority,milestone,component 46 46 FROM ticket 47 LEFT OUTER JOIN (SELECT name AS priority_name, value AS priority_value FROM enum WHERE type='priority') ON priority_name=priority47 LEFT OUTER JOIN (SELECT name AS priority_name, value AS priority_value FROM enum WHERE type='priority') e ON priority_name=priority 48 48 ORDER BY COALESCE(priority,'')='' DESC,priority_value DESC,id""") 49 49 50 50 def test_all_ordered_by_version(self): … … 53 53 self.assertEqual(sql, 54 54 """SELECT id,summary,status,owner,priority,milestone,version 55 55 FROM ticket 56 LEFT OUTER JOIN (SELECT name AS version_name, time AS version_time FROM version) ON version_name=version56 LEFT OUTER JOIN (SELECT name AS version_name, time AS version_time FROM version) a ON version_name=version 57 57 ORDER BY COALESCE(version,'')='',COALESCE(version_time,0)=0,version_time,version,id""") 58 58 59 59 def test_all_ordered_by_version_desc(self): … … 62 62 self.assertEqual(sql, 63 63 """SELECT id,summary,status,owner,priority,milestone,version 64 64 FROM ticket 65 LEFT OUTER JOIN (SELECT name AS version_name, time AS version_time FROM version) ON version_name=version65 LEFT OUTER JOIN (SELECT name AS version_name, time AS version_time FROM version) a ON version_name=version 66 66 ORDER BY COALESCE(version,'')='' DESC,COALESCE(version_time,0)=0 DESC,version_time DESC,version DESC,id""") 67 67 68 68 def test_constrained_by_milestone(self): … … 81 81 self.assertEqual(sql, 82 82 """SELECT id,summary,status,owner,priority,component,version,milestone 83 83 FROM ticket 84 LEFT OUTER JOIN (SELECT name AS milestone_name, due AS milestone_time FROM milestone) ON milestone_name=milestone84 LEFT OUTER JOIN (SELECT name AS milestone_name, due AS milestone_time FROM milestone) a ON milestone_name=milestone 85 85 ORDER BY COALESCE(milestone,'')='',COALESCE(milestone_time,0)=0,milestone_time,milestone,COALESCE(id,0)=0,id""") 86 86 87 87 def test_all_grouped_by_milestone_desc(self): … … 90 90 self.assertEqual(sql, 91 91 """SELECT id,summary,status,owner,priority,component,version,milestone 92 92 FROM ticket 93 LEFT OUTER JOIN (SELECT name AS milestone_name, due AS milestone_time FROM milestone) ON milestone_name=milestone93 LEFT OUTER JOIN (SELECT name AS milestone_name, due AS milestone_time FROM milestone) a ON milestone_name=milestone 94 94 ORDER BY COALESCE(milestone,'')='' DESC,COALESCE(milestone_time,0)=0 DESC,milestone_time DESC,milestone DESC,COALESCE(id,0)=0,id""") 95 95 96 96 def test_grouped_by_priority(self): … … 99 99 self.assertEqual(sql, 100 100 """SELECT id,summary,status,owner,milestone,component,version,priority 101 101 FROM ticket 102 LEFT OUTER JOIN (SELECT name AS priority_name, value AS priority_value FROM enum WHERE type='priority') ON priority_name=priority102 LEFT OUTER JOIN (SELECT name AS priority_name, value AS priority_value FROM enum WHERE type='priority') e ON priority_name=priority 103 103 ORDER BY COALESCE(priority,'')='',priority_value,id""") 104 104 105 105 def test_constrained_by_milestone_not(self): … … 170 170 self.assertEqual(sql, 171 171 """SELECT id,summary,status,owner,priority,milestone,component, foo.value AS foo 172 172 FROM ticket 173 LEFT OUTER JOIN ticket_custom AS foo ON (id=foo.ticket AND foo.name='foo') 173 LEFT OUTER JOIN ticket_custom AS foo ON (id=foo.ticket AND foo.name='foo') tc 174 174 WHERE COALESCE(foo,'')='something' 175 175 ORDER BY COALESCE(id,0)=0,id""") 176 176 -
trac/tests/db.py
old new 1 2 import unittest 3 from trac.Environment import Environment # TODO: take out trac. when being run 4 # from normal trac/test.py 5 6 class DBTestBase: 7 def setUp(self): 8 pass 9 10 def tearDown(self): 11 pass 12 13 class DBTestCase(DBTestBase, unittest.TestCase): 14 def test_connect(self): 15 """Testing db.connect""" 16 env = Environment('/var/trac/test') # TODO: make more generic 17 # for now, it's my local pgsql env 18 cnx = env.get_db_cnx() 19 cursor = cnx.cursor() 20 cursor.execute("select * from system") 21 row = cursor.fetchone() 22 print row 23 cnx.close() 24 25 def test_parse_args(self): 26 """Testing db.parse_args""" 27 28 def suite(): 29 return unittest.makeSuite(DBTestCase,'test') 30 31 # TODO: take this out when we put this in with the other tests 32 # Q: will we be able to do these tests for different dbms's in the test suite? 33 if __name__ == '__main__': 34 unittest.main(defaultTest='suite') 35 -
trac/Session.py
old new 64 64 def get_session(self, sid): 65 65 self.sid = sid 66 66 curs = self.db.cursor() 67 curs.execute("SELECT username,var_name,var_value FROM session" 68 " WHERE sid=%s", self.sid)67 curs.execute("SELECT username,var_name,var_value FROM session" 68 " WHERE sid=%s", (self.sid,)) 69 69 rows = curs.fetchall() 70 70 if (not rows # No session data yet 71 71 or rows[0][0] == 'anonymous' # Anon session -
trac/db.py
old new 1 # -*- coding: iso8859-1 -*- 2 # 3 # Copyright (C) 2005 Edgewall Software 4 # Copyright (C) 2005 Brad Anderson <brad@dsource.org> 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: Brad Anderson <brad@dsource.org> 21 22 import os 23 24 class DBConnection: 25 def __init__(self, module_name, connect_params): 26 # set some variables 27 self.module_name = module_name 28 self.connect_params = connect_params 29 30 # prepare the connection 31 self.parse_args() 32 self.connect() 33 34 def __getattr__(self, name): 35 """DBConnection is a wrapper for the dbms's connection, and here's 36 the magic that allows this.""" 37 return getattr(self.db, name) 38 39 def parse_args(self): 40 """very crude code for parsing the arguments in connect_params""" 41 kargs = {} 42 arg_list = [] 43 for x in self.connect_params: 44 pos1 = x.find('=') 45 pos2 = x.find('"') 46 pos3 = x.find("'") 47 if pos1 > -1: 48 if pos2 > -1 and pos2 < pos1: 49 arg_list.append(eval(x)) 50 elif pos3 > -1 and pos3 < pos1: 51 arg_list.append(eval(x)) 52 else: 53 name = x[:pos1].strip() 54 value = eval(x[pos1+1:].strip()) 55 kargs[name] = value 56 else: 57 arg_list.append(eval(x)) 58 self.args = tuple(arg_list) 59 self.kargs = kargs 60 61 62 class SQLiteDBConnection(DBConnection): 63 64 def connect(self): 65 66 # FIXME: this was pulled from Environment, and so some of the self.* 67 # variables need to be cleaned up and this method tested. 68 69 70 # since Trac has a slightly closer relationship with sqlite than 71 # other db's, there's a special case setup here so that when the 72 # path to the sqlite db is specified, its relative to TRAC_ENV 73 db_name = os.path.join(self.path, args[0]) 74 args = list(args) 75 args[0] = '%s' % db_name 76 args = tuple(args) 77 if check_exists == 1 and not os.access(db_name, os.F_OK): 78 raise EnvironmentError, 'Database "%s" not found.' % db_name 79 80 directory = os.path.dirname(db_name) 81 if (check_exists == 1 and not os.access(db_name, os.R_OK + os.W_OK)) \ 82 or not os.access(directory, os.R_OK + os.W_OK): 83 raise EnvironmentError, \ 84 'The web server user requires read _and_ write permission\n' \ 85 'to the database %s and the directory in which this file ' \ 86 'is located.' % db_name 87 88 # import database module 89 import_str = 'import sqlite' 90 exec import_str 91 m = eval('sqlite') 92 93 # get connection 94 self.db = m.connect(*self.args, **self.kargs) 95 96 97 class PostgreSQLDBConnection(DBConnection): 98 99 def connect(self): 100 101 # get strings for proper pgsql module 102 if self.module_name == 'pgsql': 103 import_str = 'from pyPgSQL import PgSQL' 104 module_str = 'PgSQL' 105 else: 106 raise EnvironmentError, "Unknown PostgreSQL DB module '%s'" \ 107 % self.module_name 108 109 # import database module 110 exec import_str 111 m = eval(module_str) 112 113 # get connection 114 self.db = m.connect(*self.args, **self.kargs) -
trac/auth.py
old new 32 32 cookie = req.incookie['trac_auth'].value 33 33 cursor.execute ("SELECT name FROM auth_cookie " 34 34 "WHERE cookie=%s AND ipnr=%s" 35 35 36 ,cookie, req.remote_addr) 36 37 row = cursor.fetchone() 37 38 if row: 38 39 self.authname = row[0] 39 40 41 40 42 def login(self, req): 41 43 cursor = self.db.cursor () 42 44 cookie = util.hex_entropy() 43 45 cursor.execute ("INSERT INTO auth_cookie (cookie, name, ipnr, time)" + 44 "VALUES (%s, %s, %s, % d)",45 cookie, req.remote_user, req.remote_addr,46 int(time.time()) );46 "VALUES (%s, %s, %s, %s)", 47 (cookie, req.remote_user, req.remote_addr, 48 int(time.time()),)); 47 49 self.db.commit () 48 50 self.authname = req.remote_user 49 51 req.outcookie['trac_auth'] = cookie … … 52 54 def logout(self): 53 55 cursor = self.db.cursor () 54 56 cursor.execute ("DELETE FROM auth_cookie WHERE name=%s", 55 self.authname)57 (self.authname,)) 56 58 self.db.commit () -
trac/Environment.py
old new 34 34 import Logging 35 35 import Mimeview 36 36 import unicodedata 37 import db 37 38 38 import sqlite 39 from types import * 39 40 40 41 db_version = db_default.db_version 41 42 … … 46 47 A Trac environment consists of a directory structure containing 47 48 among other things: 48 49 * a configuration file. 49 * a sqlitedatabase (stores tickets, wiki pages...)50 * a database (stores tickets, wiki pages...) 50 51 * Project specific templates and wiki macros. 51 52 * wiki and ticket attachments. 52 53 """ 53 def __init__(self, path, create=0 ):54 def __init__(self, path, create=0, db_str=None): 54 55 self.path = path 55 56 if create: 56 self.create( )57 self.create(db_str) 57 58 self.verify() 58 59 self.load_config() 59 60 try: # Use binary I/O on Windows … … 64 65 pass 65 66 self.setup_log() 66 67 self.setup_mimeviewer() 68 self.dbms = self.get_dbms() 67 69 68 70 def verify(self): 69 71 """Verifies that self.path is a compatible trac environment""" … … 71 73 assert fd.read(26) == 'Trac Environment Version 1' 72 74 fd.close() 73 75 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 76 def get_dbms(self): 77 db_str = self.get_config('trac', 'database') 78 if not db_str: 79 return 'sqlite' 80 pos = db_str.find(':') 81 if pos == -1: 82 raise EnvironmentError, 'Connection param must be of form ' \ 83 '(db_module_name):(db_connect_params), the value "%s ' \ 84 'does not match' % db_str 80 85 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) 86 dbms = db_str[:pos] 87 return dbms 88 89 90 def get_db_cnx(self, check_exists=1, db_str=None): 91 if db_str is None: 92 db_str = self.get_config('trac', 93 'database', 94 'sqlite:"db/trac.db",timeout=10000') 95 pos = db_str.find(':') 96 if pos == -1: 97 raise EnvironmentError, 'Connection param must be of form ' \ 98 '(db_module_name):(db_connect_params), the value "%s ' \ 99 'does not match' % db_str 100 module_name = db_str[:pos] 101 connect_params = db_str[pos+1:].split(',') 102 103 if module_name.lower() == 'sqlite': 104 conn = db.SQLiteDBConnection(module_name, connect_params) 105 elif module_name.lower() == 'pgsql': 106 conn = db.PostgreSQLDBConnection(module_name, connect_params) 107 else: 108 raise EnvironmentError, 'Unrecognized database in trac.ini: %s' \ 109 % module_name 110 111 return conn 89 112 90 def create(self): 113 114 def create(self, db_str=None): 91 115 def _create_file(fname, data=None): 92 116 fd = open(fname, 'w') 93 117 if data: fd.write(data) … … 110 134 'This directory contains project-specific custom templates and style sheet.\n') 111 135 _create_file(os.path.join(self.get_templates_dir(), 'site_header.cs'), 112 136 """<?cs 113 ####################################################################114 # Site header - Contents are automatically inserted above Trac HTML115 ?>116 """)137 #################################################################### 138 # Site header - Contents are automatically inserted above Trac HTML 139 ?> 140 """) 117 141 _create_file(os.path.join(self.get_templates_dir(), 'site_footer.cs'), 118 142 """<?cs 119 #########################################################################120 # Site footer - Contents are automatically inserted after main Trac HTML121 ?>122 """)143 ######################################################################### 144 # Site footer - Contents are automatically inserted after main Trac HTML 145 ?> 146 """) 123 147 _create_file(os.path.join(self.get_templates_dir(), 'site_css.cs'), 124 148 """<?cs 125 ##################################################################126 # Site CSS - Place custom CSS, including overriding styles here.127 ?>128 """)149 ################################################################## 150 # Site CSS - Place custom CSS, including overriding styles here. 151 ?> 152 """) 129 153 # Create default database 130 154 os.mkdir(os.path.join(self.path, 'db')) 131 cnx = sqlite.connect(os.path.join(self.path, 'db', 'trac.db')) 155 self.load_config() 156 self.setup_default_config() 157 if db_str: 158 self.cfg.set('trac', 'database', db_str) 159 self.save_config() 160 cnx = self.get_db_cnx(check_exists=0) 132 161 cursor = cnx.cursor() 133 cursor.execute(db_default.schema) 162 163 # get right db schema based on db_str 164 dbschema = db_default.schema 165 if db_str: 166 pos = db_str.find(':') 167 if pos == -1: 168 raise EnvironmentError, 'Connection param must be of form ' \ 169 '(db_module_name):(db_connect_params), the value "%s ' \ 170 'does not match' % db_str 171 module_name = db_str[:pos] 172 if module_name.lower() == "pgsql": 173 dbschema = db_default.schema_pgsql 174 cursor.execute(dbschema) 134 175 cnx.commit() 135 176 136 177 def insert_default_data(self): … … 138 179 if v == None: 139 180 return 'NULL' 140 181 else: 141 return '"%s"' % v 182 prepped = v 183 if type(v) is StringType: 184 prepped = prepped.replace("'", "''") 185 return "'%s'" % prepped 142 186 cnx = self.get_db_cnx() 143 187 cursor = cnx.cursor() 144 188 … … 149 193 values = ','.join(map(prep_value, row)) 150 194 sql = "INSERT INTO %s (%s) VALUES(%s);" % (table, cols, values) 151 195 cursor.execute(sql) 196 cnx.commit() 197 198 def setup_default_config(self): 152 199 for s,n,v in db_default.default_config: 153 200 if not self.cfg.has_section(s): 154 201 self.cfg.add_section(s) 155 202 self.cfg.set(s, n, v) 156 self.save_config()157 cnx.commit()158 203 159 204 def get_version(self): 160 205 cnx = self.get_db_cnx() … … 218 263 cursor = cnx.cursor() 219 264 cursor.execute('SELECT filename,description,type,size,time,author,ipnr ' 220 265 'FROM attachment ' 221 'WHERE type=%s AND id=%s ORDER BY time', type, id)266 'WHERE type=%s AND id=%s ORDER BY time', (type, id,)) 222 267 return cursor.fetchall() 223 268 224 269 def get_attachments_hdf(self, cnx, type, id, hdf, prefix): … … 290 335 291 336 def backup(self, dest=None): 292 337 """Simple SQLite-specific backup. Copy the database file.""" 293 db_str = self.get_config('trac', 'database', 'sqlite:db/trac.db') 338 db_str = self.get_config('trac', 'database', 339 'sqlite:"db/trac.db",timeout=10000') 294 340 if db_str[:7] != 'sqlite:': 295 raise EnvironmentError, 'Can only backup sqlite databases' 341 print 'BACKUP FAILED: Can only backup sqlite databases.' 342 # TODO: should probably ask if they want to continue 343 # or at least handle this better by shelling out to backup 344 # other dbs like pgsql... 345 return 296 346 db_name = os.path.join(self.path, db_str[7:]) 297 347 if not dest: 298 348 dest = '%s.%i.bak' % (db_name, self.get_version()) … … 321 371 err = 'No upgrade module for version %i (%s.py)' % (i, upg) 322 372 raise EnvironmentError, err 323 373 d.do_upgrade(self, i, cursor) 324 cursor.execute("UPDATE system SET value=% iWHERE "374 cursor.execute("UPDATE system SET value=%s WHERE " 325 375 "name='database_version'", db_default.db_version) 326 376 self.log.info('Upgraded db version from %d to %d', 327 377 dbver, db_default.db_version) 328 378 cnx.commit() 379 print 'Upgrade succeeded.' 329 380 return 1 -
trac/Ticket.py
old new 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 cursor.execute('SELECT name,value FROM ticket_custom WHERE ticket=%s', id) 77 77 rows = cursor.fetchall() 78 78 if rows: 79 79 for r in rows: … … 93 93 if not dict.has_key(name): 94 94 self[name] = '0' 95 95 96 def insert(self, db ):96 def insert(self, db, dbms): 97 97 """Add ticket to database""" 98 98 cursor = db.cursor() 99 99 assert not self.has_key('id') … … 106 106 std_fields = filter(lambda n: n[:7] != 'custom_', self.keys()) 107 107 custom_fields = filter(lambda n: n[:7] == 'custom_', self.keys()) 108 108 std_values = map(lambda n, self=self: self[n], std_fields) 109 109 110 nstr = string.join(std_fields, ',') 110 111 vstr = ('%s,' * len(std_fields))[:-1] 111 cursor.execute('INSERT INTO ticket (%s) VALUES (%s)' % (nstr, vstr),112 cursor.execute('INSERT INTO ticket (%s) VALUES (%s)' % (nstr, vstr), 112 113 *std_values) 113 id = db.db.sqlite_last_insert_rowid() 114 115 if dbms == 'pgsql': 116 cursor.execute("SELECT id FROM ticket " \ 117 "WHERE id = CURRVAL('ticket_id_seq')") 118 id = cursor.fetchone()[0] 119 else: # sqlite way 120 id = db.db.sqlite_last_insert_rowid() 121 114 122 for name in custom_fields: 115 123 cursor.execute('INSERT INTO ticket_custom(ticket,name,value)' 116 ' VALUES(% d, %s, %s)', id, name[7:], self[name])124 ' VALUES(%s, %s, %s)', id, name[7:], self[name]) 117 125 db.commit() 118 126 self['id'] = id 119 127 self._forget_changes() … … 149 157 for name in self._old.keys(): 150 158 if name[:7] == 'custom_': 151 159 fname = name[7:] 152 cursor.execute('REPLACE INTO ticket_custom(ticket,name,value)' 160 # some dbms's don't support REPLACE INTO, so we have to do 161 # this detection and delete 162 cursor.execute("SELECT * FROM ticket_custom " 163 "WHERE ticket=%s and name=%s" 164 , id, fname) 165 if cursor.fetchone() is not None: 166 cursor.execute("DELETE FROM ticket_custom " 167 "WHERE ticket=%s and name=%s" 168 , id, fname) 169 cursor.execute('INSERT INTO ticket_custom(ticket,name,value)' 153 170 ' VALUES(%s, %s, %s)', id, fname, self[name]) 154 171 else: 155 172 fname = name 156 cursor.execute ('UPDATE ticket SET %s=%s WHERE id=%s',157 fname, self[name], id)173 sql = "UPDATE ticket SET %s='%s' WHERE id=%s" \ 174 % (fname, self[name], id) 158 175 176 cursor.execute (sql) 177 159 178 cursor.execute ('INSERT INTO ticket_change ' 160 179 '(ticket, time, author, field, oldvalue, newvalue) ' 161 180 'VALUES (%s, %s, %s, %s, %s, %s)', … … 174 193 """Returns the changelog as a list of dictionaries""" 175 194 cursor = db.cursor() 176 195 if when: 177 cursor.execute( 'SELECT time, author, field, oldvalue, newvalue '178 'FROM ticket_change '179 'WHERE ticket=%s AND time=%s'180 'UNION '181 'SELECT time, author, "attachment", null, filename '182 'FROM attachment '183 'WHERE id=%s AND time=%s '184 'ORDER BY time', self['id'], when, self['id'], when)196 cursor.execute("SELECT time, author, field, oldvalue, newvalue " 197 "FROM ticket_change " 198 "WHERE ticket=%s AND time=%s" 199 "UNION " 200 "SELECT time, author, 'attachment', null, filename " 201 "FROM attachment " 202 "WHERE id=%s AND time=%s " 203 "ORDER BY time", self['id'], when, self['id'], when) 185 204 else: 186 cursor.execute( 'SELECT time, author, field, oldvalue, newvalue '187 'FROM ticket_change '188 'WHERE ticket=%s '189 'UNION '190 'SELECT time, author, "attachment", null,filename '191 'FROM attachment '192 'WHERE id = %s '193 'ORDER BY time', self['id'], self['id'])205 cursor.execute("SELECT time, author, field, oldvalue, newvalue " 206 "FROM ticket_change " 207 "WHERE ticket=%s " 208 "UNION " 209 "SELECT time, author, 'attachment', null,filename " 210 "FROM attachment " 211 "WHERE id = %s " 212 "ORDER BY time", self['id'], self['id']) 194 213 log = [] 195 214 while 1: 196 215 row = cursor.fetchone() … … 286 305 owner = cursor.fetchone()[0] 287 306 ticket['owner'] = owner 288 307 289 tktid = ticket.insert(self.db) 308 dbms = self.env.get_dbms() 309 tktid = ticket.insert(self.db, dbms) 290 310 291 311 # Notify 292 312 tn = TicketNotifyEmail(self.env) -
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, _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 print " -h | --host <pgsql hostname> - PostgreSQL hostname" 136 print " -db | --database <pgsql database> - PostgreSQL database name" 137 print " -u | --user <pgsql username> - PostgreSQL username" 138 print " -p | --passwd <pgsql password> - PostgreSQL password" 139 # print " -c | --clean - clean out PG database " \ 140 # "before converting. (recommended)" 141 print " --help | help - this help info" 142 print 143 print "Additional configuration options can be defined directly in the " \ 144 "script." 145 print 146 sys.exit(0) 147 148 def main(): 149 global TRAC_ENV, PG_HOST, PG_DB, PG_USER, PG_PASSWORD, PG_CLEAN 150 if len (sys.argv) > 1: 151 if sys.argv[1] in ['--help','help'] or len(sys.argv) < 4: 152 usage() 153 iter = 1 154 while iter < len(sys.argv): 155 if sys.argv[iter] in ['-t', '--tracenv'] and iter+1 < len(sys.argv): 156 TRAC_ENV = sys.argv[iter+1] 157 iter = iter + 1 158 elif sys.argv[iter] in ['-h', '--host'] and iter+1 < len(sys.argv): 159 PG_HOST = sys.argv[iter+1] 160 iter = iter + 1 161 elif sys.argv[iter] in ['-db', '--database'] and \ 162 iter+1 < len(sys.argv): 163 PG_DB = sys.argv[iter+1] 164 iter = iter + 1 165 elif sys.argv[iter] in ['-u', '--user'] and iter+1 < len(sys.argv): 166 PG_USER = sys.argv[iter+1] 167 iter = iter + 1 168 elif sys.argv[iter] in ['-p', '--passwd'] and \ 169 iter+1 < len(sys.argv): 170 PG_PASSWORD = sys.argv[iter+1] 171 iter = iter + 1 172 # elif sys.argv[iter] in ['-c', '--clean']: 173 # PG_CLEAN = 1 174 else: 175 print "Error: unknown parameter: " + sys.argv[iter] 176 sys.exit(0) 177 iter = iter + 1 178 else: 179 usage() 180 181 convert(TRAC_ENV, PG_HOST, PG_DB, PG_USER, PG_PASSWORD, PG_CLEAN) 182 183 184 if __name__ == '__main__': 185 main()
