import ctypes
import csv
from csv import DictReader
import io
import tempfile
import time
class DictReader:
def get_column_types(self):
types = []
for column in self.columns:
name = column.split("(")[0]
type = column.split("(")[1]
type = type.split(")")[0]
if type == "integer":
types.append(int)
if type == "text":
types.append(str)
return types
def get_column_names(self):
names = []
for column in self.columns:
name = column.split("(")[0]
names.append(name)
return names
def __init__(self, data):
self.result = 0
if type(data) == int:
self.data = ""
else:
self.data = data.decode()
self.rows = [row.split(";")[:-1] for row in self.data.split("\n")]
self.columns = self.rows[0]
self.rows.pop(0)
if type(data) == str:
self.result = len(self.rows)
else:
self.result = data
self.column_types = self.get_column_types()
for row in self.rows:
for index, field in enumerate(row):
row[index] = self.column_types[index](field)
self.column_names = self.get_column_names()
def __iter__(self):
return self.rows.__iter__()
libc = ctypes.CDLL("libc.so.6")
class Sorm:
def __init__(self):
self.lib = ctypes.CDLL("./sorm.so")
self.sormq = self.lib.sormq
self.sormq.argtypes = [ctypes.c_int, ctypes.c_char_p]
self.sormq.restype = ctypes.c_char_p
self.sormc = self.lib.sormc
self.sormc.argtypes = [ctypes.c_char_p]
self.sormc.restype = ctypes.c_int
self.sormd = self.lib.sormd
self.sormd.argtypes = [ctypes.c_int]
self.sormd.restype = None
self.sormm = self.lib.sormm
self.sormm.argtypes = [ctypes.c_int]
self.sormm.restype = ctypes.c_char_p
class SormDb(Sorm):
def __init__(self, path):
super().__init__()
self.path = path
self.conn = None
def c(self):
if not self.conn:
self.conn = self.sormc(self.path.encode())
return self.conn
def __enter__(self):
self.c()
return self
def __exit__(self, *args, **kwargs):
self.d()
def q(self, sql, *args) -> DictReader:
ctypes_list = []
for arg in args:
if type(arg) == int:
ctypes_list.append(ctypes.c_int)
if type(arg) == str:
ctypes_list.append(ctypes.c_char_p)
self.sormq.argtypes = [ctypes.c_int, ctypes.c_char_p] + ctypes_list
if not sql.lower().startswith("select"):
self.sormq.restype = ctypes.c_int
else:
self.sormq.restype = ctypes.c_char_p
params = tuple(
[self.conn, sql.encode()]
+ list(arg.encode() if type(arg) == str else arg for arg in args)
)
result = DictReader(self.sormq(*params))
self.m = self.sormm(self.conn).decode()
return result
def d(self):
if not self.conn:
return
self.sormd(self.conn)
self.conn = None
# Load the shared library
lib = ctypes.CDLL("./sorm.so")
free = libc.free
free.argtypes = [ctypes.c_void_p]
free.restype = None
rsomm = lib.sormm
rsomm.argtypes = [ctypes.c_int]
rsomm.restype = ctypes.c_char_p
disconnect = lib.sormd
disconnect.argtypes = [ctypes.c_int]
start = time.time()
for x in range(1):
with SormDb("db.sqlite3") as db:
for x in range(1):
# db.q("BEGIN TRANSACTION")
# for x in range(100000):
# db.q("INSERT INTO pony (name,age) VALUES (?s,?d);","Python Pony",1337)
# db.q("COMMIT")
result = db.q(
"SELECT * FROM pony WHERE id > ?d AND name like ?s ORDER BY id",
1337,
"%hon Pon%",
)
# for row in result:
# print(row)
print(result.column_names)
print(len(result.rows), "records")
print(db.m)
end = time.time()
duration = end - start
print("Duration: {}s".format(duration))