I'd like to wrap all my sqlite statement functions with a decorator which collects the statement and the lists of values I will inject in place of placeholders in my statement (to avoid sql injection). Code looks like this:
#decorator def dbexecute(func): def withcon(*args): conn = sqlite3.connect(sqlite_file_name) conn.row_factory = sqlite3.Row with conn: fa = func(*args) if isinstance(fa, tuple): s, v = fa else: s, v = fa, () out = conn.execute(s, v).fetchall() conn.close() return out return withcon #statement functions that are decorated @dbexecute def create_user(user_settings: dict): user_settings['id'] = str(uuid.uuid4()) columns = tuple([key for (key,value) in user_settings.items()]) values = tuple([value for (key,value) in user_settings.items()]) qmarks = tuple(['?']*len(values)) statement = f"INSERT INTO users {columns} VALUES {qmarks}".replace("'","") return statement, values @dbexecute def get_all_users(): statement = "SELECT * FROM users" return statement
First function returns values to replace the question marks with, but the second not. I had to handle this directly in the decorator, but I am not sure this is the good way to do it or maybe there is a more pythonic way than an if...else... block that checks the type of the inputs args.
Thanks for your feedback!