|
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))
|