In my project I have lots of functions that carry out SQL queries. These queries include SELECT, UPDATE, INSERT etc... When writing functions for SELECT queries for example, I write the same structure of code in every single function. e.g.
def generic_select_function(self):
result = self.cursor.execute("""
SQL CODE
""")
return result.fetchall()
To avoid repeating this code over and over I though I could create a wrapper function that inserts the SQL code into a template for SELECT queries.
I understand that a wrapper function may not even be necessary for this but I would like to try and implement one to develop my understanding of them.
What I have tried:
class DatabaseManagment():
def __init__(self) -> None:
self.con = sqlite3.connect("...")
self.cursor = self.con.cursor()
self.lock = threading.Lock()
def sql_select(self):
def inner(func):
result = self.cursor.execute(f"""
{func}
""")
return result.fetchall()
return inner
@sql_select
def test(self):
return "SELECT * FROM App_price"
'function' object has no attribute 'cursor'
Here an example of wrapper using inheritance:
class MyQueries:
@staticmethod
def App_price():
return "SELECT * FROM App_price"
class MyQueriesExe(MyQueries):
def select(self, func):
return f"{self.con} executing: {func()}"
def __init__(self):
self.con = 'con id: xxx:'
def App_price(self):
return self.select(super().App_price)
print(MyQueriesExe().App_price())
#con id: xxx: executing: SELECT * FROM App_price
Here a very basic example with a metaclass-decoration to illustrate the basic syntax
import sqlite3
class SqlQueriesExe(type):
def __new__(mcs, name:str, bases:tuple, class_dict:dict) -> type:
cls = super().__new__(mcs, name, bases, class_dict)
# decoration phase
for method_name in ('create_table', 'insert_into_table', 'show_table'):
app_price = getattr(cls, method_name)
setattr(cls, app_price.__name__, mcs.executer(app_price))
return cls
@staticmethod
def executer(func):
return lambda self, *args: self.con.execute(func(self, *args))
return lambda self, *args: self.con.executescript(func(self, *args))
class Db(metaclass=SqlQueriesExe):
def __str__(self):
# sqlite3.sqlite_version
# some db-info for ex pragma-stuffs
return str(self)
def __init__(self, database=":memory:"):
self.database = database
def __enter__(self):
self.con = sqlite3.connect(self.database)
self.cursor = self.con.cursor()
return self
def __exit__(self, exc_type, exc_value, exc_tb):
print('db-self.database is closing.')
# display table when closing
print(*self.show_table())
#self.con.rollback() # self.con.commit()
self.con.close()
def create_table(self):
return """CREATE TABLE IF NOT EXISTS test_table (A TEXT);"""
def insert_into_table(self):
return """INSERT INTO test_table (A) VALUES (2);"""
def show_table(self):
return """SELECT * FROM test_table;"""
with Db(":memory:") as db:
db.create_table()
db.insert_into_table()