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

Last change on this file was 11737, 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
Line 
1import trac.db.pool
2import trac.db.sqlite_backend
3import trac.db.postgres_backend
4import trac.db.mysql_backend
5
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
13def get_all(env, sql, *params):
14    """Executes the query and returns the (description, data)"""
15    db = env.get_read_db()
16    cur = db.cursor()
17    desc  = None
18    data = None
19    try:
20        cur.execute(sql, params)
21        data = list(cur.fetchall())
22        desc = cur.description
23    except Exception, e:
24        env.log.exception('There was a problem executing sql:%s \n \
25with parameters:%s\nException:%s'%(sql, params, e));
26   
27    return (desc, data)
28
29def execute_non_query(env, sql, *params):
30    """Executes the query on the given project"""
31    execute_in_trans(env, (sql, params))
32   
33def get_first_row(env, sql,*params):
34    """ Returns the first row of the query results as a tuple of values (or None)"""
35    db = env.get_read_db()
36    cur = db.cursor()
37    data = None;
38    try:
39        cur.execute(sql, params)
40        data = cur.fetchone();
41    except Exception, e:
42        env.log.exception('There was a problem executing sql:%s \n \
43        with parameters:%s\nException:%s'%(sql, params, e));
44    return data;
45
46def get_scalar(env, sql, col=0, *params):
47    """ Gets a single value (in the specified column) from the result set of the query"""
48    data = get_first_row(env, sql, *params);
49    if data:
50        return data[col]
51    else:
52        return None;
53
54def execute_in_trans(env, *args):
55    result = True
56    c_sql =[None]
57    c_params = [None]
58    try:
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)
66    except Exception, e :
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));
69        raise e
70    return result
71
72def execute_in_nested_trans(env, name, *args):
73    result = True
74    c_sql =[None]
75    c_params = [None]
76    @env.with_transaction()
77    def fn(db):
78        cur = None
79        try:
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)
87        except Exception, e :
88            cur.execute("ROLLBACK TO SAVEPOINT %s" % name)
89            env.log.exception('There was a problem executing sql:%s \n \
90    with parameters:%s\nException:%s'%(c_sql[0], c_params[0], e));
91            raise e
92    return result
93
94def current_schema (env):
95    db = env.get_read_db()
96    if is_db_type(db, trac.db.sqlite_backend.SQLiteConnection):
97        return None
98    elif is_db_type(db, trac.db.mysql_backend.MySQLConnection):
99        return get_scalar(env, 'SELECT schema();')
100    elif is_db_type(db, trac.db.postgres_backend.PostgreSQLConnection):
101        return get_scalar(env, 'SHOW search_path;')
102
103def _prep_schema(s):
104    #remove double quotes, escape single quotes
105    if not s: return "'<NOT VALID>'"
106    return ','.join(("'"+i.replace('"','').replace("'","''")+"'"
107                     for i in s.split(',')))
108
109def db_table_exists(env,  table):
110    db = env.get_read_db()
111    cnt = None
112    if is_db_type(db, trac.db.sqlite_backend.SQLiteConnection):
113        sql = "select count(*) from sqlite_master where type = 'table' and name = %s"
114        cnt = get_scalar(env, sql, 0, table)
115    else:
116        sql = """SELECT count(*) FROM information_schema.tables
117                 WHERE table_name = %%s and table_schema in (%s)
118              """ % _prep_schema(current_schema(env))
119        cnt = get_scalar(env, sql, 0, table)
120    return cnt > 0
121
122def get_column_as_list(env, sql, col=0, *params):
123    data = get_all(env, sql, *params)[1] or ()
124    return [valueList[col] for valueList in data]
125
126def get_system_value(env, key):
127    return get_scalar(env, "SELECT value FROM system WHERE name=%s", 0, key)
128
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)       
132    else:
133        execute_non_query(env, "INSERT INTO system (value, name) VALUES (%s, %s)",
134            value, key)
135
136
137def get_result_set(env, sql, *params):
138    """Executes the query and returns a Result Set"""
139    tpl = get_all(env, sql, *params);
140    if tpl and tpl[0] and tpl[1]:
141        return ResultSet(tpl)
142    else:
143        return None
144
145
146class ResultSet:
147    """ the result of calling getResultSet """
148    def __init__ (self, (columnDescription, rows)):
149        self.columnDescription, self.rows = columnDescription, rows
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;
162   
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)))
183   
184    def json_out(self):
185        json = "[%s]" % ',\r\n'. join(
186            [("{%s}" % ','.join(
187            ["'%s':'%s'" %
188             (key, unicode(self.value(val, row)).
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.