source: timingandestimationplugin/branches/trac0.12-Permissions/timingandestimationplugin/dbhelper.py

Last change on this file was 11738, checked in by Russ Tyndall, 11 years ago

updated db-helper backend checks to correctly handle pooled connections fix #10165

File size: 6.5 KB
RevLine 
[11738]1import trac.db.pool
[10779]2import trac.db.sqlite_backend
[11059]3import trac.db.postgres_backend
4import trac.db.mysql_backend
[1119]5
[11738]6def is_db_type(db, typeToVerify):
7    cnx = db.cnx
8    t = type(cnx)
9    if t == trac.db.pool.PooledConnection:
10        t = type(cnx.cnx)
11    return typeToVerify == t
12
[8141]13def get_all(env, sql, *params):
[1119]14    """Executes the query and returns the (description, data)"""
[8141]15    db = env.get_read_db()
[1119]16    cur = db.cursor()
[1693]17    desc  = None
18    data = None
[1119]19    try:
20        cur.execute(sql, params)
[1389]21        data = list(cur.fetchall())
[1119]22        desc = cur.description
[1667]23    except Exception, e:
[8141]24        env.log.exception('There was a problem executing sql:%s \n \
[1667]25with parameters:%s\nException:%s'%(sql, params, e));
[8141]26   
[1119]27    return (desc, data)
28
[8141]29def execute_non_query(env, sql, *params):
[1119]30    """Executes the query on the given project"""
[8141]31    execute_in_trans(env, (sql, params))
32   
33def get_first_row(env, sql,*params):
[2824]34    """ Returns the first row of the query results as a tuple of values (or None)"""
[8141]35    db = env.get_read_db()
[2785]36    cur = db.cursor()
[2824]37    data = None;
[2785]38    try:
[2824]39        cur.execute(sql, params)
40        data = cur.fetchone();
[2785]41    except Exception, e:
[8141]42        env.log.exception('There was a problem executing sql:%s \n \
[2785]43        with parameters:%s\nException:%s'%(sql, params, e));
[2824]44    return data;
[1119]45
[8141]46def get_scalar(env, sql, col=0, *params):
[2824]47    """ Gets a single value (in the specified column) from the result set of the query"""
[8141]48    data = get_first_row(env, sql, *params);
[2824]49    if data:
50        return data[col]
51    else:
52        return None;
[2785]53
[8141]54def execute_in_trans(env, *args):
[3119]55    result = True
[8141]56    c_sql =[None]
57    c_params = [None]
[1119]58    try:
[8141]59        @env.with_transaction()
60        def fn(db):
61            cur = db.cursor()
62            for sql, params in args:
63                c_sql[0] = sql
64                c_params[0] = params
65                cur.execute(sql, params)
[8193]66    except Exception, e :
[8141]67        env.log.exception('There was a problem executing sql:%s \n \
68    with parameters:%s\nException:%s'%(c_sql[0], c_params[0], e));
[8193]69        raise e
[3119]70    return result
[1365]71
[8193]72def execute_in_nested_trans(env, name, *args):
73    result = True
74    c_sql =[None]
75    c_params = [None]
[9701]76    @env.with_transaction()
77    def fn(db):
78        cur = None
79        try:
[8193]80            cur = db.cursor()
81            cur.execute("SAVEPOINT %s" % name)
82            for sql, params in args:
83                c_sql[0] = sql
84                c_params[0] = params
85                cur.execute(sql, params)
86            cur.execute("RELEASE SAVEPOINT %s" % name)
[9701]87        except Exception, e :
88            cur.execute("ROLLBACK TO SAVEPOINT %s" % name)
89            env.log.exception('There was a problem executing sql:%s \n \
[8193]90    with parameters:%s\nException:%s'%(c_sql[0], c_params[0], e));
[9701]91            raise e
[8193]92    return result
93
[11059]94def current_schema (env):
95    db = env.get_read_db()
[11738]96    if is_db_type(db, trac.db.sqlite_backend.SQLiteConnection):
[11059]97        return None
[11738]98    elif is_db_type(db, trac.db.mysql_backend.MySQLConnection):
[11059]99        return get_scalar(env, 'SELECT schema();')
[11738]100    elif is_db_type(db, trac.db.postgres_backend.PostgreSQLConnection):
[11059]101        return get_scalar(env, 'SHOW search_path;')
102
[11260]103def _prep_schema(s):
[11383]104    #remove double quotes, escape single quotes
105    if not s: return "'<NOT VALID>'"
106    return ','.join(("'"+i.replace('"','').replace("'","''")+"'"
[11260]107                     for i in s.split(',')))
108
[8141]109def db_table_exists(env,  table):
[10766]110    db = env.get_read_db()
[11059]111    cnt = None
[11738]112    if is_db_type(db, trac.db.sqlite_backend.SQLiteConnection):
[10766]113        sql = "select count(*) from sqlite_master where type = 'table' and name = %s"
[11059]114        cnt = get_scalar(env, sql, 0, table)
[10766]115    else:
[11059]116        sql = """SELECT count(*) FROM information_schema.tables
[11260]117                 WHERE table_name = %%s and table_schema in (%s)
118              """ % _prep_schema(current_schema(env))
119        cnt = get_scalar(env, sql, 0, table)
[10766]120    return cnt > 0
[1119]121
[8141]122def get_column_as_list(env, sql, col=0, *params):
123    data = get_all(env, sql, *params)[1] or ()
[2893]124    return [valueList[col] for valueList in data]
[1119]125
[8141]126def get_system_value(env, key):
127    return get_scalar(env, "SELECT value FROM system WHERE name=%s", 0, key)
[1119]128
[8141]129def set_system_value(env, key, value):
130    if get_system_value(env, key):
131        execute_non_query(env, "UPDATE system SET value=%s WHERE name=%s", value, key)       
[2774]132    else:
[8141]133        execute_non_query(env, "INSERT INTO system (value, name) VALUES (%s, %s)",
[2774]134            value, key)
135
136
[8141]137def get_result_set(env, sql, *params):
[1119]138    """Executes the query and returns a Result Set"""
[8141]139    tpl = get_all(env, sql, *params);
[3119]140    if tpl and tpl[0] and tpl[1]:
141        return ResultSet(tpl)
142    else:
143        return None
[1119]144
[2349]145
[1119]146class ResultSet:
147    """ the result of calling getResultSet """
148    def __init__ (self, (columnDescription, rows)):
[8141]149        self.columnDescription, self.rows = columnDescription, rows
[1119]150        self.columnMap = self.get_column_map()
151
152    def get_column_map ( self ):
153        """This function will take the result set from getAll and will
154        return a hash of the column names to their index """
155        h = {}
156        i = 0
157        if self.columnDescription:
158            for col in self.columnDescription:
159                h[ col[0] ] = i
160                i+=1
161        return h;
[8141]162   
[1119]163    def value(self, col, row ):
164        """ given a row(list or idx) and a column( name or idx ), retrieve the appropriate value"""
165        tcol = type(col)
166        trow = type(row)
167        if tcol == str:
168            if(trow == list or trow == tuple):
169                return row[self.columnMap[col]]
170            elif(trow == int):
171                return self.rows[row][self.columnMap[col]]
172            else:
173                print ("rs.value Type Failed col:%s  row:%s" % (type(col), type(row)))
174        elif tcol == int:
175            if(trow == list or trow == tuple):
176                return row[col]
177            elif(trow == int):
178                return self.rows[row][col]
179            else:
180                print ("rs.value Type Failed col:%s  row:%s" % (type(col), type(row)))
181        else:
182            print ("rs.value Type Failed col:%s  row:%s" % (type(col), type(row)))
[8141]183   
[3119]184    def json_out(self):
185        json = "[%s]" % ',\r\n'. join(
186            [("{%s}" % ','.join(
187            ["'%s':'%s'" %
[8141]188             (key, unicode(self.value(val, row)).
[3119]189              replace("'","\\'").
190              replace('"','\\"').
191              replace('\r','\\r').
192              replace('\n','\\n'))
193             for (key, val) in self.columnMap.items()]))
194             for row in self.rows])
195        #mylog.debug('serializing to json : %s'% json)
196        return json
Note: See TracBrowser for help on using the repository browser.