sorm/sorm.py

162 lines
4.2 KiB
Python
Raw Normal View History

2024-11-22 13:45:03 +00:00
import ctypes
2024-11-22 14:51:47 +00:00
import csv
2024-11-22 13:45:03 +00:00
from csv import DictReader
import io
2024-11-22 14:51:47 +00:00
import tempfile
2024-11-22 13:45:03 +00:00
import time
2024-11-22 14:51:47 +00:00
2024-11-22 13:45:03 +00:00
class DictReader:
def get_column_types(self):
2024-11-22 14:51:47 +00:00
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
2024-11-22 13:45:03 +00:00
def get_column_names(self):
names = []
for column in self.columns:
name = column.split("(")[0]
names.append(name)
return names
2024-11-22 14:51:47 +00:00
2024-11-22 13:45:03 +00:00
def __init__(self, data):
self.result = 0
if type(data) == int:
2024-11-22 14:51:47 +00:00
self.data = ""
2024-11-22 13:45:03 +00:00
else:
2024-11-22 14:51:47 +00:00
self.data = data.decode()
2024-11-22 13:45:03 +00:00
self.rows = [row.split(";")[:-1] for row in self.data.split("\n")]
2024-11-22 14:51:47 +00:00
2024-11-22 13:45:03 +00:00
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:
2024-11-22 14:51:47 +00:00
for index, field in enumerate(row):
2024-11-22 13:45:03 +00:00
row[index] = self.column_types[index](field)
self.column_names = self.get_column_names()
def __iter__(self):
return self.rows.__iter__()
2024-11-22 14:51:47 +00:00
libc = ctypes.CDLL("libc.so.6")
2024-11-22 13:45:03 +00:00
class Sorm:
2024-11-22 14:51:47 +00:00
2024-11-22 13:45:03 +00:00
def __init__(self):
2024-11-22 14:51:47 +00:00
self.lib = ctypes.CDLL("./sorm.so")
2024-11-22 13:45:03 +00:00
self.sormq = self.lib.sormq
2024-11-22 14:51:47 +00:00
self.sormq.argtypes = [ctypes.c_int, ctypes.c_char_p]
2024-11-22 13:45:03 +00:00
self.sormq.restype = ctypes.c_char_p
self.sormc = self.lib.sormc
2024-11-22 14:51:47 +00:00
self.sormc.argtypes = [ctypes.c_char_p]
self.sormc.restype = ctypes.c_int
2024-11-22 13:45:03 +00:00
self.sormd = self.lib.sormd
2024-11-22 14:51:47 +00:00
self.sormd.argtypes = [ctypes.c_int]
2024-11-22 13:45:03 +00:00
self.sormd.restype = None
self.sormm = self.lib.sormm
2024-11-22 14:51:47 +00:00
self.sormm.argtypes = [ctypes.c_int]
2024-11-22 13:45:03 +00:00
self.sormm.restype = ctypes.c_char_p
2024-11-22 14:51:47 +00:00
2024-11-22 13:45:03 +00:00
class SormDb(Sorm):
2024-11-22 14:51:47 +00:00
def __init__(self, path):
super().__init__()
2024-11-22 13:45:03 +00:00
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
2024-11-22 14:51:47 +00:00
def __exit__(self, *args, **kwargs):
2024-11-22 13:45:03 +00:00
self.d()
2024-11-22 14:51:47 +00:00
def q(self, sql, *args) -> DictReader:
2024-11-22 13:45:03 +00:00
ctypes_list = []
2024-11-22 14:51:47 +00:00
for arg in args:
2024-11-22 13:45:03 +00:00
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
2024-11-22 14:51:47 +00:00
params = tuple(
[self.conn, sql.encode()]
+ list(arg.encode() if type(arg) == str else arg for arg in args)
)
2024-11-22 13:45:03 +00:00
result = DictReader(self.sormq(*params))
self.m = self.sormm(self.conn).decode()
return result
2024-11-22 14:51:47 +00:00
2024-11-22 13:45:03 +00:00
def d(self):
if not self.conn:
return
self.sormd(self.conn)
2024-11-22 14:51:47 +00:00
self.conn = None
2024-11-22 13:45:03 +00:00
# Load the shared library
2024-11-22 14:51:47 +00:00
lib = ctypes.CDLL("./sorm.so")
2024-11-22 13:45:03 +00:00
free = libc.free
free.argtypes = [ctypes.c_void_p]
free.restype = None
rsomm = lib.sormm
2024-11-22 14:51:47 +00:00
rsomm.argtypes = [ctypes.c_int]
rsomm.restype = ctypes.c_char_p
2024-11-22 13:45:03 +00:00
disconnect = lib.sormd
2024-11-22 14:51:47 +00:00
disconnect.argtypes = [ctypes.c_int]
2024-11-22 13:45:03 +00:00
start = time.time()
for x in range(1):
2024-11-22 14:51:47 +00:00
2024-11-22 13:45:03 +00:00
with SormDb("db.sqlite3") as db:
for x in range(1):
2024-11-22 14:51:47 +00:00
# db.q("BEGIN TRANSACTION")
# for x in range(100000):
2024-11-22 13:45:03 +00:00
# db.q("INSERT INTO pony (name,age) VALUES (?s,?d);","Python Pony",1337)
2024-11-22 14:51:47 +00:00
# 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:
2024-11-22 13:45:03 +00:00
# print(row)
print(result.column_names)
2024-11-22 14:51:47 +00:00
print(len(result.rows), "records")
print(db.m)
2024-11-22 13:45:03 +00:00
end = time.time()
duration = end - start
print("Duration: {}s".format(duration))