Revision 1894
Added by Aaron Marcuse-Kubitza over 12 years ago
lib/sql.py | ||
---|---|---|
75 | 75 |
def db_config_str(db_config): |
76 | 76 |
return db_config['engine']+' database '+db_config['database'] |
77 | 77 |
|
78 |
def _query_lookup(query, params): return (query, util.cast(tuple, params)) |
|
79 |
|
|
78 | 80 |
class DbConn: |
79 | 81 |
def __init__(self, db_config, serializable=True, debug=False): |
80 | 82 |
self.db_config = db_config |
... | ... | |
120 | 122 |
def __init__(self, outer): |
121 | 123 |
Proxy.__init__(self, outer.db.cursor()) |
122 | 124 |
self.outer = outer |
125 |
self.query_lookup = None |
|
123 | 126 |
self.result = [] |
124 | 127 |
|
128 |
def execute(self, query, params=None): |
|
129 |
self.query_lookup = _query_lookup(query, params) |
|
130 |
return_value = self.inner.execute(query, params) |
|
131 |
self.query = get_cur_query(self.inner) |
|
132 |
return return_value |
|
133 |
|
|
125 | 134 |
def fetchone(self): |
126 | 135 |
row = self.inner.fetchone() |
127 | 136 |
if row == None: # fetched all rows |
128 |
self.outer.query_results[self.inner.query] = self.result |
|
137 |
assert self.query_lookup != None |
|
138 |
pass #self.outer.query_results[self.query_lookup] = (self.query, |
|
139 |
#self.result) |
|
129 | 140 |
else: self.result.append(row) |
130 | 141 |
return row |
131 | 142 |
|
132 | 143 |
class CacheCursor: |
133 |
def __init__(self, result): self.iter = iter(result) |
|
144 |
def __init__(self, query, result): |
|
145 |
self.query = query |
|
146 |
self.rowcount = len(result) |
|
147 |
self.iter = iter(result) |
|
134 | 148 |
|
135 | 149 |
def fetchone(self): |
136 | 150 |
try: return self.iter.next() |
137 | 151 |
except StopIteration: return None |
138 | 152 |
|
139 |
def run_query(self, query, params=None): |
|
140 |
cur = self.DbCursor(self) |
|
141 |
query = cur.mogrify(query, params) |
|
142 |
try: return self.CacheCursor(self.query_results[query]) |
|
153 |
def run_query(self, query, params=None, cacheable=False): |
|
154 |
query_lookup = _query_lookup(query, params) |
|
155 |
try: actual_query, result = self.query_results[query_lookup] |
|
143 | 156 |
except KeyError: |
144 |
try: cur.execute(query) |
|
157 |
cur = self.DbCursor(self) |
|
158 |
try: cur.execute(query, params) |
|
145 | 159 |
except Exception, e: |
146 | 160 |
_add_cursor_info(e, cur) |
147 | 161 |
raise |
148 | 162 |
if self.debug: |
149 | 163 |
sys.stderr.write(strings.one_line(get_cur_query(cur))+'\n') |
150 | 164 |
return cur |
165 |
else: return self.CacheCursor(actual_query, result) |
|
151 | 166 |
|
152 | 167 |
connect = DbConn |
153 | 168 |
|
154 | 169 |
##### Querying |
155 | 170 |
|
156 |
def run_raw_query(db, query, params=None): return db.run_query(query, params) |
|
171 |
def run_raw_query(db, *args, **kw_args): |
|
172 |
'''For args, see DbConn.run_query()''' |
|
173 |
return db.run_query(*args, **kw_args) |
|
157 | 174 |
|
158 | 175 |
##### Recoverable querying |
159 | 176 |
|
... | ... | |
168 | 185 |
run_raw_query(db, 'RELEASE SAVEPOINT '+savepoint) |
169 | 186 |
return return_val |
170 | 187 |
|
171 |
def run_query(db, query, params=None, recover=None): |
|
188 |
def run_query(db, query, params=None, recover=None, cacheable=False):
|
|
172 | 189 |
if recover == None: recover = False |
173 | 190 |
|
174 |
def run(): return run_raw_query(db, query, params) |
|
191 |
def run(): return run_raw_query(db, query, params, cacheable)
|
|
175 | 192 |
if recover: return with_savepoint(db, run) |
176 | 193 |
else: return run() |
177 | 194 |
|
... | ... | |
202 | 219 |
##### Basic queries |
203 | 220 |
|
204 | 221 |
def select(db, table, fields=None, conds=None, limit=None, start=None, |
205 |
recover=None): |
|
222 |
recover=None, cacheable=True):
|
|
206 | 223 |
'''@param fields Use None to select all fields in the table''' |
207 | 224 |
if conds == None: conds = {} |
208 | 225 |
assert limit == None or type(limit) == int |
... | ... | |
234 | 251 |
if missing: warnings.warn(DbWarning( |
235 | 252 |
'SELECT statement missing a WHERE, LIMIT, or OFFSET clause: '+query)) |
236 | 253 |
|
237 |
return run_query(db, query, conds.values(), recover) |
|
254 |
return run_query(db, query, conds.values(), cacheable, recover)
|
|
238 | 255 |
|
239 | 256 |
def insert(db, table, row, returning=None, recover=None): |
240 | 257 |
'''@param returning str|None An inserted column (such as pkey) to return''' |
Also available in: Unified diff
run_*query(): Fixed bug where INSERTs, etc. were cached by making callers (such as select()) explicitly turn on caching. DbConn.run_query(): Fixed bug where cur.mogrify() was not supported under MySQL by making the cache key a tuple of the unmogrified query and its params instead of the mogrified string query. CacheCursor: Store attributes of the original cursor that we use, such as query and rowcount.