PostgresqlPatch: pgsql_patch_06.diff

File pgsql_patch_06.diff, 74.3 kB (added by brad, 7 years ago)
  • scripts/trac-admin

    old new  
    2727import time 
    2828import cmd 
    2929import shlex 
    30 import sqlite 
    3130import StringIO 
     31import traceback 
    3232 
    3333from trac import util 
    3434from trac import sync 
     
    9292            return 0 
    9393        return 1 
    9494         
    95     def env_create(self): 
     95    def env_create(self, db_str): 
    9696        try: 
    97             self.__env = trac.Environment.Environment (self.envname, create=1
     97            self.__env = trac.Environment.Environment (self.envname, 1, db_str
    9898            return self.__env 
    9999        except Exception, e: 
    100100            print 'Failed to create environment.', e 
     
    111111 
    112112    def db_execsql (self, sql, cursor=None): 
    113113        data = [] 
     114        row = None 
    114115        if not cursor: 
    115116            cnx=self.db_open() 
    116117            cursor = cnx.cursor() 
     
    118119            cnx = None 
    119120        cursor.execute(sql) 
    120121        while 1: 
    121             row = cursor.fetchone() 
     122            try: 
     123                row = cursor.fetchone() 
     124            except: 
     125                pass 
    122126            if row == None: 
    123127                break 
    124128            data.append(row) 
     
    457461 
    458462    ## Initenv 
    459463    _help_initenv = [('initenv', 'Create and initialize a new environment interactively'), 
    460                      ('initenv <projectname> <repospath> <templatepath>', 
     464                     ('initenv <projectname> <repospath> <templatepath> <dbms> [dbms options]', 
    461465                      'Create and initialize a new environment from arguments')] 
    462466 
    463467    def do_initdb(self, line): 
     
    490494        dt = trac.siteconfig.__default_templates_dir__ 
    491495        prompt = 'Templates directory [%s]> ' % dt 
    492496        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             
    493552        return returnvals 
    494553          
    495554    def do_initenv(self, line): 
     
    500559        project_name = None 
    501560        repository_dir = None 
    502561        templates_dir = None 
     562        db_str = None 
    503563        if len(arg) == 1: 
    504564            returnvals = self.get_initenv_args() 
    505565            project_name = returnvals[0] 
    506566            repository_dir = returnvals[1] 
    507567            templates_dir = returnvals[2] 
    508         elif len(arg)!= 3: 
     568            db_str = returnvals[3] 
     569        elif len(arg) < 4: 
    509570            print 'Wrong number of arguments to initenv %d' % len(arg) 
    510571            return 
    511572        else: 
    512573            project_name = arg[0] 
    513574            repository_dir = arg[1] 
    514575            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         
    515616        from svn import util, repos, core 
    516617        core.apr_initialize() 
    517618        pool = core.svn_pool_create(None) 
     
    530631            return 
    531632        try: 
    532633            print 'Creating and Initializing Project' 
    533             self.env_create(
     634            self.env_create(db_str
    534635            cnx = self.__env.get_db_cnx() 
    535636            print ' Inserting default data' 
    536637            self.__env.insert_default_data() 
     
    669770                self.do_help ('wiki') 
    670771        except Exception, e: 
    671772            print 'Wiki %s failed:' % arg[0], e 
     773            print traceback.print_exc() 
     774             
    672775 
    673776    def _do_wiki_list(self): 
    674777        data = self.db_execsql('SELECT name,max(version),time' 
     
    694797        data = data.replace("'", "''") # Escape ' for safe SQL 
    695798        f.close() 
    696799         
    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'"  
     800        sql = ("INSERT INTO wiki(version,name,time,author,ipnr,text) " 
     801               " SELECT 1+COALESCE(max(version),0),'%(title)s','%(time)s'," 
     802               "'%(author)s','%(ipnr)s','%(text)s' " 
     803               "FROM wiki WHERE name='%(title)s'"  
    700804               % {'title':title, 
    701805                  'time':int(time.time()), 
    702806                  'author':'trac', 
     
    799903 
    800904    def _do_enum_add(self, type, name): 
    801905        sql = ("INSERT INTO enum('value','type','name') " 
    802                " SELECT 1+ifnull(max(value),0),'%(type)s','%(name)s'" 
     906               " SELECT 1+COALESCE(max(value),0),'%(type)s','%(name)s'" 
    803907               "   FROM enum WHERE type='%(type)s'"  
    804908               % {'type':type, 
    805909                  'name':name}) 
     
    867971 
    868972    def _do_milestone_list(self): 
    869973        data = self.db_execsql("SELECT name,due,completed FROM milestone " 
    870                                "ORDER BY IFNULL(due,0)!=0 DESC,due,name") 
     974                               "ORDER BY COALESCE(due,0)!=0 DESC,due,name") 
    871975        data = map(lambda x: (x[0], x[1] and time.strftime('%c', time.localtime(x[1])), 
    872976                              x[2] and time.strftime('%c', time.localtime(x[2]))), data) 
    873977        self.print_listing(['Name', 'Due', 'Completed'], data) 
     
    10071111                    print "Upgrade: Backup of old database saved in " \ 
    10081112                          "%s/db/trac.db.%i.bak" % (self.envname, curr) 
    10091113                else: 
    1010                     print "Upgrade: Backup disabled. Non-existant warranty voided." 
     1114                    print "Upgrade: Backup disabled. Non-existent warranty voided." 
    10111115                self.__env.upgrade(do_backup) 
    10121116            else: 
    10131117                print "Upgrade: Database is up to date, no upgrade necessary." 
  • trac/db_default.py

    old new  
    3030    result = [] 
    3131    i = 1 
    3232    for r in reps: 
    33         result.append ((i, None, r[0], r[2], r[1])) 
     33        result.append ((None, r[0], r[2], r[1])) 
    3434        i = i + 1 
    3535    return result 
    3636 
     
    174174CREATE INDEX session_idx        ON session(sid,var_name); 
    175175""" 
    176176 
     177schema_pgsql = """ 
     178CREATE TABLE revision ( 
     179        rev             integer, 
     180        time            integer, 
     181        author          text, 
     182        message         text, 
     183        CONSTRAINT revision_pkey PRIMARY KEY (rev) 
     184); 
     185 
     186CREATE TABLE node_change ( 
     187        rev             integer, 
     188        name            text, 
     189        change          char(1), 
     190        CONSTRAINT node_change_pkey PRIMARY KEY (rev, name, change) 
     191); 
     192 
     193CREATE 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); 
     200 
     201CREATE TABLE enum ( 
     202        type            text, 
     203        name            text, 
     204        value           integer, 
     205        CONSTRAINT enum_pkey PRIMARY KEY(name,type) 
     206); 
     207 
     208CREATE TABLE system ( 
     209        name            text, 
     210        value           text, 
     211        CONSTRAINT system_pkey PRIMARY KEY(name) 
     212); 
     213 
     214CREATE TABLE lock ( 
     215        name            text, 
     216        owner           text, 
     217        ipnr            text, 
     218        time            integer, 
     219        CONSTRAINT lock_pkey PRIMARY KEY(name) 
     220); 
     221 
     222--CREATE SEQUENCE ticket_id_seq; 
     223CREATE TABLE ticket ( 
     224        id              serial, 
     225        time            integer,        -- the time it was created 
     226        changetime      integer, 
     227        component       text, 
     228        severity        text, 
     229        priority        text, 
     230        owner           text,           -- who is this ticket assigned to 
     231        reporter        text, 
     232        cc              text,           -- email addresses to notify 
     233        url             text,           -- url related to this ticket 
     234        version         text,           --  
     235        milestone       text,           --  
     236        status          text, 
     237        resolution      text, 
     238        summary         text,           -- one-line summary 
     239        description     text,           -- problem description (long) 
     240        keywords        text, 
     241        CONSTRAINT ticket_pkey PRIMARY KEY(id) 
     242); 
     243 
     244CREATE TABLE ticket_change ( 
     245        ticket          integer, 
     246        time            integer, 
     247        author          text, 
     248        field           text, 
     249        oldvalue        text, 
     250        newvalue        text, 
     251        CONSTRAINT ticket_change_pkey PRIMARY KEY(ticket, time, field) 
     252); 
     253 
     254CREATE TABLE ticket_custom ( 
     255       ticket           integer, 
     256       name             text, 
     257       value            text, 
     258       CONSTRAINT ticket_custom_pkey PRIMARY KEY(ticket,name) 
     259); 
     260 
     261--CREATE SEQUENCE report_id_seq; 
     262CREATE TABLE report ( 
     263        id              serial, 
     264        author          text, 
     265        title           text, 
     266        sql             text, 
     267        description     text, 
     268        CONSTRAINT report_pkey PRIMARY KEY(id) 
     269); 
     270 
     271CREATE TABLE permission ( 
     272        username        text,           --  
     273        action          text,           -- allowable activity 
     274        CONSTRAINT permission_pkey PRIMARY KEY(username,action) 
     275); 
     276 
     277CREATE TABLE component ( 
     278         name            text, 
     279         owner           text, 
     280         CONSTRAINT component_pkey PRIMARY KEY(name) 
     281); 
     282 
     283CREATE TABLE milestone ( 
     284         name            text, 
     285         due             integer, -- Due date/time 
     286         completed       integer, -- Completed date/time 
     287         description     text, 
     288         CONSTRAINT milestone_pkey PRIMARY KEY(name) 
     289); 
     290 
     291CREATE TABLE version ( 
     292         name            text, 
     293         time            integer, 
     294         CONSTRAINT version_pkey PRIMARY KEY(name) 
     295); 
     296 
     297CREATE TABLE wiki ( 
     298         name            text, 
     299         version         integer, 
     300         time            integer, 
     301         author          text, 
     302         ipnr            text, 
     303         text            text, 
     304         comment         text, 
     305         readonly        integer, 
     306         CONSTRAINT wiki_pkey PRIMARY KEY(name,version) 
     307); 
     308 
     309CREATE TABLE attachment ( 
     310         type            text, 
     311         id              text, 
     312         filename        text, 
     313         size            integer, 
     314         time            integer, 
     315         description     text, 
     316         author          text, 
     317         ipnr            text, 
     318         CONSTRAINT attachment_pkey PRIMARY KEY(type,id,filename) 
     319); 
     320 
     321CREATE TABLE session ( 
     322         sid             text, 
     323         username        text, 
     324         var_name        text, 
     325         var_value       text, 
     326         CONSTRAINT session_pkey PRIMARY KEY(sid,var_name) 
     327); 
     328 
     329""" 
     330 
    177331## 
    178332## Default Reports 
    179333## 
     
    295449  FROM ticket t,enum p 
    296450  WHERE p.name=t.priority AND p.type='priority' 
    297451  ORDER BY (milestone IS NULL), milestone DESC, (status = 'closed'),  
    298         (CASE status WHEN 'closed' THEN modified ELSE -p.value END) DESC 
     452        (CASE status WHEN 'closed' THEN changetime ELSE (-1)*p.value END) DESC 
    299453"""), 
    300454#---------------------------------------------------------------------------- 
    301455('My Tickets', 
     
    406560             ('name', 'value'), 
    407561               (('database_version', str(db_version)),)), 
    408562           ('report', 
    409              ('id', 'author', 'title', 'sql', 'description'), 
     563             ('author', 'title', 'sql', 'description'), 
    410564               __mkreports(reports))) 
    411565 
    412566default_config = \ 
    413567 (('trac', 'htdocs_location', '/trac/'), 
    414568  ('trac', 'repository_dir', '/var/svn/myrep'), 
    415569  ('trac', 'templates_dir', '/usr/lib/trac/templates'), 
    416   ('trac', 'database', 'sqlite:db/trac.db'), 
     570  ('trac', 'database', 'sqlite:"db/trac.db",timeout=10000'), 
    417571  ('trac', 'default_charset', 'iso-8859-15'), 
    418572  ('logging', 'log_type', 'none'), 
    419573  ('logging', 'log_file', 'trac.log'), 
  • trac/Milestone.py

    old new  
    157157        cursor = self.db.cursor() 
    158158        self.log.debug("Creating new milestone '%s'" % name) 
    159159        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, 
    161161                       description) 
    162162        self.db.commit() 
    163163        self.req.redirect(self.env.href.milestone(name)) 
     
    196196                          'associated with milestone %s' % id) 
    197197            cursor.execute("UPDATE ticket SET milestone = %s " 
    198198                           "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", 
    201201                           name, due, completed, description, id) 
    202202            self.db.commit() 
    203203            self.req.redirect(self.env.href.milestone(name)) 
     
    209209        groups = [] 
    210210        if by in ['status', 'resolution', 'severity', 'priority']: 
    211211            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) 
    213213        elif by in ['component', 'milestone', 'version']: 
    214214            cursor.execute("SELECT name FROM %s " 
    215                            "WHERE IFNULL(name,'') != '' ORDER BY name" % by) 
     215                           "WHERE COALESCE(name,'') != '' ORDER BY name" % by) 
    216216        elif by == 'owner': 
    217217            cursor.execute("SELECT DISTINCT owner AS name FROM ticket " 
    218218                           "ORDER BY owner") 
  • trac/Search.py

    old new  
    117117 
    118118        cursor = self.db.cursor () 
    119119 
     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 
    120129        q = [] 
    121130        if changeset: 
    122131            q.append('SELECT 1 as type, message AS title, message, author, ' 
    123                      ' \'\' AS keywords, rev AS data, time,0 AS ver' 
     132                     ' \'\' AS keywords, %s AS data, time,0 AS ver' 
    124133                     ' FROM revision WHERE %s OR %s' %  
    125                      (self.query_to_sql(query, 'message'), 
     134                     (data_changeset, 
     135                      self.query_to_sql(query, 'message'), 
    126136                      self.query_to_sql(query, 'author'))) 
    127137        if tickets: 
    128138            q.append('SELECT DISTINCT 2 as type, a.summary AS title, ' 
    129139                     ' 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'), 
    135146                       self.query_to_sql(query, 'summary'), 
    136147                       self.query_to_sql(query, 'keywords'), 
    137148                       self.query_to_sql(query, 'description'), 
  • trac/Query.py

    old new  
    154154        sql.append("\nFROM ticket") 
    155155        for k in [k for k in cols if k in custom_fields]: 
    156156           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)) 
    158158 
    159159        for col in [c for c in ['status', 'resolution', 'priority', 'severity'] 
    160160                    if c == self.order or c == self.group]: 
    161161            sql.append("\n  LEFT OUTER JOIN (SELECT name AS %s_name, " \ 
    162162                                            "value AS %s_value " \ 
    163                                             "FROM enum WHERE type='%s')" \ 
     163                                            "FROM enum WHERE type='%s') e" \ 
    164164                       " ON %s_name=%s" % (col, col, col, col, col)) 
    165165        for col in [c for c in ['milestone', 'version'] 
    166166                    if c == self.order or c == self.group]: 
    167167            time_col = col == 'milestone' and 'due' or 'time' 
    168168            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" \ 
    170170                       " ON %s_name=%s" % (col, time_col, col, col, col, col)) 
    171171 
    172172        def get_constraint_sql(name, value, mode, neg): 
    173173            value = sql_escape(value[len(mode and '!' or '' + mode):]) 
    174174            if mode == '~' and value: 
    175                 return "IFNULL(%s,'') %sLIKE '%%%s%%'" % ( 
     175                return "COALESCE(%s,'') %sLIKE '%%%s%%'" % ( 
    176176                       name, neg and 'NOT ' or '', value) 
    177177            elif mode == '^' and value: 
    178                 return "IFNULL(%s,'') %sLIKE '%s%%'" % ( 
     178                return "COALESCE(%s,'') %sLIKE '%s%%'" % ( 
    179179                       name, neg and 'NOT ' or '', value) 
    180180            elif mode == '$' and value: 
    181                 return "IFNULL(%s,'') %sLIKE '%%%s'" % ( 
     181                return "COALESCE(%s,'') %sLIKE '%%%s'" % ( 
    182182                       name, neg and 'NOT ' or '', value) 
    183183            elif mode == '': 
    184                 return "IFNULL(%s,'')%s='%s'" % (name, neg and '!' or '', value) 
     184                return "COALESCE(%s,'')%s='%s'" % (name, neg and '!' or '', value) 
    185185 
    186186        clauses = [] 
    187187        for k, v in self.constraints.items(): 
     
    195195            # Special case for exact matches on multiple values 
    196196            if not mode and len(v) > 1: 
    197197                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)) 
    199199            elif len(v) > 1: 
    200200                constraint_sql = [get_constraint_sql(k, val, mode, neg) for val in v] 
    201201                if neg: 
     
    214214        if self.group and self.group != self.order: 
    215215            order_cols.insert(0, (self.group, self.groupdesc)) 
    216216        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) 
    219225            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) 
    221230            if col in ['status', 'resolution', 'priority', 'severity']: 
    222231                if desc: 
    223232                    sql.append("%s_value DESC" % col) 
     
    225234                    sql.append("%s_value" % col) 
    226235            elif col in ['milestone', 'version']: 
    227236                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" 
    229238                               % (col, col, col)) 
    230239                else: 
    231                     sql.append("IFNULL(%s_time,0)=0,%s_time,%s" 
     240                    sql.append("COALESCE(%s_time,0)=0,%s_time,%s" 
    232241                               % (col, col, col)) 
    233242            else: 
    234243                if desc: 
  • trac/Timeline.py

    old new  
    142142                if max_node != 0: 
    143143                    cursor_node = self.db.cursor () 
    144144                    cursor_node.execute("SELECT name, change " 
    145                                         "FROM node_change WHERE rev=%d" % item['idata']) 
     145                                        "FROM node_change WHERE rev=%s", item['idata']) 
    146146                    node_list = '' 
    147147                    node_data = '' 
    148148                    node_count = 0; 
  • trac/Report.py

    old new  
    110110    def create_report(self, title, description, sql): 
    111111        self.perm.assert_permission(perm.REPORT_CREATE) 
    112112 
     113        dbms = self.env.get_dbms() 
    113114        cursor = self.db.cursor() 
    114         cursor.execute('INSERT INTO report (id, title, sql, description)' 
    115                         'VALUES (NULL, %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                         
     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             
    117125        self.db.commit() 
    118126        self.req.redirect(self.env.href.report(id)) 
    119127 
     
    140148 
    141149        # FIXME: fetchall should probably not be used. 
    142150        info = cursor.fetchall() 
    143         cols = cursor.rs.col_defs 
     151        cols = cursor.description 
    144152        # Escape the values so that they are safe to have as html parameters 
    145153        #info = map(lambda row: map(lambda x: escape(x), row), info) 
    146154 
  • trac/tests/tracadmin-tests.txt

    old new  
    11===== test_help_ok ===== 
    2 trac-admin - The Trac Administration Console %(version)s 
     2trac-admin - The Trac Administration Console 0.8 
    33 
    44Usage: trac-admin </path/to/projenv> [command [subcommand] [option ...]] 
    55 
    66Invoking trac-admin without command starts interactive mode. 
    77 
    8 about                                             -- Shows information about trac-admin 
    9 help                                              -- Show documentation 
    10 initenv                                           -- Create and initialize a new environment interactively 
    11 initenv <projectname> <repospath> <templatepath> -- 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: "%(date_format_hint)s" 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: "%(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 milestone 
     8about                                                                   -- Shows information about trac-admin 
     9help                                                                    -- Show documentation 
     10initenv                                                                 -- Create and initialize a new environment interactively 
     11initenv <projectname> <repospath> <templatepath> <dbms> [dbms options] -- Create and initialize a new environment from arguments 
     12hotcopy <backupdir>                                                     -- Make a hot backup copy of an environment 
     13resync                                                                  -- Re-synchronize trac with the repository 
     14upgrade                                                                 -- Upgrade database to current version 
     15wiki list                                                               -- List wiki pages 
     16wiki export <page> [file]                                               -- Export wiki page to file or stdout 
     17wiki import <page> [file]                                               -- Import wiki page from file or stdin 
     18wiki dump <directory>                                                   -- Export all wiki pages to files named by title 
     19wiki load <directory>                                                   -- Import all wiki pages from directory 
     20wiki upgrade                                                            -- Upgrade default wiki pages to current version 
     21permission list                                                         -- List permission rules 
     22permission add <user> <action> [action] [...]                           -- Add a new permission rule 
     23permission remove <user> <action> [action] [...]                        -- Remove permission rule 
     24component list                                                          -- Show available components 
     25component add <name> <owner>                                            -- Add a new component 
     26component rename <name> <newname>                                       -- Rename a component 
     27component remove <name>                                                 -- Remove/uninstall component 
     28component chown <name> <owner>                                          -- Change component ownership 
     29priority list                                                           -- Show possible ticket priorities 
     30priority add <value>                                                    -- Add a priority value option 
     31priority change <value> <newvalue>                                      -- Change a priority value 
     32priority remove <value>                                                 -- Remove priority value 
     33severity list                                                           -- Show possible ticket priorities 
     34severity add <value>                                                    -- Add a severity value option 
     35severity change <value> <newvalue>                                      -- Change a severity value 
     36severity remove <value>                                                 -- Remove severity value 
     37version list                                                            -- Show versions 
     38version add <name> [time]                                               -- Add version 
     39version rename <name> <newname>                                         -- Rename version 
     40version time <name> <time>                                              -- Set version date (Format: "MM/DD/YY" or "now") 
     41version remove <name>                                                   -- Remove version 
     42milestone list                                                          -- Show milestones 
     43milestone add <name> [due]                                              -- Add milestone 
     44milestone rename <name> <newname>                                       -- Rename milestone 
     45milestone due <name> <due>                                              -- Set milestone due date (Format: "MM/DD/YY" or "now") 
     46milestone completed <name> <completed>                                  -- Set milestone completed date (Format: "MM/DD/YY" or "now") 
     47milestone remove <name>                                                 -- Remove milestone 
    4848 
    4949Visit the Trac Project at http://trac.edgewall.com/ 
    5050 
  • trac/tests/ticket.py

    old new  
    1818        assert ticket['reporter'] == 'santa' 
    1919        assert ticket['summary'] == 'Foo' 
    2020        assert ticket['custom_foo'] == 'This is a custom field' 
    21         ticket.insert(self.db
     21        ticket.insert(self.db, self.dbms
    2222        # Retrieving ticket 
    2323        ticket2 = Ticket(self.db, 1) 
    2424        assert ticket2['id'] == 1 
  • trac/tests/environment.py

    old new  
    1010        self.env = Environment(self._get_envpath(), create=1) 
    1111        self.env.insert_default_data() 
    1212        self.db = self.env.get_db_cnx() 
     13        self.dbms = self.env.get_dbms() 
    1314 
    1415    def tearDown(self): 
    1516        self.env = None 
     
    3637 
    3738    def test_config(self): 
    3839        """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' 
    4042        self.env.set_config('foo', 'bar', 'baz') 
    4143        self.env.save_config() 
    4244        assert self.env.get_config('foo', 'bar') == 'baz' 
  • trac/tests/query.py

    old new  
    1111        self.assertEqual(sql, 
    1212"""SELECT id,summary,status,owner,priority,milestone,component 
    1313FROM ticket 
    14 ORDER BY IFNULL(id,'')='',id""") 
     14ORDER BY COALESCE(id,0)=0,id""") 
    1515 
    1616    def test_all_ordered_by_id_desc(self): 
    1717        query = Query(self.env, order='id', desc=1) 
     
    1919        self.assertEqual(sql, 
    2020"""SELECT id,summary,status,owner,priority,milestone,component 
    2121FROM ticket 
    22 ORDER BY IFNULL(id,'')='' DESC,id DESC""") 
     22ORDER BY COALESCE(id,0)=0 DESC,id DESC""") 
    2323 
    2424    def test_all_ordered_by_id_verbose(self): 
    2525        query = Query(self.env, order='id', verbose=1) 
     
    2727        self.assertEqual(sql, 
    2828"""SELECT id,summary,status,owner,priority,milestone,component,reporter,time,description 
    2929FROM ticket 
    30 ORDER BY IFNULL(id,'')='',id""") 
     30ORDER BY COALESCE(id,0)=0,id""") 
    3131 
    3232    def test_all_ordered_by_priority(self): 
    3333        query = Query(self.env) # priority is default order 
     
    3535        self.assertEqual(sql, 
    3636"""SELECT id,summary,status,owner,priority,milestone,component 
    3737FROM ticket 
    38   LEFT OUTER JOIN (SELECT name AS priority_name, value AS priority_value FROM enum WHERE type='priority') ON priority_name=priority 
    39 ORDER BY IFNULL(priority,'')='',priority_value,id""") 
     38  LEFT OUTER JOIN (SELECT name AS priority_name, value AS priority_value FROM enum WHERE type='priority') e ON priority_name=priority 
     39ORDER BY COALESCE(priority,'')='',priority_value,id""") 
    4040 
    4141    def test_all_ordered_by_priority_desc(self): 
    4242        query = Query(self.env, desc=1) # priority is default order 
     
    4444        self.assertEqual(sql, 
    4545"""SELECT id,summary,status,owner,priority,milestone,component 
    4646FROM ticket 
    47   LEFT OUTER JOIN (SELECT name AS priority_name, value AS priority_value FROM enum WHERE type='priority') ON priority_name=priority 
    48 ORDER BY IFNULL(priority,'')='' DESC,priority_value DESC,id""") 
     47  LEFT OUTER JOIN (SELECT name AS priority_name, value AS priority_value FROM enum WHERE type='priority') e ON priority_name=priority 
     48ORDER BY COALESCE(priority,'')='' DESC,priority_value DESC,id""") 
    4949 
    5050    def test_all_ordered_by_version(self): 
    5151        query = Query(self.env, order='version') 
     
    5353        self.assertEqual(sql, 
    5454"""SELECT id,summary,status,owner,priority,milestone,version 
    5555FROM ticket 
    56   LEFT OUTER JOIN (SELECT name AS version_name, time AS version_time FROM version) ON version_name=version 
    57 ORDER BY IFNULL(version,'')='',IFNULL(version_time,0)=0,version_time,version,id""") 
     56  LEFT OUTER JOIN (SELECT name AS version_name, time AS version_time FROM version) a ON version_name=version 
     57ORDER BY COALESCE(version,'')='',COALESCE(version_time,0)=0,version_time,version,id""") 
    5858 
    5959    def test_all_ordered_by_version_desc(self): 
    6060        query = Query(self.env, order='version', desc=1) 
     
    6262        self.assertEqual(sql, 
    6363"""SELECT id,summary,status,owner,priority,milestone,version 
    6464FROM ticket 
    65   LEFT OUTER JOIN (SELECT name AS version_name, time AS version_time FROM version) ON version_name=version 
    66 ORDER BY IFNULL(version,'')='' DESC,IFNULL(version_time,0)=0 DESC,version_time DESC,version DESC,id""") 
     65  LEFT OUTER JOIN (SELECT name AS version_name, time AS version_time FROM version) a ON version_name=version 
     66ORDER BY COALESCE(version,'')='' DESC,COALESCE(version_time,0)=0 DESC,version_time DESC,version DESC,id""") 
    6767 
    6868    def test_constrained_by_milestone(self): 
    6969        query = Query(self.env, order='id') 
     
    7272        self.assertEqual(sql, 
    7373"""SELECT id,summary,status,owner,priority,component,version,milestone 
    7474FROM ticket 
    75 WHERE IFNULL(milestone,'')='milestone1' 
    76 ORDER BY IFNULL(id,'')='',id""") 
     75WHERE COALESCE(milestone,'')='milestone1' 
     76ORDER BY COALESCE(id,0)=0,id""") 
    7777 
    7878    def test_all_grouped_by_milestone(self): 
    7979        query = Query(self.env, order='id', group='milestone') 
     
    8181        self.assertEqual(sql, 
    8282"""SELECT id,summary,status,owner,priority,component,version,milestone 
    8383FROM ticket 
    84   LEFT OUTER JOIN (SELECT name AS milestone_name, due AS milestone_time FROM milestone) ON milestone_name=milestone 
    85 ORDER BY IFNULL(milestone,'')='',IFNULL(milestone_time,0)=0,milestone_time,milestone,IFNULL(id,'')='',id""") 
     84  LEFT OUTER JOIN (SELECT name AS milestone_name, due AS milestone_time FROM milestone) a ON milestone_name=milestone 
     85ORDER BY COALESCE(milestone,'')='',COALESCE(milestone_time,0)=0,milestone_time,milestone,COALESCE(id,0)=0,id""") 
    8686 
    8787    def test_all_grouped_by_milestone_desc(self): 
    8888        query = Query(self.env, order='id', group='milestone', groupdesc=1) 
     
    9090        self.assertEqual(sql, 
    9191"""SELECT id,summary,status,owner,priority,component,version,milestone 
    9292FROM ticket 
    93   LEFT OUTER JOIN (SELECT name AS milestone_name, due AS milestone_time FROM milestone) ON milestone_name=milestone 
    94 ORDER BY IFNULL(milestone,'')='' DESC,IFNULL(milestone_time,0)=0 DESC,milestone_time DESC,milestone DESC,IFNULL(id,'')='',id""") 
     93  LEFT OUTER JOIN (SELECT name AS milestone_name, due AS milestone_time FROM milestone) a ON milestone_name=milestone 
     94ORDER BY COALESCE(milestone,'')='' DESC,COALESCE(milestone_time,0)=0 DESC,milestone_time DESC,milestone DESC,COALESCE(id,0)=0,id""") 
    9595 
    9696    def test_grouped_by_priority(self): 
    9797        query = Query(self.env, group='priority') 
     
    9999        self.assertEqual(sql, 
    100100"""SELECT id,summary,status,owner,milestone,component,version,priority 
    101101FROM ticket 
    102   LEFT OUTER JOIN (SELECT name AS priority_name, value AS priority_value FROM enum WHERE type='priority') ON priority_name=priority 
    103 ORDER BY IFNULL(priority,'')='',priority_value,id""") 
     102  LEFT OUTER JOIN (SELECT name AS priority_name, value AS priority_value FROM enum WHERE type='priority') e ON priority_name=priority 
     103ORDER BY COALESCE(priority,'')='',priority_value,id""") 
    104104 
    105105    def test_constrained_by_milestone_not(self): 
    106106        query = Query(self.env, order='id') 
     
    109109        self.assertEqual(sql, 
    110110"""SELECT id,summary,milestone,status,owner,priority,component 
    111111FROM ticket 
    112 WHERE IFNULL(milestone,'')!='milestone1' 
    113 ORDER BY IFNULL(id,'')='',id""") 
     112WHERE COALESCE(milestone,'')!='milestone1' 
     113ORDER BY COALESCE(id,0)=0,id""") 
    114114 
    115115    def test_constrained_by_status(self): 
    116116        query = Query(self.env, order='id') 
     
    119119        self.assertEqual(sql, 
    120120"""SELECT id,summary,status,owner,priority,milestone,component 
    121121FROM ticket 
    122 WHERE IFNULL(status,'') IN ('new','assigned','reopened') 
    123 ORDER BY IFNULL(id,'')='',id""") 
     122WHERE COALESCE(status,'') IN ('new','assigned','reopened') 
     123ORDER BY COALESCE(id,0)=0,id""") 
    124124 
    125125    def test_constrained_by_owner_containing(self): 
    126126        query = Query(self.env, order='id') 
     
    129129        self.assertEqual(sql, 
    130130"""SELECT id,summary,owner,status,priority,milestone,component 
    131131FROM ticket 
    132 WHERE IFNULL(owner,'') LIKE '%someone%' 
    133 ORDER BY IFNULL(id,'')='',id""") 
     132WHERE COALESCE(owner,'') LIKE '%someone%' 
     133ORDER BY COALESCE(id,0)=0,id""") 
    134134 
    135135    def test_constrained_by_owner_not_containing(self): 
    136136        query = Query(self.env, order='id') 
     
    139139        self.assertEqual(sql, 
    140140"""SELECT id,summary,owner,status,priority,milestone,component 
    141141FROM ticket 
    142 WHERE IFNULL(owner,'') NOT LIKE '%someone%' 
    143 ORDER BY IFNULL(id,'')='',id""") 
     142WHERE COALESCE(owner,'') NOT LIKE '%someone%' 
     143ORDER BY COALESCE(id,0)=0,id""") 
    144144 
    145145    def test_constrained_by_owner_beginswith(self): 
    146146        query = Query(self.env, order='id') 
     
    149149        self.assertEqual(sql, 
    150150"""SELECT id,summary,owner,status,priority,milestone,component 
    151151FROM ticket 
    152 WHERE IFNULL(owner,'') LIKE 'someone%' 
    153 ORDER BY IFNULL(id,'')='',id""") 
     152WHERE COALESCE(owner,'') LIKE 'someone%' 
     153ORDER BY COALESCE(id,0)=0,id""") 
    154154 
    155155    def test_constrained_by_owner_endswith(self): 
    156156        query = Query(self.env, order='id') 
     
    159159        self.assertEqual(sql, 
    160160"""SELECT id,summary,owner,status,priority,milestone,component 
    161161FROM ticket 
    162 WHERE IFNULL(owner,'') LIKE '%someone' 
    163 ORDER BY IFNULL(id,'')='',id""") 
     162WHERE COALESCE(owner,'') LIKE '%someone' 
     163ORDER BY COALESCE(id,0)=0,id""") 
    164164 
    165165    def test_constrained_by_custom_field(self): 
    166166        self.env.set_config('ticket-custom', 'foo', 'text') 
     
    170170        self.assertEqual(sql, 
    171171"""SELECT id,summary,status,owner,priority,milestone,component, foo.value AS foo 
    172172FROM ticket 
    173   LEFT OUTER JOIN ticket_custom AS foo ON (id=foo.ticket AND foo.name='foo') 
    174 WHERE IFNULL(foo,'')='something' 
    175 ORDER BY IFNULL(id,'')='',id""") 
     173  LEFT OUTER JOIN ticket_custom AS foo ON (id=foo.ticket AND foo.name='foo') tc 
     174WHERE COALESCE(foo,'')='something' 
     175ORDER BY COALESCE(id,0)=0,id""") 
    176176 
    177177    def test_constrained_by_multiple_owners(self): 
    178178        query = Query(self.env, order='id') 
     
    181181        self.assertEqual(sql, 
    182182"""SELECT id,summary,owner,status,priority,milestone,component 
    183183FROM ticket 
    184 WHERE IFNULL(owner,'') IN ('someone','someone_else') 
    185 ORDER BY IFNULL(id,'')='',id""") 
     184WHERE COALESCE(owner,'') IN ('someone','someone_else') 
     185ORDER BY COALESCE(id,0)=0,id""") 
    186186 
    187187    def test_constrained_by_multiple_owners_not(self): 
    188188        query = Query(self.env, order='id') 
     
    191191        self.assertEqual(sql, 
    192192"""SELECT id,summary,owner,status,priority,milestone,component 
    193193FROM ticket 
    194 WHERE IFNULL(owner,'') NOT IN ('someone','someone_else') 
    195 ORDER BY IFNULL(id,'')='',id""") 
     194WHERE COALESCE(owner,'') NOT IN ('someone','someone_else') 
     195ORDER BY COALESCE(id,0)=0,id""") 
    196196 
    197197    def test_constrained_by_multiple_owners_contain(self): 
    198198        query = Query(self.env, order='id') 
     
    201201        self.assertEqual(sql, 
    202202"""SELECT id,summary,owner,status,priority,milestone,component 
    203203FROM ticket 
    204 WHERE (IFNULL(owner,'') LIKE '%someone%' OR IFNULL(owner,'') LIKE '%someone_else%') 
    205 ORDER BY IFNULL(id,'')='',id""") 
     204WHERE (COALESCE(owner,'') LIKE '%someone%' OR COALESCE(owner,'') LIKE '%someone_else%') 
     205ORDER BY COALESCE(id,0)=0,id""") 
    206206 
    207207def suite(): 
    208208    return unittest.makeSuite(QueryTestCase, 'test') 
  • trac/sync.py

    old new  
    3535              (util.SVN_VER_MAJOR, util.SVN_VER_MINOR, util.SVN_VER_MICRO) 
    3636 
    3737    cursor = db.cursor() 
    38     cursor.execute('SELECT ifnull(max(rev), 0) FROM revision') 
     38    cursor.execute('SELECT COALESCE(max(rev), 0) FROM revision') 
    3939    youngest_stored =  int(cursor.fetchone()[0]) 
    4040    max_rev = fs.youngest_rev(fs_ptr, pool) 
    4141    num = max_rev - youngest_stored 
  • trac/Roadmap.py

    old new  
    4444        if show == 'all': 
    4545            icalhref += '&show=all' 
    4646            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" 
    4949        else: 
    5050            self.req.hdf.setValue('roadmap.showall', '1') 
    5151            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" 
    5555 
    5656        if self.req.authname and self.req.authname != 'anonymous': 
    5757            icalhref += '&user=' + self.req.authname 
     
    176176                if ticket['status'] == 'closed': 
    177177                    cursor = self.db.cursor() 
    178178                    cursor.execute("SELECT time FROM ticket_change " 
    179                                    "WHERE ticket = %i AND field = 'status' " 
     179                                   "WHERE ticket = %s AND field = 'status' " 
    180180                                   "ORDER BY time desc LIMIT 1", ticket['id']) 
    181181                    row = cursor.fetchone() 
    182182                    if row: write_utctime('COMPLETED', localtime(row['time'])) 
  • trac/Session.py

    old new  
    103103    def get_session(self, sid): 
    104104        self.sid = sid 
    105105        curs = self.db.cursor() 
    106         curs.execute("SELECT username,var_name,var_value FROM session" 
    107                     " WHERE sid=%s", self.sid
     106        curs.execute("SELECT username,var_name,var_value FROM session"  
     107                    " WHERE sid=%s", (self.sid,)
    108108        rows = curs.fetchall() 
    109109        if (not rows                              # No session data yet 
    110110            or rows[0][0] == 'anonymous'          # Anon session 
     
    138138                self.purge_expired()  
    139139            curs.execute('INSERT INTO session(sid,username,var_name,var_value)' 
    140140                         ' VALUES(%s,%s,%s,%s)', 
    141                          self.sid, self.req.authname, key, val
     141                         (self.sid, self.req.authname, key, val,)
    142142        else: 
    143143            curs.execute('UPDATE session SET username=%s,var_value=%s' 
    144144                         ' WHERE sid=%s AND var_name=%s', 
    145                          self.req.authname, val, self.sid, key
     145                         (self.req.authname, val, self.sid, key,)
    146146        self.db.commit() 
    147147        self.vars[key] = val 
    148148 
     
    172172        curs = self.db.cursor() 
    173173        curs.execute("DELETE FROM session WHERE sid IN" 
    174174                     " (SELECT sid FROM session WHERE var_name='mod_time'" 
    175                      "  AND var_value  < %i)", mintime) 
     175                     "  AND var_value  < %s)", mintime) 
    176176        self.db.commit() 
    177177 
  • trac/Changeset.py

    old new  
    296296    def get_changeset_info (self, rev): 
    297297        cursor = self.db.cursor () 
    298298        cursor.execute ('SELECT time, author, message FROM revision ' + 
    299                         'WHERE rev=%d', rev
     299                        'WHERE rev=%s', (rev,)
    300300        row = cursor.fetchone() 
    301301        if not row: 
    302302            raise util.TracError('Changeset %d does not exist.' % rev, 
     
    306306    def get_change_info(self, rev): 
    307307        cursor = self.db.cursor () 
    308308        cursor.execute ('SELECT name, change FROM node_change ' + 
    309                         'WHERE rev=%d', rev
     309                        'WHERE rev=%s', (rev,)
    310310        info = [] 
    311311        while 1: 
    312312            row = cursor.fetchone() 
  • trac/auth.py

    old new  
    3232            cookie = req.incookie['trac_auth'].value 
    3333            cursor.execute ("SELECT name FROM auth_cookie " 
    3434                            "WHERE cookie=%s AND ipnr=%s" 
    35                             ,cookie, req.remote_addr) 
    36             if cursor.rowcount >= 1: 
    37                 self.authname = cursor.fetchone()[0] 
     35                            , (cookie, req.remote_addr,)) 
     36            row = cursor.fetchone() 
     37            if row: 
     38               self.authname = row[0] 
    3839 
    3940    def login(self, req): 
    4041        cursor = self.db.cursor () 
    4142        cookie = util.hex_entropy() 
    4243        cursor.execute ("INSERT INTO auth_cookie (cookie, name, ipnr, time)" + 
    43                         "VALUES (%s, %s, %s, %d)", 
    44                         cookie, req.remote_user, req.remote_addr, 
    45                         int(time.time())); 
     44                        "VALUES (%s, %s, %s, %s)", 
     45                        (cookie, req.remote_user, req.remote_addr, 
     46                        int(time.time()),)); 
    4647        self.db.commit () 
    4748        self.authname = req.remote_user 
    4849        req.outcookie['trac_auth'] = cookie 
     
    5152    def logout(self): 
    5253        cursor = self.db.cursor () 
    5354        cursor.execute ("DELETE FROM auth_cookie WHERE name=%s", 
    54                         self.authname
     55                        (self.authname,)
    5556        self.db.commit () 
  • trac/Wiki.py

    old new  
    5959        if version: 
    6060            cursor.execute ('SELECT version, text, readonly FROM wiki ' 
    6161                            'WHERE name=%s AND version=%s', 
    62                             name, version
     62                            (name, version,)
    6363        else: 
    6464            cursor.execute ('SELECT version, text, readonly FROM wiki ' 
    65                             'WHERE name=%s ORDER BY version DESC LIMIT 1', name) 
     65                            'WHERE name=%s ORDER BY version DESC LIMIT 1',  
     66                            (name,)) 
    6667        row = cursor.fetchone() 
    6768        if row: 
    6869            self.new = 0 
  • trac/Environment.py

    old new  
    3535import Mimeview 
    3636import unicodedata 
    3737 
    38 import sqlite 
     38from types import * 
    3939 
    4040db_version = db_default.db_version 
    4141 
     
    4646    A Trac environment consists of a directory structure containing 
    4747    among other things: 
    4848     * a configuration file. 
    49      * a sqlite database (stores tickets, wiki pages...) 
     49     * a database (stores tickets, wiki pages...) 
    5050     * Project specific templates and wiki macros. 
    5151     * wiki and ticket attachments. 
    5252    """ 
    53     def __init__(self, path, create=0): 
     53    def __init__(self, path, create=0, db_str=None): 
    5454        self.path = path 
    5555        if create: 
    56             self.create(
     56            self.create(db_str
    5757        self.verify() 
    5858        self.load_config() 
    5959        try: # Use binary I/O on Windows 
     
    6464            pass 
    6565        self.setup_log() 
    6666        self.setup_mimeviewer() 
     67        self.dbms = self.get_dbms() 
    6768 
    6869    def verify(self): 
    6970        """Verifies that self.path is a compatible trac environment""" 
     
    7172        assert fd.read(26) == 'Trac Environment Version 1' 
    7273        fd.close() 
    7374 
    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 
    8084         
    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 
    89126 
    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): 
    91160        def _create_file(fname, data=None): 
    92161            fd = open(fname, 'w') 
    93162            if data: fd.write(data) 
     
    128197""") 
    129198        # Create default database 
    130199        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) 
    132206        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) 
    134220        cnx.commit() 
    135221 
    136222    def insert_default_data(self): 
     
    138224            if v == None: 
    139225                return 'NULL' 
    140226            else: 
    141                 return '"%s"' % v 
     227                prepped = v 
     228                if type(v) is StringType: 
     229                    prepped = prepped.replace("'", "''") 
     230                return "'%s'" % prepped 
    142231        cnx = self.get_db_cnx() 
    143232        cursor = cnx.cursor() 
    144233         
     
    149238                values = ','.join(map(prep_value, row)) 
    150239                sql = "INSERT INTO %s (%s) VALUES(%s);" % (table, cols, values) 
    151240                cursor.execute(sql) 
     241        cnx.commit() 
     242 
     243    def setup_default_config(self): 
    152244        for s,n,v in db_default.default_config: 
    153245            if not self.cfg.has_section(s): 
    154246                self.cfg.add_section(s) 
    155247            self.cfg.set(s, n, v) 
    156         self.save_config() 
    157         cnx.commit() 
    158248 
    159249    def get_version(self): 
    160250        cnx = self.get_db_cnx() 
     
    218308        cursor = cnx.cursor() 
    219309        cursor.execute('SELECT filename,description,type,size,time,author,ipnr ' 
    220310                       'FROM attachment ' 
    221                        'WHERE type=%s AND id=%s ORDER BY time', type, id
     311                       'WHERE type=%s AND id=%s ORDER BY time', (type, id,)
    222312        return cursor.fetchall() 
    223313     
    224314    def get_attachments_hdf(self, cnx, type, id, hdf, prefix): 
     
    290380 
    291381    def backup(self, dest=None): 
    292382        """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') 
    294385        if db_str[:7] != 'sqlite:': 
    295             raise EnvironmentError, 'Can only backup sqlite databases' 
     386            print 'BACKUP FAILED: Can only backup sqlite databases.' 
     387            # TODO: should probably ask if they want to continue 
     388            #       or at least handle this better by shelling out to backup 
     389            #       other dbs like pgsql... 
     390            return 
    296391        db_name = os.path.join(self.path, db_str[7:]) 
    297392        if not dest: 
    298393            dest = '%s.%i.bak' % (db_name, self.get_version()) 
     
    321416                    err = 'No upgrade module for version %i (%s.py)' % (i, upg) 
    322417                    raise EnvironmentError, err 
    323418                d.do_upgrade(self, i, cursor) 
    324             cursor.execute("UPDATE system SET value=%i WHERE " 
     419            cursor.execute("UPDATE system SET value=%s WHERE " 
    325420                           "name='database_version'", db_default.db_version) 
    326421            self.log.info('Upgraded db version from %d to %d', 
    327422                          dbver, db_default.db_version) 
    328423            cnx.commit() 
     424            print 'Upgrade succeeded.' 
    329425            return 1 
  • trac/Ticket.py

    old new  
    7373            self[Ticket.std_fields[i]] = row[i] or '' 
    7474 
    7575        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) 
    7777        rows = cursor.fetchall() 
    7878        if rows: 
    7979            for r in rows: 
     
    9393            if not dict.has_key(name): 
    9494                self[name] = '0' 
    9595 
    96     def insert(self, db): 
     96    def insert(self, db, dbms): 
    9797        """Add ticket to database""" 
    9898        cursor = db.cursor() 
    9999        assert not self.has_key('id') 
     
    106106        std_fields = filter(lambda n: n[:7] != 'custom_', self.keys()) 
    107107        custom_fields = filter(lambda n: n[:7] == 'custom_', self.keys()) 
    108108        std_values = map(lambda n, self=self: self[n], std_fields) 
     109         
    109110        nstr = string.join(std_fields, ',') 
    110111        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), 
    112113                       *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             
    114122        for name in custom_fields: 
    115123            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]) 
    117125        db.commit() 
    118126        self['id'] = id 
    119127        self._forget_changes() 
     
    146154        for name in self._old.keys(): 
    147155            if name[:7] == 'custom_': 
    148156                fname = name[7:] 
    149                 cursor.execute('REPLACE INTO ticket_custom(ticket,name,value)' 
     157                # some dbms's don't support REPLACE INTO, so we have to do  
     158                # this detection and delete 
     159                cursor.execute("SELECT * FROM ticket_custom "  
     160                               "WHERE ticket=%s and name=%s"  
     161                               , id, fname) 
     162                if cursor.fetchone() is not None: 
     163                    cursor.execute("DELETE FROM ticket_custom "  
     164                                   "WHERE ticket=%s and name=%s"  
     165                                   , id, fname) 
     166                cursor.execute('INSERT INTO ticket_custom(ticket,name,value)' 
    150167                               ' VALUES(%s, %s, %s)', id, fname, self[name]) 
    151168            else: 
    152169                fname = name 
    153                 cursor.execute ('UPDATE ticket SET %s=%s WHERE id=%s', 
    154                                 fname, self[name], id) 
     170                sql = "UPDATE ticket SET %s='%s' WHERE id=%s" \ 
     171                      % (fname, self[name], id) 
    155172 
     173                cursor.execute (sql) 
     174 
    156175            cursor.execute ('INSERT INTO ticket_change ' 
    157176                            '(ticket, time, author, field, oldvalue, newvalue) ' 
    158177                            'VALUES (%s, %s, %s, %s, %s, %s)', 
     
    171190        """Returns the changelog as a list of dictionaries""" 
    172191        cursor = db.cursor() 
    173192        if when: 
    174             cursor.execute('SELECT time, author, field, oldvalue, newvalue ' 
    175                            'FROM ticket_change ' 
    176                            'WHERE ticket=%s AND time=%s' 
    177                            'UNION ' 
    178                            'SELECT time, author, "attachment", null, filename ' 
    179                            'FROM attachment ' 
    180                            'WHERE id=%s AND time=%s ' 
    181                            'ORDER BY time',  self['id'], when, self['id'], when) 
     193            cursor.execute("SELECT time, author, field, oldvalue, newvalue " 
     194                           "FROM ticket_change " 
     195                           "WHERE ticket=%s AND time=%s" 
     196                           "UNION " 
     197                           "SELECT time, author, 'attachment', null, filename " 
     198                           "FROM attachment " 
     199                           "WHERE id=%s AND time=%s " 
     200                           "ORDER BY time",  self['id'], when, self['id'], when) 
    182201        else: 
    183             cursor.execute('SELECT time, author, field, oldvalue, newvalue ' 
    184                            'FROM ticket_change ' 
    185                            'WHERE ticket=%s ' 
    186                            'UNION ' 
    187                            'SELECT time, author, "attachment", null,filename ' 
    188                            'FROM attachment ' 
    189                            'WHERE id = %s ' 
    190                            'ORDER BY time', self['id'],  self['id']) 
     202            cursor.execute("SELECT time, author, field, oldvalue, newvalue " 
     203                           "FROM ticket_change " 
     204                           "WHERE ticket=%s " 
     205                           "UNION " 
     206                           "SELECT time, author, 'attachment', null,filename " 
     207                           "FROM attachment " 
     208                           "WHERE id = %s " 
     209                           "ORDER BY time", self['id'],  self['id']) 
    191210        log = [] 
    192211        while 1: 
    193212            row = cursor.fetchone() 
     
    283302            owner = cursor.fetchone()[0] 
    284303            ticket['owner'] = owner 
    285304 
    286         tktid = ticket.insert(self.db) 
     305        dbms = self.env.get_dbms() 
     306        tktid = ticket.insert(self.db, dbms) 
    287307 
    288308        # Notify 
    289309        tn = TicketNotifyEmail(self.env) 
  • trac/WikiFormatter.py

    old new  
    130130    def _changesethref_formatter(self, match, fullmatch): 
    131131        number = int(match[1:-1]) 
    132132        cursor = self.db.cursor () 
    133         cursor.execute('SELECT message FROM revision WHERE rev=%d', number) 
     133        cursor.execute('SELECT message FROM revision WHERE rev=%s', number) 
    134134        row = cursor.fetchone () 
    135135        if not row: 
    136136            return '[<a class="missing" href="%s">%d</a>]' % (self._href.changeset(number), number) 
  • contrib/tracdb-sqlite2pg.py

    old new  
     1#!/usr/bin/env python 
     2 
     3""" 
     4Import a Trac database from sqlite to postgresql. 
     5 
     6Requires:  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            
     12Author: Brad Anderson <brad@dsource.org> 
     13 
     14 
     15""" 
     16 
     17import sys, os 
     18import sqlite 
     19import pgdb 
     20from trac.util import sql_escape 
     21 
     22tables=['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 
     42def 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     
     115def 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 
     148def 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 
     184if __name__ == '__main__': 
     185    main()