Compare commits

..
21 Commits
Author SHA1 Message Date
retoor b6ac734183 fix: suppress unused parameter warnings and remove dead code in cli and main
SORM tests / Compile (push) Successful in 6s
SORM build / build (push) Successful in 19s
2024-12-08 19:27:05 +00:00
retoor 985b469af4 chore: remove debug console.log statements from user authentication flow 2024-12-08 18:59:58 +00:00
retoor 60f98fdec7 chore: strip debug print statements and dead csv cleanup code from sormc and sormq 2024-12-08 18:58:50 +00:00
retoor 5565dd7e81 feat: add rlib.h header with 8.4k lines of core utility macros, type definitions, and MIT license boilerplate 2024-12-02 13:21:44 +00:00
retoor e28a87af74 fix: replace broken curl download with local cp for rlib.h in build workflow 2024-12-02 13:21:11 +00:00
retoor dbe70775d5 chore: add rlib.h download step before build in build.yaml workflow 2024-12-02 13:18:12 +00:00
retoor fc73c4221b feat: add rlib.h dependency and update includes to local path for runtime library support 2024-11-28 22:28:33 +00:00
retoor 0dfeef5d9d chore: fix trailing quote typo in build workflow echo command 2024-11-22 15:31:46 +00:00
retoor 228163c92d chore: fix apt-get command syntax in build workflow by removing extraneous 'get' 2024-11-22 15:30:38 +00:00
retoor 9f2941859d chore: replace named steps with echo placeholders in CI build workflow 2024-11-22 15:30:01 +00:00
retoor faa3749681 chore: add gitea ci workflow with build steps for sorm project 2024-11-22 15:27:37 +00:00
retoor d473276fd8 chore: remove trailing whitespace and reorder includes in cli.h, main.c, sorm.h, sorm.py, str.h 2024-11-22 14:51:47 +00:00
retoor 625e78ba79 docs: clarify C standard compatibility and fix punctuation in README dependencies section 2024-11-22 13:57:47 +00:00
retoor f54e36bdd8 docs: add building requirements and thread safety sections to readme
The README now includes a new "Building" section with build command and dependency list, and moves the "Thread safety" section after "Design choices" for better logical flow. The caution about missing rlib.h has been removed.
2024-11-22 13:56:40 +00:00
retoor f3a3dfef9e docs: add caution note about missing rlib.h dependency and future plans 2024-11-22 13:51:55 +00:00
retoor 01415a8fe9 feat: add Gitea workflow for automated SORM tests on push events
- Created .gitea/workflows/test.yaml with a Compile job running on ubuntu-latest
- Configured workflow to trigger on push events with echo steps for event, branch, and repository info
- Added checkout action and file listing step using gitea workspace variable
2024-11-22 13:45:03 +00:00
retoor b9e687ebdb chore: fix grammar and phrasing errors in README documentation files 2024-11-22 13:45:03 +00:00
retoor 1da30958d1 docs: fix formatting of code literals and casing in README examples 2024-11-22 13:45:03 +00:00
retoor f81ad80fa6 docs: add language identifier to C code blocks in README examples 2024-11-22 13:45:03 +00:00
retoor e58479ccd1 docs: add comprehensive project overview, setup instructions, and C/Python API examples to README
The README now includes a full project description explaining the SORM (SQL ORM) philosophy, thread safety considerations, design choices favoring native types for cross-language compatibility, and detailed C API examples covering connection, table creation, and query execution. Also adds Python support documentation with variadic function calling patterns through ctypes.
2024-11-22 13:45:03 +00:00
retoor 0f0657496b feat: add initial project scaffold with clang-format, gitignore, Makefile, core C headers, main entry, Python bindings, and dynamic library build 2024-11-22 13:45:03 +00:00
11 changed files with 8908 additions and 491 deletions
+21
View File
@@ -0,0 +1,21 @@
name: SORM build
run-name: Build 🚀
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: echo "Update apt repository"
- run: apt update
- run: echo "Installing dependencies"
- run: apt install build-essential sqlite3 libsqlite3-dev libreadline-dev libpython3-dev make -y
- name: Check out repository code
uses: actions/checkout@v4
- name: List files in the repository
run: |
ls ${{ gitea.workspace }}
- run: cp rlib.h /usr/include/
- run: echo "Build project (misses rlib.h)"
- run: make build
- run: echo "This job's status is ${{ job.status }}."
+3 -2
View File
@@ -1,9 +1,10 @@
all: build run all: build run
build: build:
gcc main.c -lsqlite3 -lreadline -o sorm gcc main.c -Wextra -Wall -lsqlite3 -lreadline -o sorm
gcc -shared -o sorm.so -fPIC main.c -lsqlite3 -lreadline gcc -shared -o sorm.so -fPIC main.c -lsqlite3 -lreadline
run: run:
./sorm ./sorm
+27 -3
View File
@@ -1,5 +1,9 @@
# SORM # SORM
## Todo
- auto complete table / view names.
## Description ## Description
SORM stands for SQL ORM. I made this because I have a love/hate relationship with both. I combined them together to have the best of both worlds! SORM stands for SQL ORM. I made this because I have a love/hate relationship with both. I combined them together to have the best of both worlds!
@@ -10,14 +14,34 @@ Examples of common used functions are:
- `sormq(int conn, char *sql, ...)` execute query. Variadic arguments. Works like `printf`. Returns result in CSV format in case of `SELECT`. - `sormq(int conn, char *sql, ...)` execute query. Variadic arguments. Works like `printf`. Returns result in CSV format in case of `SELECT`.
- `sorm_csvd(char *csv_data)` dumps your CSV result data to a nice fixed content width table in the terminal. - `sorm_csvd(char *csv_data)` dumps your CSV result data to a nice fixed content width table in the terminal.
## Thread safety
I wonder if I have configured sqlite3 the right way for thread safety. It maybe requires a manual compilation of the shared object file. Will look into that. SORM is written with thread safety in mind.
## Design choices ## Design choices
I use mainly native types and not custom structs. For example, the db parameter is an int. This is so it can easily communicate with other languages using a shared object file. I use mainly native types and not custom structs. For example, the db parameter is an int. This is so it can easily communicate with other languages using a shared object file.
Same argument is for the result set of `sormq` (the query function) resulting in a `char *` containing CSV data. Same argument is for the result set of `sormq` (the query function) resulting in a `char *` containing CSV data.
While the performance is nice, it's not written with performance in mind at all. While the performance is nice, it's not written with performance in mind at all.
## Thread safety
I wonder if I have configured sqlite3 the right way for thread safety. It maybe requires a manual compilation of the shared object file. Will look into that. SORM is written with thread safety in mind.
## Building
It has only one build command for the shared object file and the REPL/CLI.
It has not been compiled with optimizations / warnings enabled. Don't recommend for now.
```bash
make build
```
### Requirements
This project has the following dependencies:
- sqlite3-dev (`apt install sqlite3-dev`)
- readline(-dev?) (no idea how to install)
- gcc
- make
The project probably works from C99 to C2X.
### Caution
This project won't compile on your local PC because `rlib.h` is missing. This is my bundle of libraries that I regularely use. I will add this later as 3rd party lib. Maybe I will cherry pick only the functions that SORM uses out of it to keep the source clean, else I will have thousands of lines nothing to do with this project in the source.
## Python support ## Python support
The Python library is low quality. I made it just for fun and test. This is not a defitive version. But it show very well how to communicate with a shared object file. I'm sure someone will be happy with examples how to use variadic functions trough Python to C. See `sorm.py` The Python library is low quality. I made it just for fun and test. This is not a defitive version. But it show very well how to communicate with a shared object file. I'm sure someone will be happy with examples how to use variadic functions trough Python to C. See `sorm.py`
+16 -32
View File
@@ -1,19 +1,21 @@
#ifndef SORM_CLI_H #ifndef SORM_CLI_H
#define SORM_CLI_H #define SORM_CLI_H
#include "sorm.h"
#include <fcntl.h>
#include <readline/history.h>
#include <readline/readline.h>
#include <rlib.h> #include <rlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <readline/readline.h> #include <unistd.h>
#include <readline/history.h>
#include "sorm.h"
const char *history_filename = ".sorm_history"; const char *history_filename = ".sorm_history";
int _sorm_readline_accept_line(int count, int key) { int _sorm_readline_accept_line(int count, int key) {
(void)count;
(void)key;
if (strchr(rl_line_buffer, ';')) { if (strchr(rl_line_buffer, ';')) {
rl_done = 1; rl_done = 1;
@@ -24,16 +26,7 @@ const char * history_filename = ".sorm_history";
} }
char *_sorm_autocompletion_generator(const char *text, int state) { char *_sorm_autocompletion_generator(const char *text, int state) {
const char* completions[] = { const char *completions[] = {"exit", sorm_last_query, sorm_last_query_expanded, "python", "history", "memory", "truncate", NULL};
"exit",
sorm_last_query,
sorm_last_query_expanded,
"python",
"history",
"memory",
"truncate",
NULL
};
int list_index; int list_index;
if (!state) { if (!state) {
@@ -51,15 +44,13 @@ char* _sorm_autocompletion_generator(const char* text, int state) {
} }
char **_sorm_autocomplete(const char *text, int start, int end) { char **_sorm_autocomplete(const char *text, int start, int end) {
(void)start;
(void)end;
rl_attempted_completion_over = 1; rl_attempted_completion_over = 1;
return rl_completion_matches(text, _sorm_autocompletion_generator); return rl_completion_matches(text, _sorm_autocompletion_generator);
} }
int _hs_read_file(const char *filename, char *buffer, size_t size) {
int
_hs_read_file (const char *filename, char *buffer, size_t size)
{
int fd; int fd;
ssize_t bytes_read; ssize_t bytes_read;
@@ -77,10 +68,7 @@ _hs_read_file (const char *filename, char *buffer, size_t size)
return 0; return 0;
} }
int sorm_cli_history_dump(const char *filename) {
int
sorm_cli_history_dump (const char *filename)
{
register int line_start, line_end; register int line_start, line_end;
char *input; char *input;
struct stat finfo; struct stat finfo;
@@ -100,7 +88,7 @@ sorm_cli_history_dump (const char *filename)
} }
input[file_size] = '\0'; input[file_size] = '\0';
for (line_start = line_end = 0; line_end < file_size; line_end++) { for (line_start = line_end = 0; (size_t)line_end < file_size; line_end++) {
if (input[line_end] == '\n') { if (input[line_end] == '\n') {
input[line_end] = '\0'; input[line_end] = '\0';
@@ -110,7 +98,7 @@ sorm_cli_history_dump (const char *filename)
} }
} }
if (line_start < file_size) if ((size_t)line_start < file_size)
printf("%s\n", input + line_start); printf("%s\n", input + line_start);
free(input); free(input);
@@ -147,7 +135,6 @@ char * sorm_cli_readline(char * prompt){
return result; return result;
} }
bool sormrepl_handle_command(char *command) { bool sormrepl_handle_command(char *command) {
if (!strncmp(command, "history", 7)) { if (!strncmp(command, "history", 7)) {
sorm_cli_history_dump(history_filename); sorm_cli_history_dump(history_filename);
@@ -156,9 +143,6 @@ bool sormrepl_handle_command(char * command){
return false; return false;
} }
void sormrepl(int sorm) { void sormrepl(int sorm) {
sorm_t * db = sormg(sorm);
char sql[4097];
sorm_cli_init(history_filename); sorm_cli_init(history_filename);
char *query; char *query;
while ((query = sorm_cli_readline("sql> "))) { while ((query = sorm_cli_readline("sql> "))) {
@@ -167,7 +151,6 @@ void sormrepl(int sorm){
sorm_ptr res = sormq(sorm, query); sorm_ptr res = sormq(sorm, query);
if (res) { if (res) {
if (sormqt(query) == SORM_SELECT) { if (sormqt(query) == SORM_SELECT) {
int length = sormlv(res);
sormfmtd(res); sormfmtd(res);
free(res); free(res);
} else if (sormqt(query) == SORM_DELETE) { } else if (sormqt(query) == SORM_DELETE) {
@@ -177,7 +160,8 @@ void sormrepl(int sorm){
} }
} }
printf("Rows: %lld, Execute %s, Format: %s\n",sorm_row_count, format_time(_sorm_query_duration),format_time(_sorm_result_format_duration)); printf("Rows: %lld, Execute %s, Format: %s\n", sorm_row_count, format_time(_sorm_query_duration),
format_time(_sorm_result_format_duration));
printf("%s\n", rmalloc_stats()); printf("%s\n", rmalloc_stats());
} }
} }
+7 -22
View File
@@ -1,31 +1,16 @@
#include "sorm.h"
#include "cli.h" #include "cli.h"
#include "sorm.h"
int main() { int main() {
int db = sormc("db.sqlite3"); int db = sormc("db.sqlite3");
// sormq(db,"DROP TABLE IF EXISTS pony;"); // sormq(db,"DROP TABLE IF EXISTS pony;");
printf("%d\n",db);
sormq(db, "CREATE TABLE IF NOT EXISTS pony (id INTEGER PRIMARY KEY AUTOINCREMENT,name,age);", NULL); sormq(db, "CREATE TABLE IF NOT EXISTS pony (id INTEGER PRIMARY KEY AUTOINCREMENT,name,age);", NULL);
sorm_pk iid = sormq(db, "INSERT INTO pony (id,name,age) VALUES (NULL,%s,%d);", sormq(db, "INSERT INTO pony (id,name,age) VALUES (NULL,%s,%d);", "Teenii", 19);
"Teenii", sormq(db, "INSERT INTO pony (id,name,age) VALUES (NULL,%s,%d);", "Amber", 20);
19 sormq(db, "INSERT INTO pony (id,name,age) VALUES (NULL,%s,%d);", "Feuerherz", 20);
); sormq(db, "INSERT INTO pony (id,name,age) VALUES (NULL,%s,%d);", "Retoor", 34);
iid = sormq(db, "INSERT INTO pony (id,name,age) VALUES (NULL,%s,%d);", sorm_str csv2 = (sorm_str)sormq(db, "SELECT * FROM pony WHERE id = %d and age = %d ", 1, 33);
"Amber", sorm_str csv3 = (sorm_str)sormq(db, "SELECT * FROM pony LIMIT 2");
20
);
iid = sormq(db, "INSERT INTO pony (id,name,age) VALUES (NULL,%s,%d);",
"Feuerherz",
20
);
iid = sormq(db, "INSERT INTO pony (id,name,age) VALUES (NULL,%s,%d);",
"Retoor",
34
);
sorm_str csv = sormq(db, "SELECT * FROM pony WHERE id in (?i,?i,?i)",1,2,3);
sorm_str csv2 = sormq(db, "SELECT * FROM pony WHERE id = %d and age = %d ", 1,33);
sorm_str csv3 = sormq(db, "SELECT * FROM pony LIMIT 2");
// free(csv3); // free(csv3);
// free(csv2); // free(csv2);
if (csv2) if (csv2)
+8448
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
+23 -68
View File
@@ -1,19 +1,18 @@
#ifndef SORM_H #ifndef SORM_H
#define SORM_H #define SORM_H
#include <rlib.h> #include "str.h"
#include <ctype.h>
#include "rlib.h"
#include <sqlite3.h> #include <sqlite3.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdbool.h>
#include <stdarg.h>
#include <ctype.h>
#include "str.h"
sqlite3 *db; sqlite3 *db;
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
char *sorm_last_query = NULL; char *sorm_last_query = NULL;
char *sorm_last_query_expanded = NULL; char *sorm_last_query_expanded = NULL;
@@ -52,14 +51,11 @@ void sormd(int db);
char *sormpt(char *sql, int number); char *sormpt(char *sql, int number);
unsigned int sormcq(char *sql, char *out); unsigned int sormcq(char *sql, char *out);
unsigned int sormpc(char *sql); unsigned int sormpc(char *sql);
sqlite3_stmt * sormb(sorm_t* db, char * sql, ...);
sorm_ptr sormq(int db, char *sql, ...); sorm_ptr sormq(int db, char *sql, ...);
char *sorm_csvc(int db, sqlite3_stmt *stmt); char *sorm_csvc(int db, sqlite3_stmt *stmt);
char *sorm_csvd(int db, sqlite3_stmt *stmt); char *sorm_csvd(int db, sqlite3_stmt *stmt);
char *sorm_csv(int db, sqlite3_stmt *stmt); char *sorm_csv(int db, sqlite3_stmt *stmt);
typedef enum sorm_query_t { typedef enum sorm_query_t {
SORM_UNKNOWN = 0, SORM_UNKNOWN = 0,
SORM_SELECT = 1, SORM_SELECT = 1,
@@ -71,26 +67,19 @@ typedef enum sorm_query_t {
const int sorm_null = -1337; const int sorm_null = -1337;
sorm_t **sorm_instances = NULL; sorm_t **sorm_instances = NULL;
int sorm_instance_count = 0; int sorm_instance_count = 0;
int sormc(char *path) { int sormc(char *path) {
// sorm connect // sorm connect
printf("HIERR\n");
sorm_instance_count++; sorm_instance_count++;
sorm_instance_count++; sorm_instance_count++;
sorm_instances = realloc(sorm_instances, sorm_instance_count * sizeof(sorm_t *) + sorm_instance_count * sizeof(sorm_t)); sorm_instances = realloc(sorm_instances, sorm_instance_count * sizeof(sorm_t *) + sorm_instance_count * sizeof(sorm_t));
printf("HIERR\n"); sorm_t *db = (sorm_t *)&sorm_instances[sorm_instance_count - 1];
sorm_t * db = &sorm_instances[sorm_instance_count - 1];
printf("HIERR\n");
db->conn = NULL; db->conn = NULL;
printf("HIERR\n");
db->csv = NULL; db->csv = NULL;
db->current_column = 0; db->current_column = 0;
db->current_row = 0; db->current_row = 0;
@@ -101,17 +90,13 @@ int sormc(char * path){
db->time_result_format_end = 0; db->time_result_format_end = 0;
db->time_result_format_start = 0; db->time_result_format_start = 0;
if(sqlite3_open(path,&db->conn)) if (sqlite3_open(path, &db->conn)) {
{
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db->conn)); fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db->conn));
return 0; return 0;
} }
printf("DONE!\n");
return sorm_instance_count; return sorm_instance_count;
} }
sorm_t * sormg(int ptr){ sorm_t *sormg(int ptr) { return (sorm_t *)&sorm_instances[ptr - 1]; }
return &sorm_instances[ptr -1];
}
char *sormgcsv(int ptr) { char *sormgcsv(int ptr) {
/* sorm get csv*/ /* sorm get csv*/
@@ -121,8 +106,7 @@ char * sormgcsv(int ptr){
void sormd(int sorm) { void sormd(int sorm) {
sorm_t *db = sormg(sorm); sorm_t *db = sormg(sorm);
if(sqlite3_close(db->conn)) if (sqlite3_close(db->conn)) {
{
fprintf(stderr, "Error closing database: %s\n", sqlite3_errmsg(db->conn)); fprintf(stderr, "Error closing database: %s\n", sqlite3_errmsg(db->conn));
} }
if (sorm_last_query) { if (sorm_last_query) {
@@ -133,7 +117,6 @@ void sormd(int sorm){
free(sorm_last_query_expanded); free(sorm_last_query_expanded);
sorm_last_query_expanded = NULL; sorm_last_query_expanded = NULL;
} }
} }
char *sormpt(char *sql, int number) { char *sormpt(char *sql, int number) {
@@ -163,7 +146,6 @@ char * sormpt(char * sql, int number){
} }
sqlp++; sqlp++;
index++; index++;
} }
if (index == number) { if (index == number) {
return result; return result;
@@ -178,7 +160,6 @@ char * sormpt(char * sql, int number){
return NULL; return NULL;
} }
unsigned int sormcq(char *sql, char *out) { unsigned int sormcq(char *sql, char *out) {
// clean query // clean query
// converts %s %i parameters to ? // converts %s %i parameters to ?
@@ -226,9 +207,10 @@ Execute 3.35s, Format: 36.77s
Memory usage: 537 GB, 96.026 allocated, 96.024 freed, 2 in use. Memory usage: 537 GB, 96.026 allocated, 96.024 freed, 2 in use.
*/ */
char *sorm_csvc(int db, sqlite3_stmt *stmt) { char *sorm_csvc(int db, sqlite3_stmt *stmt) {
(void)db;
sormstr_t *str = sormstrn(512); sormstr_t *str = sormstrn(512);
unsigned int column_count = sqlite3_column_count(stmt); unsigned int column_count = sqlite3_column_count(stmt);
for(int i = 0; i < column_count; i++){ for (uint i = 0; i < column_count; i++) {
const char *column_name = sqlite3_column_name(stmt, i); const char *column_name = sqlite3_column_name(stmt, i);
sormstra(str, column_name); sormstra(str, column_name);
sormstra(str, "("); sormstra(str, "(");
@@ -243,7 +225,7 @@ char * sorm_csvc(int db, sqlite3_stmt * stmt){
return sormstrc(str); return sormstrc(str);
} }
char *sorm_csvd(int sorm, sqlite3_stmt *stmt) { char *sorm_csvd(int sorm, sqlite3_stmt *stmt) {
sorm_t * db = sormg(sorm); (void)sorm;
int rc = SQLITE_ROW; int rc = SQLITE_ROW;
int column_count = sqlite3_column_count(stmt); int column_count = sqlite3_column_count(stmt);
/* /*
@@ -270,7 +252,7 @@ char * sorm_csvd(int sorm, sqlite3_stmt * stmt) {
sprintf(temp, "%f", sqlite3_column_double(stmt, field_index)); sprintf(temp, "%f", sqlite3_column_double(stmt, field_index));
sormstra(str, temp); sormstra(str, temp);
} else if (sqlite3_column_type(stmt, field_index) == SQLITE3_TEXT) { } else if (sqlite3_column_type(stmt, field_index) == SQLITE3_TEXT) {
const char * temp = sqlite3_column_text(stmt,field_index); const char *temp = ( char *)sqlite3_column_text(stmt, field_index);
sormstra(str, temp); sormstra(str, temp);
} else { } else {
// exit(1); // exit(1);
@@ -289,7 +271,6 @@ char * sorm_csvd(int sorm, sqlite3_stmt * stmt) {
} }
char *sorm_csv(int sorm, sqlite3_stmt *stmt) { char *sorm_csv(int sorm, sqlite3_stmt *stmt) {
sorm_t * db = sormg(sorm);
sorm_row_count = 0; sorm_row_count = 0;
char *column_names = sorm_csvc(sorm, stmt); char *column_names = sorm_csvc(sorm, stmt);
char *data = sorm_csvd(sorm, stmt); char *data = sorm_csvd(sorm, stmt);
@@ -304,31 +285,16 @@ char * sorm_csv(int sorm,sqlite3_stmt * stmt){
return result; return result;
} }
sqlite3_stmt * sormb(sorm_t* db, char * sql, ...){
// Bind parameters to statement and return amount of parameters
int rc = 0;
sqlite3_stmt * stmt;
va_list args;
va_start(args,sql);
unsigned int number = 0;
char * clean_query = (char *)malloc(strlen(sql) + 1);
unsigned int parameter_count = sormcq(sql,clean_query);
free(clean_query);
return stmt;
}
char *sormm(sorm_t *db) { char *sormm(sorm_t *db) {
(void)db;
/* sormmemory */ /* sormmemory */
return rmalloc_stats(); return rmalloc_stats();
} }
sorm_ptr sormq(int sorm, char *sql, ...) { sorm_ptr sormq(int sorm, char *sql, ...) {
sorm_t *db = sormg(sorm); sorm_t *db = sormg(sorm);
if(db->csv){
//free(db->csv);
//db->csv = NULL;
}
_sorm_query_start = nsecs(); _sorm_query_start = nsecs();
db->time_query_start = nsecs(); db->time_query_start = nsecs();
va_list args; va_list args;
@@ -336,22 +302,22 @@ sorm_ptr sormq(int sorm, char * sql, ...){
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
sorm_ptr result = NULL; sorm_ptr result = NULL;
char *clean_query = malloc(strlen(sql) + 1); char *clean_query = malloc(strlen(sql) + 1);
unsigned int parameter_count = sormcq(sql,clean_query); uint parameter_count = sormcq(sql, clean_query);
int rc = sqlite3_prepare_v2(db->conn, clean_query, -1, &stmt, 0); int rc = sqlite3_prepare_v2(db->conn, clean_query, -1, &stmt, 0);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
fprintf(stderr, "%s\n", sqlite3_errmsg(db->conn)); fprintf(stderr, "%s\n", sqlite3_errmsg(db->conn));
} }
free(clean_query); free(clean_query);
int number = 0; int number = 0;
for(int i = 0; i < parameter_count; i++){ for (uint i = 0; i < parameter_count; i++) {
number++; number++;
char *column_type = sormpt(sql, number); char *column_type = sormpt(sql, number);
int arg_index = number - 1;
if (!strcmp(column_type, "int") || !strcmp(column_type, "integer") || !strcmp(column_type, "number")) { if (!strcmp(column_type, "int") || !strcmp(column_type, "integer") || !strcmp(column_type, "number")) {
rc = sqlite3_bind_int(stmt, number, va_arg(args, int)); rc = sqlite3_bind_int(stmt, number, va_arg(args, int));
} else if (!strcmp(column_type, "int64")) { } else if (!strcmp(column_type, "int64")) {
rc = sqlite3_bind_int64(stmt, number, va_arg(args, __uint64_t)); rc = sqlite3_bind_int64(stmt, number, va_arg(args, __uint64_t));
}else if(!strcmp(column_type, "double") || !strcmp(column_type, "dec") || !strcmp(column_type, "decimal") || !strcmp(column_type, "float")){ } else if (!strcmp(column_type, "double") || !strcmp(column_type, "dec") || !strcmp(column_type, "decimal") ||
!strcmp(column_type, "float")) {
rc = sqlite3_bind_double(stmt, number, va_arg(args, double)); rc = sqlite3_bind_double(stmt, number, va_arg(args, double));
} else if (!strcmp(column_type, "blob")) { } else if (!strcmp(column_type, "blob")) {
size_t size = (size_t)va_arg(args, size_t); size_t size = (size_t)va_arg(args, size_t);
@@ -359,7 +325,7 @@ sorm_ptr sormq(int sorm, char * sql, ...){
rc = sqlite3_bind_blob(stmt, number, data, size, SQLITE_STATIC); rc = sqlite3_bind_blob(stmt, number, data, size, SQLITE_STATIC);
} else if (!strcmp(column_type, "text") || !strcmp(column_type, "str") || !strcmp(column_type, "string")) { } else if (!strcmp(column_type, "text") || !strcmp(column_type, "str") || !strcmp(column_type, "string")) {
unsigned char *data = va_arg(args, unsigned char *); unsigned char *data = va_arg(args, unsigned char *);
rc = sqlite3_bind_text(stmt, number, data, -1, SQLITE_STATIC); rc = sqlite3_bind_text(stmt, number, (char *)data, -1, SQLITE_STATIC);
} }
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
fprintf(stderr, "Failed to bind parameters: %s\n", sqlite3_errmsg(db->conn)); fprintf(stderr, "Failed to bind parameters: %s\n", sqlite3_errmsg(db->conn));
@@ -381,7 +347,6 @@ sorm_ptr sormq(int sorm, char * sql, ...){
else { else {
fprintf(stderr, "Execution failed: %s\n", sqlite3_errmsg(db->conn)); fprintf(stderr, "Execution failed: %s\n", sqlite3_errmsg(db->conn));
} }
if (sorm_last_query) { if (sorm_last_query) {
free(sorm_last_query); free(sorm_last_query);
@@ -400,8 +365,6 @@ sorm_ptr sormq(int sorm, char * sql, ...){
return result; return result;
} }
char sormlc(char *sql) { char sormlc(char *sql) {
// returns last char // returns last char
char last_char = 0; char last_char = 0;
@@ -421,7 +384,7 @@ int sormlv(char * csv){
while (*csv) { while (*csv) {
char *found = strstr(csv, ";"); char *found = strstr(csv, ";");
if (found) { if (found) {
if(found - csv > longest) if (found - csv > (long int)longest)
longest = found - csv; longest = found - csv;
csv = csv + (found - csv) + 1; csv = csv + (found - csv) + 1;
} else { } else {
@@ -456,8 +419,7 @@ char * sormrq(FILE * f){
bool in_string = false; bool in_string = false;
while ((c = fgetc(f)) != EOF && strlen(buffer) != sizeof(buffer) - 2) { while ((c = fgetc(f)) != EOF && strlen(buffer) != sizeof(buffer) - 2) {
*bufferp = c; *bufferp = c;
if(c == '"') if (c == '"') {
{
in_string = !in_string; in_string = !in_string;
} }
if (!in_string && c == ';') { if (!in_string && c == ';') {
@@ -467,7 +429,6 @@ char * sormrq(FILE * f){
*bufferp = 0; *bufferp = 0;
} }
return strdup(buffer); return strdup(buffer);
} }
char *sormcsvn(char *csv) { char *sormcsvn(char *csv) {
@@ -514,7 +475,7 @@ char * sormfmt(char * csv){
sormstr_t *str = sormstrn(longest + 2); sormstr_t *str = sormstrn(longest + 2);
while (*csv && (field = sormcsvn(csv))) { while (*csv && (field = sormcsvn(csv))) {
sormstra(str, field); sormstra(str, field);
for(int i = 0; i < longest - strlen(field); i++) for (size_t i = 0; i < longest - strlen(field); i++)
sormstra(str, " "); sormstra(str, " ");
csv += strlen(field); csv += strlen(field);
@@ -538,8 +499,7 @@ void apply_colors(char * csv){
printf("%s\n", csv); printf("%s\n", csv);
end = strstr(csv, "\n"); end = strstr(csv, "\n");
char *line; char *line;
if(end) if (end) {
{
line = (char *)malloc(end - csv + 1024); line = (char *)malloc(end - csv + 1024);
strncpy(line, csv, end - csv); strncpy(line, csv, end - csv);
} else { } else {
@@ -560,7 +520,6 @@ void apply_colors(char * csv){
if (*csv && *(csv + 1)) if (*csv && *(csv + 1))
csv++; csv++;
} }
} }
void sormfmtd(char *csv) { void sormfmtd(char *csv) {
@@ -569,8 +528,4 @@ void sormfmtd(char * csv){
free(formatted); free(formatted);
} }
#endif #endif
+28 -29
View File
@@ -5,6 +5,7 @@ import io
import tempfile import tempfile
import time import time
class DictReader: class DictReader:
def get_column_types(self): def get_column_types(self):
@@ -25,12 +26,13 @@ class DictReader:
name = column.split("(")[0] name = column.split("(")[0]
names.append(name) names.append(name)
return names return names
def __init__(self, data): def __init__(self, data):
self.result = 0 self.result = 0
if type(data) == int: if type(data) == int:
self.data = '' self.data = ""
else: else:
self.data = data.decode(); self.data = data.decode()
self.rows = [row.split(";")[:-1] for row in self.data.split("\n")] self.rows = [row.split(";")[:-1] for row in self.data.split("\n")]
self.columns = self.rows[0] self.columns = self.rows[0]
@@ -45,43 +47,38 @@ class DictReader:
row[index] = self.column_types[index](field) row[index] = self.column_types[index](field)
self.column_names = self.get_column_names() self.column_names = self.get_column_names()
def __iter__(self): def __iter__(self):
return self.rows.__iter__() return self.rows.__iter__()
libc = ctypes.CDLL("libc.so.6")
libc = ctypes.CDLL('libc.so.6');
class Sorm: class Sorm:
def __init__(self): def __init__(self):
self.lib = ctypes.CDLL('./sorm.so') self.lib = ctypes.CDLL("./sorm.so")
self.sormq = self.lib.sormq self.sormq = self.lib.sormq
self.sormq.argtypes = [ctypes.c_int, ctypes.c_char_p]; self.sormq.argtypes = [ctypes.c_int, ctypes.c_char_p]
self.sormq.restype = ctypes.c_char_p self.sormq.restype = ctypes.c_char_p
self.sormc = self.lib.sormc self.sormc = self.lib.sormc
self.sormc.argtypes = [ctypes.c_char_p]; self.sormc.argtypes = [ctypes.c_char_p]
self.sormc.restype = ctypes.c_int; self.sormc.restype = ctypes.c_int
self.sormd = self.lib.sormd self.sormd = self.lib.sormd
self.sormd.argtypes = [ctypes.c_int]; self.sormd.argtypes = [ctypes.c_int]
self.sormd.restype = None self.sormd.restype = None
self.sormm = self.lib.sormm self.sormm = self.lib.sormm
self.sormm.argtypes = [ctypes.c_int]; self.sormm.argtypes = [ctypes.c_int]
self.sormm.restype = ctypes.c_char_p self.sormm.restype = ctypes.c_char_p
class SormDb(Sorm): class SormDb(Sorm):
def __init__(self, path): def __init__(self, path):
super().__init__( super().__init__()
)
self.path = path self.path = path
self.conn = None self.conn = None
@@ -109,7 +106,10 @@ class SormDb(Sorm):
self.sormq.restype = ctypes.c_int self.sormq.restype = ctypes.c_int
else: else:
self.sormq.restype = ctypes.c_char_p 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)) params = tuple(
[self.conn, sql.encode()]
+ list(arg.encode() if type(arg) == str else arg for arg in args)
)
result = DictReader(self.sormq(*params)) result = DictReader(self.sormq(*params))
self.m = self.sormm(self.conn).decode() self.m = self.sormm(self.conn).decode()
return result return result
@@ -120,43 +120,42 @@ class SormDb(Sorm):
self.sormd(self.conn) self.sormd(self.conn)
self.conn = None self.conn = None
# Load the shared library # Load the shared library
lib = ctypes.CDLL('./sorm.so') lib = ctypes.CDLL("./sorm.so")
free = libc.free free = libc.free
free.argtypes = [ctypes.c_void_p] free.argtypes = [ctypes.c_void_p]
free.restype = None free.restype = None
rsomm = lib.sormm rsomm = lib.sormm
rsomm.argtypes = [ctypes.c_int]; rsomm.argtypes = [ctypes.c_int]
rsomm.restype = ctypes.c_char_p; rsomm.restype = ctypes.c_char_p
disconnect = lib.sormd disconnect = lib.sormd
disconnect.argtypes = [ctypes.c_int]; disconnect.argtypes = [ctypes.c_int]
start = time.time() start = time.time()
for x in range(1): for x in range(1):
with SormDb("db.sqlite3") as db: with SormDb("db.sqlite3") as db:
for x in range(1): for x in range(1):
# db.q("BEGIN TRANSACTION") # db.q("BEGIN TRANSACTION")
# for x in range(100000): # for x in range(100000):
# db.q("INSERT INTO pony (name,age) VALUES (?s,?d);","Python Pony",1337) # db.q("INSERT INTO pony (name,age) VALUES (?s,?d);","Python Pony",1337)
# db.q("COMMIT") # db.q("COMMIT")
result = db.q("SELECT * FROM pony WHERE id > ?d AND name like ?s ORDER BY id",1337, "%hon Pon%"); result = db.q(
"SELECT * FROM pony WHERE id > ?d AND name like ?s ORDER BY id",
1337,
"%hon Pon%",
)
# for row in result: # for row in result:
# print(row) # print(row)
print(result.column_names) print(result.column_names)
print(len(result.rows), "records") print(len(result.rows), "records")
print(db.m); print(db.m)
end = time.time() end = time.time()
duration = end - start duration = end - start
print("Duration: {}s".format(duration)) print("Duration: {}s".format(duration))
BIN
View File
Binary file not shown.
+2 -2
View File
@@ -1,9 +1,9 @@
#ifndef SORM_STR_H #ifndef SORM_STR_H
#define SORM_STR_H #define SORM_STR_H
#include <rlib.h> #include "rlib.h"
#include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
typedef struct sormstr_t { typedef struct sormstr_t {
char *content; char *content;