PostgresqlPatch: pgsql_patch_01.diff

File pgsql_patch_01.diff, 61.2 kB (added by brad, 7 years ago)
  • trac/core.py

    old new  
    11# -*- coding: iso8859-1 -*- 
    22# 
    33# Copyright (C) 2003, 2004 Edgewall Software 
    4 # Copyright (C) 2003, 2004 Jonas Borgström <jonas@edgewall.com> 
     4# Copyright (C) 2003, 2004 Jonas Borgstr?m <jonas@edgewall.com> 
    55# 
    66# Trac is free software; you can redistribute it and/or 
    77# modify it under the terms of the GNU General Public License as 
     
    1717# along with this program; if not, write to the Free Software 
    1818# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
    1919# 
    20 # Author: Jonas Borgström <jonas@edgewall.com> 
     20# Author: Jonas Borgstr?m <jonas@edgewall.com> 
    2121 
    2222import os 
    2323import re 
  • trac/db_default.py

    old new  
    414414 (('trac', 'htdocs_location', '/trac/'), 
    415415  ('trac', 'repository_dir', '/var/svn/myrep'), 
    416416  ('trac', 'templates_dir', '/usr/lib/trac/templates'), 
    417   ('trac', 'database', 'sqlite:db/trac.db'), 
     417  ('trac', 'database', 'sqlite:"db/trac.db",timeout=10000'), 
    418418  ('trac', 'default_charset', 'iso-8859-15'), 
    419419  ('logging', 'log_type', 'none'), 
    420420  ('logging', 'log_file', 'trac.log'), 
  • trac/Milestone.py

    old new  
    200200        groups = [] 
    201201        if by in ['status', 'resolution', 'severity', 'priority']: 
    202202            cursor.execute("SELECT name FROM enum WHERE type = %s " 
    203                            "AND IFNULL(name,'') != '' ORDER BY value", by) 
     203                           "AND COALESCE(name,'') != '' ORDER BY value", by) 
    204204        elif by in ['component', 'milestone', 'version']: 
    205205            cursor.execute("SELECT name FROM %s " 
    206                            "WHERE IFNULL(name,'') != '' ORDER BY name" % by) 
     206                           "WHERE COALESCE(name,'') != '' ORDER BY name" % by) 
    207207        elif by == 'owner': 
    208208            cursor.execute("SELECT DISTINCT owner AS name FROM ticket " 
    209209                           "ORDER BY owner") 
  • trac/Query.py

    old new  
    11# -*- coding: iso8859-1 -*- 
    22# 
    33# Copyright (C) 2003, 2004 Edgewall Software 
    4 # Copyright (C) 2003, 2004 Jonas Borgström <jonas@edgewall.com> 
     4# Copyright (C) 2003, 2004 Jonas Borgstr?m <jonas@edgewall.com> 
    55# 
    66# Trac is free software; you can redistribute it and/or 
    77# modify it under the terms of the GNU General Public License as 
     
    1717# along with this program; if not, write to the Free Software 
    1818# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
    1919# 
    20 # Author: Jonas Borgström <jonas@edgewall.com> 
     20# Author: Jonas Borgstr?m <jonas@edgewall.com> 
    2121 
    2222from __future__ import nested_scopes 
    2323from time import gmtime, localtime, strftime 
     
    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') subq" % (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') subq" \ 
    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            sql.append("\n  LEFT OUTER JOIN (SELECT name AS %s_name, " \ 
    168                                             "time AS %s_time FROM %s)" \ 
     168                                            "time AS %s_time FROM %s) subq" \ 
    169169                       " ON %s_name=%s" % (col, col, col, col, col)) 
    170170 
    171171        def get_constraint_sql(name, value, mode, neg): 
    172172            value = sql_escape(value[len(mode and '!' or '' + mode):]) 
    173173            if mode == '~' and value: 
    174                 return "IFNULL(%s,'') %sLIKE '%%%s%%'" % ( 
     174                return "COALESCE(%s,'') %sLIKE '%%%s%%'" % ( 
    175175                       name, neg and 'NOT ' or '', value) 
    176176            elif mode == '^' and value: 
    177                 return "IFNULL(%s,'') %sLIKE '%s%%'" % ( 
     177                return "COALESCE(%s,'') %sLIKE '%s%%'" % ( 
    178178                       name, neg and 'NOT ' or '', value) 
    179179            elif mode == '$' and value: 
    180                 return "IFNULL(%s,'') %sLIKE '%%%s'" % ( 
     180                return "COALESCE(%s,'') %sLIKE '%%%s'" % ( 
    181181                       name, neg and 'NOT ' or '', value) 
    182182            elif mode == '': 
    183                 return "IFNULL(%s,'')%s='%s'" % (name, neg and '!' or '', value) 
     183                return "COALESCE(%s,'')%s='%s'" % (name, neg and '!' or '', value) 
    184184 
    185185        clauses = [] 
    186186        for k, v in self.constraints.items(): 
     
    194194            # Special case for exact matches on multiple values 
    195195            if not mode and len(v) > 1: 
    196196                inlist = ",".join(["'" + sql_escape(val[neg and 1 or 0:]) + "'" for val in v]) 
    197                 clauses.append("IFNULL(%s,'') %sIN (%s)" % (k, neg and "NOT " or "", inlist)) 
     197                clauses.append("COALESCE(%s,'') %sIN (%s)" % (k, neg and "NOT " or "", inlist)) 
    198198            elif len(v) > 1: 
    199199                constraint_sql = [get_constraint_sql(k, val, mode, neg) for val in v] 
    200200                if neg: 
     
    214214            order_cols.insert(0, (self.group, self.groupdesc)) 
    215215        for col, desc in order_cols: 
    216216            if desc: 
    217                 sql.append("IFNULL(%s,'')='' DESC," % col) 
     217                sql.append("COALESCE(%s,'')='' DESC," % col) 
    218218            else: 
    219                 sql.append("IFNULL(%s,'')=''," % col) 
     219                sql.append("COALESCE(%s,'')=''," % col) 
    220220            if col in ['status', 'resolution', 'priority', 'severity']: 
    221221                if desc: 
    222222                    sql.append("%s_value DESC" % col) 
     
    224224                    sql.append("%s_value" % col) 
    225225            elif col in ['milestone', 'version']: 
    226226                if desc: 
    227                     sql.append("IFNULL(%s_time,0)=0 DESC,%s_time DESC,%s DESC" 
     227                    sql.append("COALESCE(%s_time,0)=0 DESC,%s_time DESC,%s DESC" 
    228228                               % (col, col, col)) 
    229229                else: 
    230                     sql.append("IFNULL(%s_time,0)=0,%s_time,%s" 
     230                    sql.append("COALESCE(%s_time,0)=0,%s_time,%s" 
    231231                               % (col, col, col)) 
    232232            else: 
    233233                if desc: 
  • trac/Timeline.py

    old new  
    11# -*- coding: iso8859-1 -*- 
    22# 
    33# Copyright (C) 2003, 2004 Edgewall Software 
    4 # Copyright (C) 2003, 2004 Jonas Borgström <jonas@edgewall.com> 
     4# Copyright (C) 2003, 2004 Jonas Borgstr?m <jonas@edgewall.com> 
    55# 
    66# Trac is free software; you can redistribute it and/or 
    77# modify it under the terms of the GNU General Public License as 
     
    1717# along with this program; if not, write to the Free Software 
    1818# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
    1919# 
    20 # Author: Jonas Borgström <jonas@edgewall.com> 
     20# Author: Jonas Borgstr?m <jonas@edgewall.com> 
    2121 
    2222import time 
    2323import string 
  • trac/Report.py

    old new  
    11# -*- coding: iso8859-1 -*- 
    22# 
    33# Copyright (C) 2003, 2004 Edgewall Software 
    4 # Copyright (C) 2003, 2004 Jonas Borgström <jonas@edgewall.com> 
     4# Copyright (C) 2003, 2004 Jonas Borgstr?m <jonas@edgewall.com> 
    55# 
    66# Trac is free software; you can redistribute it and/or 
    77# modify it under the terms of the GNU General Public License as 
     
    1717# along with this program; if not, write to the Free Software 
    1818# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
    1919# 
    20 # Author: Jonas Borgström <jonas@edgewall.com> 
     20# Author: Jonas Borgstr?m <jonas@edgewall.com> 
    2121 
    2222import os 
    2323import re 
     
    9595            sql = 'SELECT id AS report, title FROM report ORDER BY report' 
    9696            description = 'This is a list of reports available.' 
    9797        else: 
    98             cursor.execute('SELECT title, sql, description from report ' 
    99                            ' WHERE id=%s', id) 
     98            sql = "SELECT title, sql, description from report " \ 
     99                  "WHERE id=%s" % id 
     100            cursor.execute(sql) 
    100101            row = cursor.fetchone() 
    101102            if not row: 
    102103                raise util.TracError('Report %d does not exist.' % id, 
     
    133134        sql = self.sql_sub_vars(sql, args) 
    134135        if not sql: 
    135136            raise util.TracError('Report %s has no SQL query.' % id) 
     137        self.env.log.debug("sql: %s" % sql) 
    136138        cursor.execute(sql) 
    137139 
    138140        if sql.find('__group__') == -1: 
     
    140142 
    141143        # FIXME: fetchall should probably not be used. 
    142144        info = cursor.fetchall() 
    143         cols = cursor.rs.col_defs 
     145        cols = cursor.description 
     146         
    144147        # Escape the values so that they are safe to have as html parameters 
    145148        #info = map(lambda row: map(lambda x: escape(x), row), info) 
    146149 
  • trac/sync.py

    old new  
    11# -*- coding: iso8859-1 -*- 
    22# 
    33# Copyright (C) 2003, 2004 Edgewall Software 
    4 # Copyright (C) 2003, 2004 Jonas Borgström <jonas@edgewall.com> 
     4# Copyright (C) 2003, 2004 Jonas Borgstr?m <jonas@edgewall.com> 
    55# 
    66# Trac is free software; you can redistribute it and/or 
    77# modify it under the terms of the GNU General Public License as 
     
    1717# along with this program; if not, write to the Free Software 
    1818# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
    1919# 
    20 # Author: Jonas Borgström <jonas@edgewall.com> 
     20# Author: Jonas Borgstr?m <jonas@edgewall.com> 
    2121 
    2222from svn import fs, util, delta, repos, core 
     23from util import sql_escape 
    2324 
    2425import posixpath 
    2526 
     
    3536              (util.SVN_VER_MAJOR, util.SVN_VER_MINOR, util.SVN_VER_MICRO) 
    3637 
    3738    cursor = db.cursor() 
    38     cursor.execute('SELECT ifnull(max(rev), 0) FROM revision') 
    39     youngest_stored =  int(cursor.fetchone()[0]) 
     39    cursor.execute('SELECT max(rev) FROM revision') 
     40    row = cursor.fetchone() 
     41    youngest_stored = 0 
     42    if row and row[0] != None: 
     43        youngest_stored =  int(row[0]) 
     44     
    4045    max_rev = fs.youngest_rev(fs_ptr, pool) 
    4146    num = max_rev - youngest_stored 
    4247    offset = youngest_stored + 1 
     
    5257 
    5358        date = util.svn_time_from_cstring(date, subpool) / 1000000 
    5459         
    55         cursor.execute ('INSERT INTO revision (rev, time, author, message) ' 
    56                         'VALUES (%s, %s, %s, %s)', rev + offset, date, 
    57                         author, message) 
     60        sql = "INSERT INTO revision (rev, time, author, message) " \ 
     61              "VALUES (%s, %s, '%s', '%s')" \ 
     62              % ( rev + offset, date, sql_escape(author), sql_escape(message) ) 
     63        cursor.execute (sql) 
    5864        insert_change (subpool, fs_ptr, rev + offset, cursor) 
    5965        core.svn_pool_clear(subpool) 
    6066 
  • trac/Session.py

    old new  
    2121 
    2222import sys 
    2323import time 
    24 from util import hex_entropy, add_dict_to_hdf, TracError 
     24from util import hex_entropy, add_dict_to_hdf, TracError, sql_escape 
    2525 
    2626class Session: 
    2727    """Basic session handling and per-session storage.""" 
     
    104104        self.sid = sid 
    105105        curs = self.db.cursor() 
    106106        curs.execute("SELECT username,var_name,var_value FROM session" 
    107                     " WHERE sid=%s", self.sid) 
     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 
     
    136136        if currval == None: 
    137137            if key == 'last_visit': # Limit the frequency of purging 
    138138                self.purge_expired()  
    139             curs.execute('INSERT INTO session(sid,username,var_name,var_value)' 
    140                          ' VALUES(%s,%s,%s,%s)', 
    141                          self.sid, self.req.authname, key, val) 
     139            sql = "INSERT INTO session(sid,username,var_name,var_value) " \ 
     140                  "VALUES('%s','%s','%s','%s')" \ 
     141                  % ( 
     142                     sql_escape(self.sid), sql_escape(self.req.authname), 
     143                     sql_escape(key), sql_escape(val) 
     144                    ) 
     145            curs.execute(sql) 
    142146        else: 
    143             curs.execute('UPDATE session SET username=%s,var_value=%s' 
    144                          ' WHERE sid=%s AND var_name=%s', 
    145                          self.req.authname, val, self.sid, key) 
     147            sql = "UPDATE session SET username='%s',var_value='%s' " \ 
     148                  "WHERE sid='%s' AND var_name='%s'" \ 
     149                  % (sql_escape(self.req.authname), 
     150                     sql_escape(str(val)), 
     151                     sql_escape(self.sid), 
     152                     sql_escape(key)  
     153                    ) 
     154            curs.execute(sql) 
    146155        self.db.commit() 
    147156        self.vars[key] = val 
    148157 
  • trac/Roadmap.py

    old new  
    5151                                   self.env.href.roadmap()) 
    5252            query = "SELECT name, time, descr FROM milestone " \ 
    5353                    "WHERE name != '' " \ 
    54                     "ORDER BY (IFNULL(time, 0) = 0) ASC, time ASC, name" 
     54                    "ORDER BY (COALESCE(time, 0) = 0) ASC, time ASC, name" 
    5555        else: 
    5656            self.req.hdf.setValue('roadmap.showall', '1') 
    5757            self.req.hdf.setValue('roadmap.href.list', 
     
    5959            query = "SELECT name, time, descr FROM milestone " \ 
    6060                    "WHERE name != '' " \ 
    6161                    "AND (time IS NULL OR time = 0 OR time > %d) " \ 
    62                     "ORDER BY (IFNULL(time, 0) = 0) ASC, time ASC, name" % time() 
     62                    "ORDER BY (COALESCE(time, 0) = 0) ASC, time ASC, name" % time() 
    6363 
    6464        if self.req.authname and self.req.authname != 'anonymous': 
    6565            icalhref += '&user=' + self.req.authname 
  • trac/db_default_pgsql.py

    old new  
     1# -*- coding: iso8859-1 -*- 
     2# 
     3# Copyright (C) 2003, 2004 Edgewall Software 
     4# Copyright (C) 2003, 2004 Daniel Lundin <daniel@edgewall.com> 
     5# 
     6# Trac is free software; you can redistribute it and/or 
     7# modify it under the terms of the GNU General Public License as 
     8# published by the Free Software Foundation; either version 2 of the 
     9# License, or (at your option) any later version. 
     10# 
     11# Trac is distributed in the hope that it will be useful, 
     12# but WITHOUT ANY WARRANTY; without even the implied warranty of 
     13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
     14# General Public License for more details. 
     15# 
     16# You should have received a copy of the GNU General Public License 
     17# along with this program; if not, write to the Free Software 
     18# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
     19# 
     20# Author: Daniel Lundin <daniel@edgewall.com> 
     21 
     22 
     23# Database version identifier. Used for automatic upgrades. 
     24db_version = 7 
     25 
     26def __mkreports(reps): 
     27    """Utility function used to create report data in same syntax as the 
     28    default data. This extra step is done to simplify editing the default 
     29    reports.""" 
     30    result = [] 
     31    i = 1 
     32    for r in reps: 
     33        result.append ((i, None, r[0], r[2], r[1])) 
     34        i = i + 1 
     35    return result 
     36 
     37 
     38## 
     39## Default data 
     40## 
     41 
     42schema = """ 
     43CREATE TABLE revision ( 
     44        rev             integer, 
     45        time            integer, 
     46        author          text, 
     47        message         text, 
     48        CONSTRAINT revision_pkey PRIMARY KEY (rev) 
     49) WITHOUT OIDS; 
     50 
     51CREATE TABLE node_change ( 
     52        rev             integer, 
     53        name            text, 
     54        change          char(1), 
     55        CONSTRAINT node_change_pkey PRIMARY KEY (rev, name, change) 
     56) WITHOUT OIDS; 
     57 
     58CREATE TABLE auth_cookie ( 
     59        cookie          text, 
     60        name            text, 
     61        ipnr            text, 
     62        time            integer, 
     63        CONSTRAINT auth_cookie_pkey PRIMARY KEY(cookie, name, ipnr) 
     64) WITHOUT OIDS; 
     65 
     66CREATE TABLE enum ( 
     67        type            text, 
     68        name            text, 
     69        value           text, 
     70        CONSTRAINT enum_pkey PRIMARY KEY(name,type) 
     71) WITHOUT OIDS; 
     72 
     73CREATE TABLE system ( 
     74        name            text, 
     75        value           text, 
     76        CONSTRAINT system_pkey PRIMARY KEY(name) 
     77) WITHOUT OIDS; 
     78 
     79CREATE TABLE lock ( 
     80        name            text, 
     81        owner           text, 
     82        ipnr            text, 
     83        time            integer, 
     84        CONSTRAINT lock_pkey PRIMARY KEY(name) 
     85) WITHOUT OIDS; 
     86 
     87CREATE TABLE ticket ( 
     88        id              integer, 
     89        time            integer,        -- the time it was created 
     90        changetime      integer, 
     91        component       text, 
     92        severity        text, 
     93        priority        text, 
     94        owner           text,           -- who is this ticket assigned to 
     95        reporter        text, 
     96        cc              text,           -- email addresses to notify 
     97        url             text,           -- url related to this ticket 
     98        version         text,           --  
     99        milestone       text,           --  
     100        status          text, 
     101        resolution      text, 
     102        summary         text,           -- one-line summary 
     103        description     text,           -- problem description (long) 
     104        keywords        text, 
     105        CONSTRAINT ticket_pkey PRIMARY KEY(id) 
     106) WITHOUT OIDS; 
     107 
     108CREATE TABLE ticket_change ( 
     109        ticket          integer, 
     110        time            integer, 
     111        author          text, 
     112        field           text, 
     113        oldvalue        text, 
     114        newvalue        text, 
     115        CONSTRAINT ticket_change_pkey PRIMARY KEY(ticket, time, field) 
     116) WITHOUT OIDS; 
     117 
     118CREATE TABLE ticket_custom ( 
     119       ticket               integer, 
     120       name             text, 
     121       value            text, 
     122       CONSTRAINT ticket_custom_pkey PRIMARY KEY(ticket,name) 
     123) WITHOUT OIDS; 
     124 
     125CREATE TABLE report ( 
     126        id              integer, 
     127        author          text, 
     128        title           text, 
     129        sql             text, 
     130        description     text, 
     131        CONSTRAINT report_pkey PRIMARY KEY(id) 
     132) WITHOUT OIDS; 
     133 
     134CREATE TABLE permission ( 
     135        username        text,           --  
     136        action          text,           -- allowable activity 
     137        CONSTRAINT permission_pkey PRIMARY KEY(username,action) 
     138) WITHOUT OIDS; 
     139 
     140CREATE TABLE component ( 
     141         name            text, 
     142         owner           text, 
     143         CONSTRAINT component_pkey PRIMARY KEY(name) 
     144) WITHOUT OIDS; 
     145 
     146CREATE TABLE milestone ( 
     147         id              integer, 
     148         name            text, 
     149         time            integer, 
     150         descr           text, 
     151         CONSTRAINT milestone_pkey PRIMARY KEY(name) 
     152) WITHOUT OIDS; 
     153 
     154CREATE TABLE version ( 
     155         name            text, 
     156         time            integer, 
     157         CONSTRAINT version_pkey PRIMARY KEY(name) 
     158) WITHOUT OIDS; 
     159 
     160CREATE TABLE wiki ( 
     161         name            text, 
     162         version         integer, 
     163         time            integer, 
     164         author          text, 
     165         ipnr            text, 
     166         text            text, 
     167         comment         text, 
     168         readonly        integer, 
     169         CONSTRAINT wiki_pkey PRIMARY KEY(name,version) 
     170) WITHOUT OIDS; 
     171 
     172CREATE TABLE attachment ( 
     173         type            text, 
     174         id              text, 
     175         filename        text, 
     176         size            integer, 
     177         time            integer, 
     178         description     text, 
     179         author          text, 
     180         ipnr            text, 
     181         CONSTRAINT attachment_pkey PRIMARY KEY(type,id,filename) 
     182) WITHOUT OIDS; 
     183 
     184CREATE TABLE session ( 
     185         sid             text, 
     186         username        text, 
     187         var_name        text, 
     188         var_value       text, 
     189         CONSTRAINT session_pkey PRIMARY KEY(sid,var_name) 
     190) WITHOUT OIDS; 
     191 
     192""" 
     193 
     194#CREATE INDEX node_change_idx ON node_change(rev); 
     195#CREATE INDEX ticket_change_idx  ON ticket_change(ticket, time); 
     196#CREATE INDEX wiki_idx           ON wiki(name,version); 
     197#CREATE INDEX session_idx        ON session(sid,var_name); 
     198 
     199## 
     200## Default Reports 
     201## 
     202 
     203reports = ( 
     204('Active Tickets', 
     205""" 
     206 * List all active tickets by priority. 
     207 * Color each row based on priority. 
     208 * If a ticket has been accepted, a '*' is appended after the owner's name 
     209""", 
     210""" 
     211SELECT p.value AS __color__, 
     212   id AS ticket, summary, component, version, milestone, severity,  
     213   (CASE status WHEN 'assigned' THEN owner||' *' ELSE owner END) AS owner, 
     214   time AS created, 
     215   changetime AS _changetime, description AS _description, 
     216   reporter AS _reporter 
     217  FROM ticket t, enum p 
     218  WHERE status IN ('new', 'assigned', 'reopened')  
     219AND p.name = t.priority AND p.type = 'priority' 
     220  ORDER BY p.value, milestone, severity, time 
     221"""), 
     222#---------------------------------------------------------------------------- 
     223 ('Active Tickets by Version', 
     224""" 
     225This report shows how to color results by priority, 
     226while grouping results by version. 
     227 
     228Last modification time, description and reporter are included as hidden fields 
     229for useful RSS export. 
     230""", 
     231""" 
     232SELECT p.value AS __color__, 
     233   version AS __group__, 
     234   id AS ticket, summary, component, version, severity,  
     235   (CASE status WHEN 'assigned' THEN owner||' *' ELSE owner END) AS owner, 
     236   time AS created, 
     237   changetime AS _changetime, description AS _description, 
     238   reporter AS _reporter 
     239  FROM ticket t, enum p 
     240  WHERE status IN ('new', 'assigned', 'reopened')  
     241AND p.name = t.priority AND p.type = 'priority' 
     242  ORDER BY (version IS NULL),version, p.value, severity, time 
     243"""), 
     244#---------------------------------------------------------------------------- 
     245('All Tickets by Milestone', 
     246""" 
     247This report shows how to color results by priority, 
     248while grouping results by milestone. 
     249 
     250Last modification time, description and reporter are included as hidden fields 
     251for useful RSS export. 
     252""", 
     253""" 
     254SELECT p.value AS __color__, 
     255   milestone||' Release' AS __group__, 
     256   id AS ticket, summary, component, version, severity,  
     257   (CASE status WHEN 'assigned' THEN owner||' *' ELSE owner END) AS owner, 
     258   time AS created, 
     259   changetime AS _changetime, description AS _description, 
     260   reporter AS _reporter 
     261  FROM ticket t, enum p 
     262  WHERE status IN ('new', 'assigned', 'reopened')  
     263AND p.name = t.priority AND p.type = 'priority' 
     264  ORDER BY (milestone IS NULL),milestone, p.value, severity, time 
     265"""), 
     266#---------------------------------------------------------------------------- 
     267('Assigned, Active Tickets by Owner', 
     268""" 
     269List assigned tickets, group by ticket owner, sorted by priority. 
     270""", 
     271""" 
     272 
     273SELECT p.value AS __color__, 
     274   owner AS __group__, 
     275   id AS ticket, summary, component, milestone, severity, time AS created, 
     276   changetime AS _changetime, description AS _description, 
     277   reporter AS _reporter 
     278  FROM ticket t,enum p 
     279  WHERE status = 'assigned' 
     280AND p.name=t.priority AND p.type='priority' 
     281  ORDER BY owner, p.value, severity, time 
     282"""), 
     283#---------------------------------------------------------------------------- 
     284('Assigned, Active Tickets by Owner (Full Description)', 
     285""" 
     286List tickets assigned, group by ticket owner. 
     287This report demonstrates the use of full-row display. 
     288""", 
     289""" 
     290SELECT p.value AS __color__, 
     291   owner AS __group__, 
     292   id AS ticket, summary, component, milestone, severity, time AS created, 
     293   description AS _description_, 
     294   changetime AS _changetime, reporter AS _reporter 
     295  FROM ticket t, enum p 
     296  WHERE status = 'assigned' 
     297AND p.name = t.priority AND p.type = 'priority' 
     298  ORDER BY owner, p.value, severity, time 
     299"""), 
     300#---------------------------------------------------------------------------- 
     301('All Tickets By Milestone  (Including closed)', 
     302""" 
     303A more complex example to show how to make advanced reports. 
     304""", 
     305""" 
     306SELECT p.value AS __color__, 
     307   t.milestone AS __group__, 
     308   (CASE status  
     309      WHEN 'closed' THEN 'color: #777; background: #ddd; border-color: #ccc;' 
     310      ELSE  
     311        (CASE owner WHEN '$USER' THEN 'font-weight: bold' END) 
     312    END) AS __style__, 
     313   id AS ticket, summary, component, status,  
     314   resolution,version, severity, priority, owner, 
     315   changetime AS modified, 
     316   time AS _time,reporter AS _reporter 
     317  FROM ticket t,enum p 
     318  WHERE p.name=t.priority AND p.type='priority' 
     319  ORDER BY (milestone IS NULL), milestone DESC, (status = 'closed'),  
     320        (CASE status WHEN 'closed' THEN modified ELSE -p.value END) DESC 
     321"""), 
     322#---------------------------------------------------------------------------- 
     323('My Tickets', 
     324""" 
     325This report demonstrates the use of the automatically set  
     326$USER dynamic variable, replaced with the username of the 
     327logged in user when executed. 
     328""", 
     329""" 
     330SELECT p.value AS __color__, 
     331   (CASE status WHEN 'assigned' THEN 'Assigned' ELSE 'Owned' END) AS __group__, 
     332   id AS ticket, summary, component, version, milestone, 
     333   severity, priority, time AS created, 
     334   changetime AS _changetime, description AS _description, 
     335   reporter AS _reporter 
     336  FROM ticket t, enum p 
     337  WHERE t.status IN ('new', 'assigned', 'reopened')  
     338AND p.name = t.priority AND p.type = 'priority' AND owner = '$USER' 
     339  ORDER BY (status = 'assigned') DESC, p.value, milestone, severity, time 
     340"""), 
     341#---------------------------------------------------------------------------- 
     342('Active Tickets, Mine first', 
     343""" 
     344 * List all active tickets by priority. 
     345 * Show all tickets owned by the logged in user in a group first. 
     346""", 
     347""" 
     348SELECT p.value AS __color__, 
     349   (CASE owner  
     350     WHEN '$USER' THEN 'My Tickets'  
     351     ELSE 'Active Tickets'  
     352    END) AS __group__, 
     353   id AS ticket, summary, component, version, milestone, severity,  
     354   (CASE status WHEN 'assigned' THEN owner||' *' ELSE owner END) AS owner, 
     355   time AS created, 
     356   changetime AS _changetime, description AS _description, 
     357   reporter AS _reporter 
     358  FROM ticket t, enum p 
     359  WHERE status IN ('new', 'assigned', 'reopened')  
     360AND p.name = t.priority AND p.type = 'priority' 
     361  ORDER BY (owner = '$USER') DESC, p.value, milestone, severity, time 
     362""")) 
     363 
     364 
     365## 
     366## Default database values 
     367## 
     368 
     369# (table, (column1, column2), ((row1col1, row1col2), (row2col1, row2col2))) 
     370data = (('component', 
     371             ('name', 'owner'), 
     372               (('component1', 'somebody'), 
     373                ('component2', 'somebody'))), 
     374           ('milestone', 
     375             ('name', 'time'), 
     376               (('', 0),  
     377                ('milestone1', 0), 
     378                ('milestone2', 0), 
     379                ('milestone3', 0), 
     380                ('milestone4', 0))), 
     381           ('version', 
     382             ('name', 'time'), 
     383               (('', 0), 
     384                ('1.0', 0), 
     385                ('2.0', 0))), 
     386           ('enum', 
     387             ('type', 'name', 'value'), 
     388               (('status', 'new', 1), 
     389                ('status', 'assigned', 2), 
     390                ('status', 'reopened', 3), 
     391                ('status', 'closed', 4), 
     392                ('resolution', 'fixed', 1), 
     393                ('resolution', 'invalid', 2), 
     394                ('resolution', 'wontfix', 3), 
     395                ('resolution', 'duplicate', 4), 
     396                ('resolution', 'worksforme', 5), 
     397                ('severity', 'blocker', 1), 
     398                ('severity', 'critical', 2), 
     399                ('severity', 'major', 3), 
     400                ('severity', 'normal', 4), 
     401                ('severity', 'minor', 5), 
     402                ('severity', 'trivial', 6), 
     403                ('severity', 'enhancement', 7), 
     404                ('priority', 'highest', 1), 
     405                ('priority', 'high', 2), 
     406                ('priority', 'normal', 3), 
     407                ('priority', 'low', 4), 
     408                ('priority', 'lowest', 5))), 
     409           ('permission', 
     410             ('username', 'action'), 
     411               (('anonymous', 'LOG_VIEW'), 
     412                ('anonymous', 'FILE_VIEW'), 
     413                ('anonymous', 'WIKI_VIEW'), 
     414                ('anonymous', 'WIKI_CREATE'), 
     415                ('anonymous', 'WIKI_MODIFY'), 
     416                ('anonymous', 'SEARCH_VIEW'), 
     417                ('anonymous', 'REPORT_VIEW'), 
     418                ('anonymous', 'REPORT_SQL_VIEW'), 
     419                ('anonymous', 'TICKET_VIEW'), 
     420                ('anonymous', 'TICKET_CREATE'), 
     421                ('anonymous', 'TICKET_MODIFY'), 
     422                ('anonymous', 'BROWSER_VIEW'), 
     423                ('anonymous', 'TIMELINE_VIEW'), 
     424                ('anonymous', 'CHANGESET_VIEW'), 
     425                ('anonymous', 'ROADMAP_VIEW'), 
     426                ('anonymous', 'MILESTONE_VIEW'))), 
     427           ('system', 
     428             ('name', 'value'), 
     429               (('database_version', str(db_version)),)), 
     430           ('report', 
     431             ('id', 'author', 'title', 'sql', 'description'), 
     432               __mkreports(reports))) 
     433 
     434default_config = \ 
     435 (('trac', 'htdocs_location', '/trac/'), 
     436  ('trac', 'repository_dir', '/var/svn/myrep'), 
     437  ('trac', 'templates_dir', '/usr/lib/trac/templates'), 
     438  ('trac', 'database', 'pgdb:"",host="localhost:5432",database="trac",' \ 
     439   'user="trac",password="trac"'), 
     440  ('trac', 'default_charset', 'iso-8859-15'), 
     441  ('logging', 'log_type', 'none'), 
     442  ('logging', 'log_file', 'trac.log'), 
     443  ('logging', 'log_level', 'DEBUG'), 
     444  ('project', 'name', 'My Project'), 
     445  ('project', 'descr', 'My example project'), 
     446  ('project', 'url', 'http://example.com/'), 
     447  ('project', 'icon', 'trac.ico'), 
     448  ('project', 'footer', 
     449   ' Visit the Trac open source project at<br />' 
     450   '<a href="http://trac.edgewall.com/">http://trac.edgewall.com/</a>'), 
     451  ('ticket', 'default_version', ''), 
     452  ('ticket', 'default_severity', 'normal'), 
     453  ('ticket', 'default_priority', 'normal'), 
     454  ('ticket', 'default_milestone', ''), 
     455  ('ticket', 'default_component', 'component1'), 
     456  ('header_logo', 'link', 'http://trac.edgewall.com/'), 
     457  ('header_logo', 'src', 'trac_banner.png'), 
     458  ('header_logo', 'alt', 'Trac'), 
     459  ('header_logo', 'width', '236'), 
     460  ('header_logo', 'height', '73'), 
     461  ('attachment', 'max_size', '262144'), 
     462  ('diff', 'tab_width', '8'), 
     463  ('mimeviewer', 'enscript_path', 'enscript'), 
     464  ('notification', 'smtp_enabled', 'false'), 
     465  ('notification', 'smtp_server', 'localhost'), 
     466  ('notification', 'smtp_always_cc', ''), 
     467  ('notification', 'always_notify_reporter', 'false'), 
     468  ('notification', 'smtp_from', 'trac@localhost'), 
     469  ('notification', 'smtp_replyto', 'trac@localhost'), 
     470  ('timeline', 'changeset_show_files', '0')) 
     471    
  • trac/auth.py

    old new  
    11# -*- coding: iso8859-1 -*- 
    22# 
    33# Copyright (C) 2003, 2004 Edgewall Software 
    4 # Copyright (C) 2003, 2004 Jonas Borgström <jonas@edgewall.com> 
     4# Copyright (C) 2003, 2004 Jonas Borgstr?m <jonas@edgewall.com> 
    55# 
    66# Trac is free software; you can redistribute it and/or 
    77# modify it under the terms of the GNU General Public License as 
     
    1717# along with this program; if not, write to the Free Software 
    1818# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
    1919# 
    20 # Author: Jonas Borgström <jonas@edgewall.com> 
     20# Author: Jonas Borgstr?m <jonas@edgewall.com> 
    2121 
    2222import time 
    2323import util 
     
    3030        if req.incookie.has_key('trac_auth'): 
    3131            cursor = db.cursor () 
    3232            cookie = req.incookie['trac_auth'].value 
    33             cursor.execute ("SELECT name FROM auth_cookie " 
    34                             "WHERE cookie=%s AND ipnr=%s" 
    35                             ,cookie, req.remote_addr) 
     33            sql = "SELECT name FROM auth_cookie " \ 
     34                  "WHERE cookie='%s' AND ipnr='%s'" \ 
     35                  % ( cookie, req.remote_addr ) 
     36            cursor.execute(sql) 
    3637            if cursor.rowcount >= 1: 
    3738                self.authname = cursor.fetchone()[0] 
    3839 
    3940    def login(self, req): 
    4041        cursor = self.db.cursor () 
    4142        cookie = util.hex_entropy() 
    42         cursor.execute ("INSERT INTO auth_cookie (cookie, name, ipnr, time)" + 
    43                         "VALUES (%s, %s, %s, %d)", 
    44                         cookie, req.remote_user, req.remote_addr, 
    45                         int(time.time())); 
     43        sql = "INSERT INTO auth_cookie (cookie, name, ipnr, time)" \ 
     44              "VALUES ('%s', '%s', '%s', %d)" \ 
     45              % ( cookie, req.remote_user, req.remote_addr, int(time.time()) ) 
     46        cursor.execute(sql); 
     47         
     48#        cursor.execute ("INSERT INTO auth_cookie (cookie, name, ipnr, time)" + 
     49#                        "VALUES (%s, %s, %s, %d)", 
     50#                        cookie, req.remote_user, req.remote_addr, 
     51#                        int(time.time())); 
    4652        self.db.commit () 
    4753        self.authname = req.remote_user 
    4854        req.outcookie['trac_auth'] = cookie 
  • trac/Wiki.py

    old new  
    11# -*- coding: iso8859-1 -*- 
    22# 
    33# Copyright (C) 2003, 2004 Edgewall Software 
    4 # Copyright (C) 2003, 2004 Jonas Borgström <jonas@edgewall.com> 
     4# Copyright (C) 2003, 2004 Jonas Borgstr?m <jonas@edgewall.com> 
    55# 
    66# Trac is free software; you can redistribute it and/or 
    77# modify it under the terms of the GNU General Public License as 
     
    1717# along with this program; if not, write to the Free Software 
    1818# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
    1919# 
    20 # Author: Jonas Borgström <jonas@edgewall.com> 
     20# Author: Jonas Borgstr?m <jonas@edgewall.com> 
    2121 
    2222import os 
    2323import time 
     
    2727 
    2828import perm 
    2929from Module import Module 
    30 from util import escape, TracError, get_reporter_id 
     30from util import escape, TracError, get_reporter_id, sql_escape 
    3131from Session import Session 
    3232from WikiFormatter import * 
    3333 
     
    5656        self.name = name 
    5757        self.perm = perm 
    5858        cursor = self.db.cursor () 
     59        sql = "SELECT version, text, readonly FROM wiki " 
    5960        if version: 
    60             cursor.execute ('SELECT version, text, readonly FROM wiki ' 
    61                             'WHERE name=%s AND version=%s', 
    62                             name, version) 
     61            sql += "WHERE name='%s' AND version=%s" % (name, version) 
    6362        else: 
    64             cursor.execute ('SELECT version, text, readonly FROM wiki ' 
    65                             'WHERE name=%s ORDER BY version DESC LIMIT 1', name
     63            sql += "WHERE name='%s' ORDER BY version DESC LIMIT 1" % name 
     64        cursor.execute(sql
    6665        row = cursor.fetchone() 
    6766        if row: 
    6867            self.new = 0 
     
    102101            self.db.commit () 
    103102            self.old_readonly = self.readonly 
    104103        elif self.modified: 
    105             cursor.execute ('INSERT INTO WIKI ' 
    106                             '(name, version, time, author, ipnr, text, comment, readonly) ' 
    107                             'VALUES (%s, %s, %s, %s, %s, %s, %s, %s)', 
    108                             self.name, self.version, int(time.time()), 
    109                             author, remote_addr, self.text, comment, self.readonly) 
     104            sql = "INSERT INTO WIKI " \ 
     105                  "(name, version, time, author, ipnr, text, comment, readonly) " \ 
     106                  "VALUES ('%s', %s, %s, '%s', '%s', '%s', '%s', %s)" \ 
     107                  % ( 
     108                     sql_escape(self.name), self.version, int(time.time()), 
     109                     sql_escape(author), sql_escape(remote_addr),  
     110                     sql_escape(self.text), sql_escape(comment), self.readonly 
     111                    ) 
     112            cursor.execute (sql) 
    110113            self.db.commit () 
    111114            self.old_readonly = self.readonly 
    112115            self.modified = 0 
     
    124127        This information is used to present a changelog/history for a given page 
    125128        """ 
    126129        cursor = self.db.cursor () 
    127         cursor.execute ('SELECT version, time, author, comment, ipnr FROM wiki ' 
    128                         'WHERE name=%s ORDER BY version DESC', pagename) 
     130        sql = "SELECT version, time, author, comment, ipnr FROM wiki " \ 
     131              "WHERE name='%s' ORDER BY version DESC" % pagename 
     132        cursor.execute (sql) 
    129133        i = 0 
    130134        while 1: 
    131135            row = cursor.fetchone() 
     
    155159           self.req.redirect(self.env.href.wiki(pagename, version, 1)) 
    156160 
    157161        cursor = self.db.cursor() 
    158         cursor.execute ('SELECT text,author,comment,time FROM wiki ' 
    159                         'WHERE name=%s AND (version=%s or version=%s)' 
    160                         'ORDER BY version ASC', pagename, version - 1, version) 
     162        sql = "SELECT text,author,comment,time FROM wiki " \ 
     163              "WHERE name='%s' AND (version=%s or version=%s) " \ 
     164              "ORDER BY version ASC" % (pagename, version - 1, version) 
     165        cursor.execute (sql) 
    161166        res = cursor.fetchall() 
    162167        if not res: 
    163168            raise TracError('Version %d of page "%s" not found.' 
    164169                            % (version, pagename), 
    165170                            'Page Not Found') 
    166  
     171         
    167172        if len(res) == 1: 
    168173            old = '' 
    169174        else: 
  • trac/Environment.py

    old new  
    11# -*- coding: iso8859-1 -*- 
    22# 
    33# Copyright (C) 2003, 2004 Edgewall Software 
    4 # Copyright (C) 2003, 2004 Jonas Borgström <jonas@edgewall.com> 
     4# Copyright (C) 2003, 2004 Jonas Borgstr?m <jonas@edgewall.com> 
    55# 
    66# Trac is free software; you can redistribute it and/or 
    77# modify it under the terms of the GNU General Public License as 
     
    1717# along with this program; if not, write to the Free Software 
    1818# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
    1919# 
    20 # Author: Jonas Borgström <jonas@edgewall.com> 
     20# Author: Jonas Borgstr?m <jonas@edgewall.com> 
    2121# 
    2222# Todo: Move backup and upgrade from db.py 
    2323# 
     
    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 
     
    7171        assert fd.read(26) == 'Trac Environment Version 1' 
    7272        fd.close() 
    7373 
    74     def get_db_cnx(self): 
    75         db_str = self.get_config('trac', 'database', 'sqlite:db/trac.db') 
    76         assert db_str[:7] == 'sqlite:' 
    77         db_name = os.path.join(self.path, db_str[7:]) 
    78         if not os.access(db_name, os.F_OK): 
    79             raise EnvironmentError, 'Database "%s" not found.' % db_name 
     74    def get_db_cnx(self, check_exists=1): 
     75        db_str = self.get_config('trac',  
     76                                 'database',  
     77                                 'sqlite:"db/trac.db",timeout=10000') 
     78                                  
     79        pos = db_str.find(':') 
     80        if pos == -1: 
     81            raise EnvironmentError, 'Connection param must be of form ' \ 
     82                  '(db_module_name):(db_connect_params), the value "%s ' \ 
     83                  'does not match' % db_str 
    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        module_name = db_str[:pos] 
     86        connect_params = db_str[pos+1:].split(',') 
     87         
     88        # following is very crude code for parsing the arguments in the 
     89        # db_connect_params string 
     90        kargs = {} 
     91        arg_list = [] 
     92        for x in connect_params: 
     93            pos1 = x.find('=') 
     94            pos2 = x.find('"') 
     95            pos3 = x.find("'") 
     96            if pos1 > -1: 
     97                if pos2 > -1 and pos2 < pos1: 
     98                    arg_list.append(eval(x)) 
     99                elif pos3 > -1 and pos3 < pos1: 
     100                    arg_list.append(eval(x)) 
     101                else: 
     102                    name = x[:pos1].strip() 
     103                    value = eval(x[pos1+1:].strip()) 
     104                    kargs[name] = value 
     105            else: 
     106                # self.log.debug("Environment - get_db_cnx - x: %s" % x) 
     107                arg_list.append(eval(x)) 
     108        args = tuple(arg_list) 
     109         
     110        import_str = 'import %s' % module_name 
    89111 
    90     def create(self): 
     112        # since Trac has a slightly closer relationship with sqlite than 
     113        # other db's, there's a special case setup here so that when the 
     114        # path to the sqlite db is specified, its relative to TRAC_ENV 
     115        if module_name == 'sqlite': 
     116            db_name = os.path.join(self.path, args[0]) 
     117            args = list(args) 
     118            args[0] = '%s' % db_name 
     119            args = tuple(args) 
     120            if check_exists == 1 and not os.access(db_name, os.F_OK): 
     121                raise EnvironmentError, 'Database "%s" not found.' % db_name 
     122         
     123            directory = os.path.dirname(db_name) 
     124            if (check_exists == 1 and not os.access(db_name, os.R_OK + os.W_OK)) \ 
     125                or not os.access(directory, os.R_OK + os.W_OK): 
     126                raise EnvironmentError, \ 
     127                      'The web server user requires read _and_ write permission\n' \ 
     128                      'to the database %s and the directory this file is located in.' % db_name 
     129         
     130        # handle weird import for PostgreSQL module 
     131        if module_name == 'PgSQL': 
     132            import_str = "from pyPgSQL import PgSQL" 
     133             
     134        exec import_str 
     135        m = eval(module_name) 
     136 
     137#        self.log.debug("Connecting to database module [%s] with: args=%s, " \ 
     138#                       "kargs=%s" % (module_name, str(args), str(kargs))) 
     139        conn = m.connect(*args, **kargs) 
     140        return conn 
     141 
     142 
     143    def create(self, db_str=None): 
    91144        def _create_file(fname, data=None): 
    92145            fd = open(fname, 'w') 
    93146            if data: fd.write(data) 
     
    128181""") 
    129182        # Create default database 
    130183        os.mkdir(os.path.join(self.path, 'db')) 
    131         cnx = sqlite.connect(os.path.join(self.path, 'db', 'trac.db')) 
     184        self.load_config() 
     185        self.setup_default_config() 
     186        if db_str: 
     187            self.cfg.set('trac', 'database', db_str) 
     188        self.save_config() 
     189        cnx = self.get_db_cnx(check_exists=0) 
    132190        cursor = cnx.cursor() 
    133191        cursor.execute(db_default.schema) 
    134192        cnx.commit() 
     
    138196            if v == None: 
    139197                return 'NULL' 
    140198            else: 
    141                 return '"%s"' % v 
     199                prepped = v 
     200                if type(v) == str: 
     201                    prepped = prepped.replace("'", "''") 
     202                return "'%s'" % prepped 
    142203        cnx = self.get_db_cnx() 
    143204        cursor = cnx.cursor() 
    144205         
     
    149210                values = ','.join(map(prep_value, row)) 
    150211                sql = "INSERT INTO %s (%s) VALUES(%s);" % (table, cols, values) 
    151212                cursor.execute(sql) 
     213        cnx.commit() 
     214 
     215    def setup_default_config(self): 
    152216        for s,n,v in db_default.default_config: 
    153217            if not self.cfg.has_section(s): 
    154218                self.cfg.add_section(s) 
    155219            self.cfg.set(s, n, v) 
    156         self.save_config() 
    157         cnx.commit() 
    158220 
    159221    def get_version(self): 
    160222        cnx = self.get_db_cnx() 
     
    216278 
    217279    def get_attachments(self, cnx, type, id): 
    218280        cursor = cnx.cursor() 
    219         cursor.execute('SELECT filename,description,type,size,time,author,ipnr ' 
    220                        'FROM attachment ' 
    221                        'WHERE type=%s AND id=%s ORDER BY time', type, id) 
     281        sql = "SELECT filename,description,type,size,time,author,ipnr " \ 
     282              "FROM attachment " \ 
     283              "WHERE type='%s' AND id='%s' ORDER BY time" % (type, id) 
     284        cursor.execute(sql) 
    222285        return cursor.fetchall() 
    223286     
    224287    def get_attachments_hdf(self, cnx, type, id, hdf, prefix): 
  • trac/Ticket.py

    old new  
    11# -*- coding: iso8859-1 -*- 
    22# 
    33# Copyright (C) 2003, 2004 Edgewall Software 
    4 # Copyright (C) 2003, 2004 Jonas Borgström <jonas@edgewall.com> 
     4# Copyright (C) 2003, 2004 Jonas Borgstr?m <jonas@edgewall.com> 
    55# 
    66# Trac is free software; you can redistribute it and/or 
    77# modify it under the terms of the GNU General Public License as 
     
    1717# along with this program; if not, write to the Free Software 
    1818# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
    1919# 
    20 # Author: Jonas Borgström <jonas@edgewall.com> 
     20# Author: Jonas Borgstr?m <jonas@edgewall.com> 
    2121 
    2222import re 
    2323import time 
     
    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        sql = "SELECT name,value FROM ticket_custom WHERE ticket=%s" % id 
     77        cursor.execute(sql) 
    7778        rows = cursor.fetchall() 
    7879        if rows: 
    7980            for r in rows: 
     
    134135        # is updated accordingly. (#623). 
    135136        if self['status'] == 'new' and self._old.has_key('component') and \ 
    136137               not self._old.has_key('owner'): 
    137             cursor.execute('SELECT owner FROM component ' 
    138                            'WHERE name=%s', self._old['component']) 
     138            sql = "SELECT owner FROM component " \ 
     139                  "WHERE name=%s" % self._old['component'] 
     140            cursor.execute(sql) 
    139141            old_owner = cursor.fetchone()[0] 
    140142            if self['owner'] == old_owner: 
    141                 cursor.execute('SELECT owner FROM component ' 
    142                                'WHERE name=%s', self['component']) 
     143                sql = "SELECT owner FROM component " \ 
     144                      "WHERE name=%s" % self['component'] 
     145                cursor.execute(sql) 
    143146                self['owner'] = cursor.fetchone()[0] 
    144147            
    145148 
    146149        for name in self._old.keys(): 
    147150            if name[:7] == 'custom_': 
    148151                fname = name[7:] 
    149                 cursor.execute('REPLACE INTO ticket_custom(ticket,name,value)' 
    150                                ' VALUES(%s, %s, %s)', id, fname, self[name]) 
     152                sql = "REPLACE INTO ticket_custom(ticket,name,value) " \ 
     153                      "VALUES(%s, '%s', '%s')" \ 
     154                      % (id, util.sql_escape(fname), util.sql_escape(self[name])) 
     155                cursor.execute(sql) 
    151156            else: 
    152157                fname = name 
    153                 cursor.execute ('UPDATE ticket SET %s=%s WHERE id=%s', 
    154                                 fname, self[name], id) 
    155  
    156             cursor.execute ('INSERT INTO ticket_change ' 
    157                             '(ticket, time, author, field, oldvalue, newvalue) ' 
    158                             'VALUES (%s, %s, %s, %s, %s, %s)', 
    159                             id, when, author, fname, self._old[name], self[name]) 
     158                sql = "UPDATE ticket SET %s='%s' WHERE id=%s" \ 
     159                      % (fname, util.sql_escape(self[name]), id) 
     160                cursor.execute (sql) 
     161             
     162            sql = "INSERT INTO ticket_change " \ 
     163                  "(ticket, time, author, field, oldvalue, newvalue) " \ 
     164                  "VALUES (%s, %s, '%s', '%s', '%s', '%s')" \ 
     165                  % ( 
     166                     id, when, util.sql_escape(author), util.sql_escape(fname), 
     167                     util.sql_escape(self._old[name]), util.sql_escape(self[name]) 
     168                    ) 
     169            cursor.execute (sql) 
    160170        if comment: 
    161             cursor.execute ('INSERT INTO ticket_change ' 
    162                             '(ticket,time,author,field,oldvalue,newvalue) ' 
    163                             "VALUES (%s, %s, %s, 'comment', '', %s)", 
    164                             id, when, author, comment) 
     171            sql = "INSERT INTO ticket_change " \ 
     172                  "(ticket,time,author,field,oldvalue,newvalue) " \ 
     173                  "VALUES (%s, %s, '%s', 'comment', '', '%s')" \ 
     174                  % ( id, when, util.sql_escape(author), util.sql_escape(comment) ) 
     175            cursor.execute (sql) 
    165176 
    166         cursor.execute ('UPDATE ticket SET changetime=%s WHERE id=%s', when, id) 
     177        sql = "UPDATE ticket SET changetime=%s WHERE id=%s" % (when, id) 
     178        cursor.execute (sql) 
    167179        db.commit() 
    168180        self._forget_changes() 
    169181 
    170182    def get_changelog(self, db, when=0): 
    171183        """Returns the changelog as a list of dictionaries""" 
    172184        cursor = db.cursor() 
     185        when_clause = "" 
    173186        if when: 
    174             cursor.execute('SELECT time, author, field, oldvalue, newvalue ' 
    175                            'FROM ticket_change ' 
    176                            'WHERE ticket=%s AND time=%s' 
    177                            'UNION ' 
    178                            'SELECT time, author, "attachment", null, filename ' 
    179                            'FROM attachment ' 
    180                            'WHERE id=%s AND time=%s ' 
    181                            'ORDER BY time',  self['id'], when, self['id'], when) 
    182         else: 
    183             cursor.execute('SELECT time, author, field, oldvalue, newvalue ' 
    184                            'FROM ticket_change ' 
    185                            'WHERE ticket=%s ' 
    186                            'UNION ' 
    187                            'SELECT time, author, "attachment", null,filename ' 
    188                            'FROM attachment ' 
    189                            'WHERE id = %s ' 
    190                            'ORDER BY time', self['id'],  self['id']) 
     187            when_clause = " AND time=%s " % when 
     188        sql = "SELECT time, author, field, oldvalue, newvalue " \ 
     189              "FROM ticket_change " \ 
     190              "WHERE ticket=%s %s " \ 
     191              "UNION " \ 
     192              "SELECT time, author, 'attachment', null, filename " \ 
     193              "FROM attachment " \ 
     194              "WHERE id=%s %s " \ 
     195              "ORDER BY time" \ 
     196              % (self['id'], when_clause, self['id'], when_clause) 
     197        # raise util.TracError(sql) 
     198        cursor.execute(sql) 
    191199        log = [] 
    192200        while 1: 
    193201            row = cursor.fetchone() 
  • contrib/create_pgdb.sql

    old new  
     1CREATE TABLE revision ( 
     2        rev             integer, 
     3        time            integer, 
     4        author          text, 
     5        message         text, 
     6        CONSTRAINT revision_pkey PRIMARY KEY (rev) 
     7) WITHOUT OIDS; 
     8 
     9CREATE TABLE node_change ( 
     10        rev             integer, 
     11        name            text, 
     12        change          char(1), 
     13        CONSTRAINT node_change_pkey PRIMARY KEY (rev, name, change) 
     14) WITHOUT OIDS; 
     15 
     16CREATE TABLE auth_cookie ( 
     17        cookie          text, 
     18        name            text, 
     19        ipnr            text, 
     20        time            integer, 
     21        CONSTRAINT auth_cookie_pkey PRIMARY KEY(cookie, name, ipnr) 
     22) WITHOUT OIDS; 
     23 
     24CREATE TABLE enum ( 
     25        type            text, 
     26        name            text, 
     27        value           text, 
     28        CONSTRAINT enum_pkey PRIMARY KEY(name,type) 
     29) WITHOUT OIDS; 
     30 
     31CREATE TABLE system ( 
     32        name            text, 
     33        value           text, 
     34        CONSTRAINT system_pkey PRIMARY KEY(name) 
     35) WITHOUT OIDS; 
     36 
     37CREATE TABLE lock ( 
     38        name            text, 
     39        owner           text, 
     40        ipnr            text, 
     41        time            integer, 
     42        CONSTRAINT lock_pkey PRIMARY KEY(name) 
     43) WITHOUT OIDS; 
     44 
     45CREATE TABLE ticket ( 
     46        id              integer, 
     47        time            integer,        -- the time it was created 
     48        changetime      integer, 
     49        component       text, 
     50        severity        text, 
     51        priority        text, 
     52        owner           text,           -- who is this ticket assigned to 
     53        reporter        text, 
     54        cc              text,           -- email addresses to notify 
     55        url             text,           -- url related to this ticket 
     56        version         text,           --  
     57        milestone       text,           --  
     58        status          text, 
     59        resolution      text, 
     60        summary         text,           -- one-line summary 
     61        description     text,           -- problem description (long) 
     62        keywords        text, 
     63        CONSTRAINT ticket_pkey PRIMARY KEY(id) 
     64) WITHOUT OIDS; 
     65 
     66CREATE TABLE ticket_change ( 
     67        ticket          integer, 
     68        time            integer, 
     69        author          text, 
     70        field           text, 
     71        oldvalue        text, 
     72        newvalue        text, 
     73        CONSTRAINT ticket_change_pkey PRIMARY KEY(ticket, time, field) 
     74) WITHOUT OIDS; 
     75 
     76CREATE TABLE ticket_custom ( 
     77       ticket               integer, 
     78       name             text, 
     79       value            text, 
     80       CONSTRAINT ticket_custom_pkey PRIMARY KEY(ticket,name) 
     81) WITHOUT OIDS; 
     82 
     83CREATE TABLE report ( 
     84        id              integer, 
     85        author          text, 
     86        title           text, 
     87        sql             text, 
     88        description     text, 
     89        CONSTRAINT report_pkey PRIMARY KEY(id) 
     90) WITHOUT OIDS; 
     91 
     92CREATE TABLE permission ( 
     93        username        text,           --  
     94        action          text,           -- allowable activity 
     95        CONSTRAINT permission_pkey PRIMARY KEY(username,action) 
     96) WITHOUT OIDS; 
     97 
     98CREATE TABLE component ( 
     99         name            text, 
     100         owner           text, 
     101         CONSTRAINT component_pkey PRIMARY KEY(name) 
     102) WITHOUT OIDS; 
     103 
     104CREATE TABLE milestone ( 
     105         id              integer, 
     106         name            text, 
     107         time            integer, 
     108         descr           text, 
     109         CONSTRAINT milestone_pkey PRIMARY KEY(name) 
     110) WITHOUT OIDS; 
     111 
     112CREATE TABLE version ( 
     113         name            text, 
     114         time            integer, 
     115         CONSTRAINT version_pkey PRIMARY KEY(name) 
     116) WITHOUT OIDS; 
     117 
     118CREATE TABLE wiki ( 
     119         name            text, 
     120         version         integer, 
     121         time            integer, 
     122         author          text, 
     123         ipnr            text, 
     124         text            text, 
     125         comment         text, 
     126         readonly        integer, 
     127         CONSTRAINT wiki_pkey PRIMARY KEY(name,version) 
     128) WITHOUT OIDS; 
     129 
     130CREATE TABLE attachment ( 
     131         type            text, 
     132         id              text, 
     133         filename        text, 
     134         size            integer, 
     135         time            integer, 
     136         description     text, 
     137         author          text, 
     138         ipnr            text, 
     139         CONSTRAINT attachment_pkey PRIMARY KEY(type,id,filename) 
     140) WITHOUT OIDS; 
     141 
     142CREATE TABLE session ( 
     143         sid             text, 
     144         username        text, 
     145         var_name        text, 
     146         var_value       text, 
     147         CONSTRAINT session_pkey PRIMARY KEY(sid,var_name) 
     148) WITHOUT OIDS; 
  • contrib/tracdb-sqlite2pg.py

    old new  
     1#!/usr/bin/env python 
     2 
     3""" 
     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, _force): 
     43     
     44     
     45    # init PostgreSQL environment 
     46    print "PostgreSQL('%s':'%s':'%s'): connecting..." \ 
     47                      % (_host, _db, _user) 
     48    pg_con = pgdb.connect(host=_host, database=_db,  
     49                          user=_user, password=_password) 
     50    pg_cur = pg_con.cursor() 
     51 
     52    # init Trac environment 
     53    print "Trac SQLite('%s'): connecting..." % (_env) 
     54    trac_con = sqlite.connect(os.path.join(_env, "db/trac.db"), 
     55                              timeout=10000) 
     56    trac_cur = trac_con.cursor() 
     57    print 
     58 
     59#    fieldtypes = FieldTranslator() 
     60#    fieldtypes['0'] = 'int' 
     61#    fieldtypes['6'] = 'text' 
     62     
     63    # loop thru tables, converting them 
     64    for t in tables: 
     65        print 
     66        print "Converting Table: '%s'" % t 
     67 
     68        # clear out existing table 
     69        pg_cur.execute("truncate table %s;" % t) 
     70 
     71        # get table info 
     72        sql = "SELECT * FROM %s" % t 
     73        trac_cur.execute(sql) 
     74        cols = trac_cur.rs.col_defs 
     75        counter = 0 
     76         
     77        # loop thru rows, moving data from sqlite to pgsql 
     78        while 1: 
     79            row = trac_cur.fetchone() 
     80            counter += 1 
     81            if not row: 
     82                break 
     83            flds="" 
     84            vals="" 
     85            for c in cols: 
     86                field = c[0] 
     87                type = c[1] 
     88                value = row[field] 
     89                if value != None: 
     90                    flds += ", %s" % field 
     91                    if type in [6]: 
     92                        value = "'%s'" % sql_escape(value) 
     93                    vals += ", %s" % value 
     94            flds = flds[2:] 
     95            vals = vals[2:] 
     96            sql  = "INSERT INTO %s " % t 
     97            sql += "(%s) " % flds 
     98            sql += "VALUES (%s);" % vals 
     99 
     100            pg_cur.execute(sql) 
     101            pg_con.commit() 
     102             
     103            if counter % 100 == 0: 
     104                print "%s rows" % counter 
     105         
     106    trac_cur.close() 
     107    trac_con.close() 
     108    pg_cur.close() 
     109    pg_con.close() 
     110    print 
     111         
     112     
     113def usage(): 
     114    print "tracdb-sqlite2pg - Converts a Trac database from sqlite to postgresql." 
     115    print 
     116    print "Usage: tracdb-sqlite2pg.py [options]" 
     117    print 
     118    print "Available Options:" 
     119    print "  -t  | --tracenv /path/to/trac/env - full path to Trac environment" 
     120    print "  -h  | --host <pgsql hostname>     - PostgreSQL hostname" 
     121    print "  -db | --database <pgsql database> - PostgreSQL database name" 
     122    print "  -u  | --user <pgsql username>     - PostgreSQL username" 
     123    print "  -p  | --passwd <pgsql password>   - PostgreSQL password" 
     124    print "  -c  | --clean                     - clean out PG database before converting." 
     125    print "  --help | help                     - this help info" 
     126    print 
     127    print "Additional configuration options can be defined directly in the script." 
     128    print 
     129    sys.exit(0) 
     130 
     131def main(): 
     132    global TRAC_ENV, PG_HOST, PG_DB, PG_USER, PG_PASSWORD, PG_CLEAN 
     133    if len (sys.argv) > 1: 
     134        if sys.argv[1] in ['--help','help'] or len(sys.argv) < 4: 
     135            usage() 
     136        iter = 1 
     137        while iter < len(sys.argv): 
     138            if sys.argv[iter] in ['-t', '--tracenv'] and iter+1 < len(sys.argv): 
     139                TRAC_ENV = sys.argv[iter+1] 
     140                iter = iter + 1 
     141            elif sys.argv[iter] in ['-h', '--host'] and iter+1 < len(sys.argv): 
     142                PG_HOST = sys.argv[iter+1] 
     143                iter = iter + 1 
     144            elif sys.argv[iter] in ['-db', '--database'] and iter+1 < len(sys.argv): 
     145                PG_DB = sys.argv[iter+1] 
     146                iter = iter + 1 
     147            elif sys.argv[iter] in ['-u', '--user'] and iter+1 < len(sys.argv): 
     148                PG_USER = sys.argv[iter+1] 
     149                iter = iter + 1 
     150            elif sys.argv[iter] in ['-p', '--passwd'] and iter+1 < len(sys.argv): 
     151                PG_PASSWORD = sys.argv[iter+1] 
     152                iter = iter + 1 
     153            elif sys.argv[iter] in ['-c', '--clean']: 
     154                PG_CLEAN = 1 
     155            else: 
     156                print "Error: unknown parameter: " + sys.argv[iter] 
     157                sys.exit(0) 
     158            iter = iter + 1 
     159    else: 
     160        usage() 
     161         
     162    convert(TRAC_ENV, PG_HOST, PG_DB, PG_USER, PG_PASSWORD, PG_CLEAN) 
     163 
     164 
     165if __name__ == '__main__': 
     166    main()