78
78
raise DBException("Attempt to insert an unsupported type "
79
79
"into the database (%s)" % repr(type(val)))
81
def _parse_boolean(val):
83
Accepts a boolean as output from the DB (either the string 't' or 'f').
84
Returns a boolean value True or False.
85
Also accepts other values which mean True or False in PostgreSQL.
86
If none match, raises a DBException.
88
# On a personal note, what sort of a language allows 7 different values
89
# to denote each of True and False?? (A: SQL)
90
if isinstance(val, bool):
96
elif val == 'true' or val == 'y' or val == 'yes' or val == '1' \
99
elif val == 'false' or val == 'n' or val == 'no' or val == '0' \
103
raise DBException("Invalid boolean value returned from DB")
105
81
class DBException(Exception):
106
82
"""A DBException is for bad conditions in the database or bad input to
107
83
these methods. If Postgres throws an exception it does not get rebadged.
185
161
if dry: return query
186
162
self.db.query(query)
188
def return_insert(self, dict, tablename, tablefields, returning,
189
disallowed=frozenset([]), dry=False):
190
"""Inserts a new row in a table, using data from a supplied
191
dictionary (which will be checked by check_dict) and returns certain
193
dict: Dictionary mapping column names to values. The values may be
194
any of the following types:
195
str, int, long, float, NoneType.
196
tablename: String, name of the table to insert into. Will NOT be
197
escaped - must be a valid identifier.
198
returning: List of fields to return, not escaped
199
tablefields, disallowed: see check_dict.
200
dry: Returns the SQL query as a string, and does not execute it.
201
Raises a DBException if the dictionary contains invalid fields.
203
if not DB.check_dict(dict, tablefields, disallowed):
204
extras = set(dict.keys()) - tablefields
205
raise DBException("Supplied dictionary contains invalid fields. (%s)" % (repr(extras)))
206
# Build two lists concurrently: field names and values, as SQL strings
209
for k,v in dict.items():
211
values.append(_escape(v))
212
if len(fieldnames) == 0: return
213
fieldnames = ', '.join(fieldnames)
214
values = ', '.join(values)
215
returns = ', '.join(returning)
216
query = ("INSERT INTO %s (%s) VALUES (%s) RETURNING (%s);"
217
% (tablename, fieldnames, values, returns))
219
return self.db.query(query)
222
164
def update(self, primarydict, updatedict, tablename, tablefields,
223
165
primary_keys, disallowed_update=frozenset([]), dry=False):
224
166
"""Updates a row in a table, matching against primarydict to find the
292
234
# Return as a dictionary
293
235
return result.dictresult()[0]
295
def start_transaction(self, dry=False):
296
"""Starts a DB transaction.
297
Will not commit any changes until self.commit() is called.
299
query = "START TRANSACTION;"
303
def commit(self, dry=False):
304
"""Commits (ends) a DB transaction.
305
Commits all changes since the call to start_transaction.
311
def rollback(self, dry=False):
312
"""Rolls back (ends) a DB transaction, undoing all changes since the
313
call to start_transaction.
319
237
# PROBLEM AND PROBLEM ATTEMPT FUNCTIONS #
321
239
def get_problem_problemid(self, exercisename, dry=False):