Compare commits

..
6 Commits
Author SHA1 Message Date
retoor bdac78671d Added runner config
SORM tests / Compile (push) Successful in 6s
2024-11-22 14:45:03 +01:00
retoor 8eaed85e50 Upgraded english quality 2024-11-22 14:45:03 +01:00
retoor 82e133e225 Updated Readme 2024-11-22 14:45:03 +01:00
retoor 87deb64ff1 Added content 2024-11-22 14:45:03 +01:00
retoor 2e1ab5c63a Updated Readme 2024-11-22 14:45:03 +01:00
retoor d58d06031a Initial commit 2024-11-22 14:45:03 +01:00
11 changed files with 494 additions and 8911 deletions
-21
View File
@@ -1,21 +0,0 @@
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 }}."
+4 -5
View File
@@ -1,10 +1,9 @@
all: build run all: build run
build: build:
gcc main.c -Wextra -Wall -lsqlite3 -lreadline -o sorm gcc main.c -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
+3 -27
View File
@@ -1,9 +1,5 @@
# 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!
@@ -14,34 +10,14 @@ 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`
+105 -89
View File
@@ -1,116 +1,128 @@
#ifndef SORM_CLI_H #ifndef SORM_CLI_H
#define SORM_CLI_H #define SORM_CLI_H
#include "sorm.h" #include <rlib.h>
#include <fcntl.h>
#include <readline/history.h>
#include <readline/readline.h>
#include <rlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <readline/readline.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;
return 0; return 0;
} }
rl_insert_text("\n"); rl_insert_text("\n");
return 0; return 0;
} }
char *_sorm_autocompletion_generator(const char *text, int state) { char* _sorm_autocompletion_generator(const char* text, int state) {
const char *completions[] = {"exit", sorm_last_query, sorm_last_query_expanded, "python", "history", "memory", "truncate", NULL}; const char* completions[] = {
int list_index; "exit",
sorm_last_query,
sorm_last_query_expanded,
"python",
"history",
"memory",
"truncate",
NULL
};
int list_index;
if (!state) { if (!state) {
list_index = 0; list_index = 0;
} }
while (completions[list_index] != NULL) { while (completions[list_index] != NULL) {
if (strncmp(completions[list_index], text, strlen(text)) == 0) { if (strncmp(completions[list_index], text, strlen(text)) == 0) {
return strdup(completions[list_index++]); return strdup(completions[list_index++]);
} }
list_index++; list_index++;
} }
return NULL; return NULL;
} }
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;
fd = open(filename, O_RDONLY); fd = open (filename, O_RDONLY);
if (fd < 0) if (fd < 0)
return -1; return -1;
bytes_read = read(fd, buffer, size); bytes_read = read (fd, buffer, size);
close(fd); close (fd);
if (bytes_read < 0 || (size_t)bytes_read != size) if (bytes_read < 0 || (size_t)bytes_read != size)
return -1; return -1;
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;
size_t file_size; size_t file_size;
if (stat(filename, &finfo) < 0) if (stat (filename, &finfo) < 0)
return -1; return -1;
file_size = (size_t)finfo.st_size; file_size = (size_t)finfo.st_size;
input = (char *)malloc(file_size + 1); input = (char *)malloc (file_size + 1);
if (!input) if (!input)
return -1; return -1;
if (_hs_read_file(filename, input, file_size) < 0) { if (_hs_read_file (filename, input, file_size) < 0) {
free(input); free (input);
return -1; return -1;
} }
input[file_size] = '\0'; input[file_size] = '\0';
for (line_start = line_end = 0; (size_t)line_end < file_size; line_end++) { for (line_start = line_end = 0; line_end < file_size; line_end++) {
if (input[line_end] == '\n') { if (input[line_end] == '\n') {
input[line_end] = '\0'; input[line_end] = '\0';
printf("%s\n", input + line_start); printf ("%s\n",input + line_start);
line_start = line_end + 1; line_start = line_end + 1;
} }
} }
if ((size_t)line_start < file_size) if (line_start < file_size)
printf("%s\n", input + line_start); printf ("%s\n",input + line_start);
free(input); free (input);
return where_history(); return where_history ();
} }
char sorm_history_filename[4096]; char sorm_history_filename[4096];
void sorm_cli_init(const char *history_filename) { void sorm_cli_init(const char * history_filename){
strcpy(sorm_history_filename, history_filename); strcpy(sorm_history_filename, history_filename);
rl_bind_key('\n', NULL); rl_bind_key('\n',NULL);
rl_bind_key('\r', NULL); rl_bind_key('\r', NULL);
rl_add_defun("custom-accept-line", _sorm_readline_accept_line, '\n'); rl_add_defun("custom-accept-line", _sorm_readline_accept_line, '\n');
rl_add_defun("custom-accept-line-cr", _sorm_readline_accept_line, '\r'); rl_add_defun("custom-accept-line-cr", _sorm_readline_accept_line, '\r');
@@ -118,51 +130,55 @@ void sorm_cli_init(const char *history_filename) {
rl_attempted_completion_function = _sorm_autocomplete; rl_attempted_completion_function = _sorm_autocomplete;
rl_variable_bind("show-all-if-ambiguous", "on"); rl_variable_bind("show-all-if-ambiguous", "on");
rl_variable_bind("menu-complete-display-prefix", "on"); rl_variable_bind("menu-complete-display-prefix", "on");
using_history(); using_history();
read_history(sorm_history_filename); read_history(sorm_history_filename);
} }
char sorm_cli_previous_command[sizeof(rl_line_buffer)]; char sorm_cli_previous_command[sizeof(rl_line_buffer)];
char *sorm_cli_readline(char *prompt) { char * sorm_cli_readline(char * prompt){
char *result = readline(prompt); char * result = readline(prompt);
if (strcmp(rl_line_buffer, sorm_cli_previous_command)) { if(strcmp(rl_line_buffer,sorm_cli_previous_command)){
add_history((const char *)result); add_history((const char *)result);
write_history(sorm_history_filename); write_history(sorm_history_filename);
} }
strcpy(sorm_cli_previous_command, rl_line_buffer); strcpy(sorm_cli_previous_command,rl_line_buffer);
return result; return result;
} }
bool sormrepl_handle_command(char *command) {
if (!strncmp(command, "history", 7)) { bool sormrepl_handle_command(char * command){
sorm_cli_history_dump(history_filename); if(!strncmp(command, "history",7)){
return true; sorm_cli_history_dump(history_filename);
} return true;
}
return false; return false;
} }
void sormrepl(int sorm) { void sormrepl(int sorm){
sorm_cli_init(history_filename); sorm_t * db = sormg(sorm);
char *query; char sql[4097];
while ((query = sorm_cli_readline("sql> "))) {
if (sormrepl_handle_command(query))
continue;
sorm_ptr res = sormq(sorm, query);
if (res) {
if (sormqt(query) == SORM_SELECT) {
sormfmtd(res);
free(res);
} else if (sormqt(query) == SORM_DELETE) {
printf("%d records affected.\n", res);
} else if (sormqt(query) == SORM_INSERT) {
printf("Last insert id: %d.\n", res);
}
}
printf("Rows: %lld, Execute %s, Format: %s\n", sorm_row_count, format_time(_sorm_query_duration), sorm_cli_init(history_filename);
format_time(_sorm_result_format_duration)); char * query;
printf("%s\n", rmalloc_stats()); while((query = sorm_cli_readline("sql> "))){
} if(sormrepl_handle_command(query))
continue;
sorm_ptr res = sormq(sorm,query);
if(res){
if(sormqt(query) == SORM_SELECT){
int length = sormlv(res);
sormfmtd(res);
free(res);
}else if(sormqt(query) == SORM_DELETE){
printf("%d records affected.\n",res);
}else if(sormqt(query) == SORM_INSERT){
printf("Last insert id: %d.\n",res);
}
}
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());
}
} }
#endif #endif
+30 -15
View File
@@ -1,24 +1,39 @@
#include "cli.h"
#include "sorm.h" #include "sorm.h"
#include "cli.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;");
sormq(db, "CREATE TABLE IF NOT EXISTS pony (id INTEGER PRIMARY KEY AUTOINCREMENT,name,age);", NULL); printf("%d\n",db);
sormq(db, "INSERT INTO pony (id,name,age) VALUES (NULL,%s,%d);", "Teenii", 19); sormq(db, "CREATE TABLE IF NOT EXISTS pony (id INTEGER PRIMARY KEY AUTOINCREMENT,name,age);",NULL);
sormq(db, "INSERT INTO pony (id,name,age) VALUES (NULL,%s,%d);", "Amber", 20); 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);", "Feuerherz", 20); "Teenii",
sormq(db, "INSERT INTO pony (id,name,age) VALUES (NULL,%s,%d);", "Retoor", 34); 19
sorm_str csv2 = (sorm_str)sormq(db, "SELECT * FROM pony WHERE id = %d and age = %d ", 1, 33); );
sorm_str csv3 = (sorm_str)sormq(db, "SELECT * FROM pony LIMIT 2"); iid = sormq(db, "INSERT INTO pony (id,name,age) VALUES (NULL,%s,%d);",
// free(csv3); "Amber",
// free(csv2); 20
if (csv2) );
printf("%s\n", csv2); iid = sormq(db, "INSERT INTO pony (id,name,age) VALUES (NULL,%s,%d);",
printf("%s\n", csv3); "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(csv2);
if(csv2)
printf("%s\n",csv2);
printf("%s\n",csv3);
free(csv3); free(csv3);
sormd(db); sormd(db);
printf("%s\n", rmalloc_stats()); printf("%s\n",rmalloc_stats());
db = sormc("db.sqlite3"); db = sormc("db.sqlite3");
sormrepl(db); sormrepl(db);
} }
-8448
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
+278 -233
View File
@@ -1,20 +1,21 @@
#ifndef SORM_H #ifndef SORM_H
#define SORM_H #define SORM_H
#include "str.h" #include <rlib.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_expanded = NULL; char * sorm_last_query = NULL;
char * sorm_last_query_expanded = NULL;
nsecs_t _sorm_query_start = 0; nsecs_t _sorm_query_start = 0;
nsecs_t _sorm_query_end = 0; nsecs_t _sorm_query_end = 0;
@@ -27,10 +28,10 @@ nsecs_t _sorm_result_format_duration = 0;
int64_t sorm_row_count = 0; int64_t sorm_row_count = 0;
typedef struct sorm_t { typedef struct sorm_t {
sqlite3 *conn; sqlite3 * conn;
int current_row; int current_row;
int current_column; int current_column;
char *csv; char * csv;
nsecs_t time_query_start; nsecs_t time_query_start;
nsecs_t time_query_end; nsecs_t time_query_end;
nsecs_t time_query_duration; nsecs_t time_query_duration;
@@ -38,23 +39,26 @@ typedef struct sorm_t {
nsecs_t time_result_format_end; nsecs_t time_result_format_end;
nsecs_t time_result_format_duration; nsecs_t time_result_format_duration;
} sorm_t; } sorm_t;
typedef char *sorm_pk; typedef char * sorm_pk;
typedef char *sorm_int; typedef char * sorm_int;
typedef char *sorm_ptr; typedef char * sorm_ptr;
typedef unsigned char *sorm_str; typedef unsigned char * sorm_str;
typedef double sorm_double; typedef double sorm_double;
typedef double sorm_float; typedef double sorm_float;
typedef bool sorm_bool; typedef bool sorm_bool;
int sormc(char *path); int sormc(char * path);
void sormd(int db); 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);
sorm_ptr sormq(int db, char *sql, ...); sqlite3_stmt * sormb(sorm_t* db, char * sql, ...);
char *sorm_csvc(int db, sqlite3_stmt *stmt); sorm_ptr sormq(int db, char * sql, ...);
char *sorm_csvd(int db, sqlite3_stmt *stmt); char * sorm_csvc(int db, sqlite3_stmt * stmt);
char *sorm_csv(int db, sqlite3_stmt *stmt); char * sorm_csvd(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,
@@ -67,19 +71,26 @@ 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));
sorm_t *db = (sorm_t *)&sorm_instances[sorm_instance_count - 1]; printf("HIERR\n");
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;
@@ -89,86 +100,94 @@ int sormc(char *path) {
db->time_result_format_duration = 0; db->time_result_format_duration = 0;
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)); {
return 0; fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db->conn));
return 0;
} }
printf("DONE!\n");
return sorm_instance_count; return sorm_instance_count;
} }
sorm_t *sormg(int ptr) { return (sorm_t *)&sorm_instances[ptr - 1]; } sorm_t * sormg(int ptr){
return &sorm_instances[ptr -1];
}
char *sormgcsv(int ptr) { char * sormgcsv(int ptr){
/* sorm get csv*/ /* sorm get csv*/
sorm_t *db = sormg(ptr); sorm_t * db = sormg(ptr);
return db->csv; return db->csv;
} }
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){
free(sorm_last_query); free(sorm_last_query);
sorm_last_query = NULL; sorm_last_query = NULL;
} }
if (sorm_last_query_expanded) { if(sorm_last_query_expanded){
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){
// param type // param type
char *sqlp = sql; char * sqlp = sql;
char *result = NULL; char * result = NULL;
int index = 0; int index = 0;
while (*sqlp) { while(*sqlp){
if (*sqlp == '%' || *sqlp == '?') { if(*sqlp == '%' || *sqlp == '?'){
sqlp++; sqlp++;
switch (*sqlp) { switch(*sqlp){
case 'f': case 'f':
result = "double"; result = "double";
break; break;
case 's': case 's':
result = "text"; result = "text";
break; break;
case 'd': case 'd':
result = "int"; result = "int";
break; break;
case 'b': case 'b':
result = "blob"; result = "blob";
break; break;
default: default:
result = "?"; result = "?";
break; break;
} }
sqlp++; sqlp++;
index++; index++;
} }
if (index == number) { if(index == number){
return result; return result;
} }
if (*sqlp) if(*sqlp)
sqlp++; sqlp++;
} }
if (number > index) { if(number > index){
printf("RETURNED\n"); printf("RETURNED\n");
return NULL; return NULL;
} }
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 ?
unsigned int count = 0; unsigned int count = 0;
while (*sql) { while(*sql){
if (*sql != '%' && *sql != '?') if(*sql != '%' && *sql != '?')
*out = *sql; *out = *sql;
else { else{
count++; count++;
sql++; sql++;
*out = '?'; *out = '?';
@@ -180,25 +199,25 @@ unsigned int sormcq(char *sql, char *out) {
return count; return count;
} }
unsigned int sormpc(char *sql) { unsigned int sormpc(char * sql){
int number = 0; int number = 0;
while (sormpt(sql, number) != NULL) while(sormpt(sql,number) != NULL)
number++; number++;
printf("FOUND: %d\n", number); printf("FOUND: %d\n",number);
return number; return number;
} }
char *sormcts(int column_type) { char * sormcts(int column_type){
if (column_type == SQLITE_INTEGER) if(column_type == SQLITE_INTEGER)
return "integer"; return "integer";
else if (column_type == SQLITE_TEXT) else if(column_type == SQLITE_TEXT)
return "text"; return "text";
else if (column_type == SQLITE_FLOAT) else if(column_type == SQLITE_FLOAT)
return "float"; return "float";
else if (column_type == SQLITE_NULL) else if(column_type == SQLITE_NULL)
return "null"; return "null";
else if (column_type == SQLITE_BLOB) else if(column_type == SQLITE_BLOB)
return "blob"; return "blob";
return "?"; return "?";
} }
@@ -206,26 +225,25 @@ char *sormcts(int column_type) {
Execute 3.35s, Format: 36.77s 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, "("); char column_type[1000] = "";
char column_type[1000] = ""; sprintf(column_type,"%s",sormcts(sqlite3_column_type(stmt,i)));
sprintf(column_type, "%s", sormcts(sqlite3_column_type(stmt, i))); sormstra(str,column_type);
sormstra(str, column_type); sormstra(str,")");
sormstra(str, ")");
// if(i != column_count - 1)
// if(i != column_count - 1) sormstra(str,";");
sormstra(str, ";"); }
}
return sormstrc(str); return sormstrc(str);
} }
char *sorm_csvd(int sorm, sqlite3_stmt *stmt) { char * sorm_csvd(int sorm, sqlite3_stmt * stmt) {
(void)sorm; sorm_t * db = sormg(sorm);
int rc = SQLITE_ROW; int rc = SQLITE_ROW;
int column_count = sqlite3_column_count(stmt); int column_count = sqlite3_column_count(stmt);
/* /*
@@ -239,119 +257,136 @@ char *sorm_csvd(int sorm, sqlite3_stmt *stmt) {
xecute 3.42s, Format: 37.33s xecute 3.42s, Format: 37.33s
Memory usage: 6 MB, 96.052 (re)allocated, 96.024 unqiue freed, 2 in use. Memory usage: 6 MB, 96.052 (re)allocated, 96.024 unqiue freed, 2 in use.
*/ */
sormstr_t *str = sormstrn(512); sormstr_t * str = sormstrn(512);
while (rc == SQLITE_ROW) { while(rc == SQLITE_ROW){
sorm_row_count++; sorm_row_count++;
for (int field_index = 0; field_index < column_count; field_index++) { for(int field_index = 0; field_index < column_count; field_index++){
if (sqlite3_column_type(stmt, field_index) == SQLITE_INTEGER) { if(sqlite3_column_type(stmt,field_index) == SQLITE_INTEGER){
char temp[1000] = ""; char temp[1000] = "";
sprintf(temp, "%lld", sqlite3_column_int64(stmt, field_index)); sprintf(temp, "%lld",sqlite3_column_int64(stmt,field_index));
sormstra(str, temp); sormstra(str,temp);
} else if (sqlite3_column_type(stmt, field_index) == SQLITE_FLOAT) { }else if(sqlite3_column_type(stmt,field_index) == SQLITE_FLOAT){
char temp[1000] = ""; char temp[1000] = "";
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 = ( char *)sqlite3_column_text(stmt, field_index); const char * temp = sqlite3_column_text(stmt,field_index);
sormstra(str, temp); sormstra(str,temp);
} else { } else {
// exit(1); // exit(1);
}
// if(field_index != column_count - 1)
sormstra(str,";");
} }
// if(field_index != column_count - 1) sormstra(str,"\n");
sormstra(str, ";"); rc = sqlite3_step(stmt);
} }
sormstra(str, "\n"); char * text = sormstrc(str);
rc = sqlite3_step(stmt); if(*text)
} if(text[strlen(text)-1] == '\n')
char *text = sormstrc(str); text[strlen(text)-1] = 0;
if (*text) return strdup(text);
if (text[strlen(text) - 1] == '\n')
text[strlen(text) - 1] = 0;
return strdup(text);
} }
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);
char *result = (char *)malloc(strlen(column_names) + strlen(data) + 2); char * result = (char *)malloc(strlen(column_names) + strlen(data) + 2);
result[0] = 0; result[0] = 0;
strcat(result, column_names); strcat(result,column_names);
if (*column_names) if(*column_names)
strcat(result, "\n"); strcat(result,"\n");
free(column_names); free(column_names);
strcat(result, data); strcat(result,data);
free(data); free(data);
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;
va_start(args, sql); va_start (args,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);
uint parameter_count = sormcq(sql, clean_query); unsigned int 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 (uint i = 0; i < parameter_count; i++) { for(int i = 0; i < parameter_count; i++){
number++; number++;
char *column_type = sormpt(sql, number); char * column_type = sormpt(sql,number);
if (!strcmp(column_type, "int") || !strcmp(column_type, "integer") || !strcmp(column_type, "number")) { int arg_index = number - 1;
rc = sqlite3_bind_int(stmt, number, va_arg(args, int)); if(!strcmp(column_type, "int") || !strcmp(column_type, "integer") || !strcmp(column_type, "number")) {
} else if (!strcmp(column_type, "int64")) { rc = sqlite3_bind_int(stmt, number, va_arg(args,int));
rc = sqlite3_bind_int64(stmt, number, va_arg(args, __uint64_t)); }else if(!strcmp(column_type, "int64")){
} else if (!strcmp(column_type, "double") || !strcmp(column_type, "dec") || !strcmp(column_type, "decimal") || rc = sqlite3_bind_int64(stmt, number,va_arg(args,__uint64_t));
!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);
unsigned char *data = va_arg(args, unsigned char *); unsigned char * data = va_arg(args,unsigned char *);
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, (char *)data, -1, SQLITE_STATIC); rc = sqlite3_bind_text(stmt, number, 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));
result = NULL; result = NULL;
} }
} }
rc = sqlite3_step(stmt); rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE && rc != SQLITE_ROW) { if (rc != SQLITE_DONE && rc != SQLITE_ROW) {
fprintf(stderr, "Execution failed: %s\n", sqlite3_errmsg(db->conn)); fprintf(stderr, "Execution failed: %s\n", sqlite3_errmsg(db->conn));
} else if (rc == SQLITE_DONE) { }else if(rc == SQLITE_DONE){
if (!sqlite3_strnicmp(sql, "SELECT", 6)) { if(!sqlite3_strnicmp(sql,"SELECT",6)){
result = 0; result = 0;
} else { }else {
result = (sorm_ptr)sqlite3_last_insert_rowid(db->conn); result = (sorm_ptr)sqlite3_last_insert_rowid(db->conn);
} }
} else if (rc == SQLITE_ROW) { } else if (rc == SQLITE_ROW) {
result = sorm_csv(sorm, stmt); result = sorm_csv(sorm,stmt);
} }
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);
} }
if (sorm_last_query) { if(sorm_last_query){
free(sorm_last_query_expanded); free(sorm_last_query_expanded);
} }
sorm_last_query = strdup(sqlite3_sql(stmt)); sorm_last_query = strdup(sqlite3_sql(stmt));
@@ -365,99 +400,103 @@ 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;
while (*sql) { while(*sql){
if (*sql == ' ' || *sql == '\t' || *sql == '\n') if(*sql == ' ' || *sql == '\t' || *sql == '\n')
continue; continue ;
// printf("%c\n",*sql); //printf("%c\n",*sql);
last_char = *sql; last_char = *sql;
sql++; sql++;
} }
return last_char; return last_char;
} }
int sormlv(char *csv) { int sormlv(char * csv){
size_t longest = 0; size_t longest = 0;
while (*csv) { while(*csv){
char *found = strstr(csv, ";"); char * found = strstr(csv,";");
if (found) { if(found){
if (found - csv > (long int)longest) if(found - csv > longest)
longest = found - csv; longest = found-csv;
csv = csv + (found - csv) + 1; csv = csv + (found - csv) + 1;
} else { }else{
break; break;
} }
} }
return longest; return longest;
} }
sorm_query_t sormqt(char *sql) { sorm_query_t sormqt(char * sql){
while (*sql && isspace(*sql)) while(*sql && isspace(*sql))
sql++; sql++;
if (!sqlite3_strnicmp(sql, "select", 6)) if(!sqlite3_strnicmp(sql,"select",6))
return SORM_SELECT; return SORM_SELECT;
else if (!sqlite3_strnicmp(sql, "update", 6)) else if(!sqlite3_strnicmp(sql, "update",6))
return SORM_UPDATE; return SORM_UPDATE;
else if (!sqlite3_strnicmp(sql, "delete", 6)) else if(!sqlite3_strnicmp(sql, "delete",6))
return SORM_DELETE; return SORM_DELETE;
else if (!sqlite3_strnicmp(sql, "create", 6)) { else if(!sqlite3_strnicmp(sql, "create",6)){
return SORM_CREATE; return SORM_CREATE;
} else { }else {
return SORM_UNKNOWN; return SORM_UNKNOWN;
} }
} }
char *sormrq(FILE *f) { char * sormrq(FILE * f){
static char buffer[4097]; static char buffer[4097];
buffer[0] = 0; buffer[0] = 0;
char *bufferp = buffer; char * bufferp = buffer;
char c; char c;
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 == ';'){
break; break;
} }
bufferp++; bufferp++;
*bufferp = 0; *bufferp = 0;
} }
return strdup(buffer); return strdup(buffer);
} }
char *sormcsvn(char *csv) { char * sormcsvn(char * csv){
if (!csv || !*csv) if(!csv || !*csv)
return NULL; return NULL;
char *pos = strstr(csv, ";"); char * pos = strstr(csv,";");
char *pos2 = strstr(csv, "\n"); char * pos2 = strstr(csv,"\n");
if (pos2) { if(pos2){
if (pos > pos2) { if(pos > pos2){
pos = pos2; pos = pos2;
} }
// pos = pos > pos2 ? pos2 : pos; //pos = pos > pos2 ? pos2 : pos;
} }
if (!pos || !*pos) if(!pos || !*pos)
return strdup(csv); return strdup(csv);
int length = pos - csv; int length = pos - csv;
char *result = malloc(length + 2); char * result = malloc(length + 2);
strncpy(result, csv, length); strncpy(result,csv,length);
result[length] = 0; result[length] = 0;
// csv += strlen(result); //csv += strlen(result);
return result; return result;
} }
char *sormfmt(char *csv) { char * sormfmt(char * csv){
_sorm_result_format_start = nsecs(); _sorm_result_format_start = nsecs();
size_t longest = sormlv(csv); size_t longest = sormlv(csv);
char *field; char * field;
/* /*
sormstrn(1) sormstrn(1)
Execute 3.77s, Format: 36.40s Execute 3.77s, Format: 36.40s
@@ -472,15 +511,15 @@ char *sormfmt(char *csv) {
Execute 3.11s, Format: 36.45s Execute 3.11s, Format: 36.45s
Memory usage: 6 MB, 96.048 (re)allocated, 96.024 unqiue freed, 2 in use. Memory usage: 6 MB, 96.048 (re)allocated, 96.024 unqiue freed, 2 in use.
*/ */
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 (size_t i = 0; i < longest - strlen(field); i++) for(int i = 0; i < longest - strlen(field); i++)
sormstra(str, " "); sormstra(str," ");
csv += strlen(field); csv += strlen(field);
while (*csv == ';' || *csv == '\n') { while( *csv == ';' || *csv == '\n'){
if (*csv == '\n') if(*csv == '\n')
sormstra(str, "\n"); sormstra(str, "\n");
csv++; csv++;
} }
@@ -491,41 +530,47 @@ char *sormfmt(char *csv) {
return sormstrc(str); return sormstrc(str);
} }
void apply_colors(char *csv) { void apply_colors(char * csv){
char *end; char * end;
bool even = false; bool even = false;
while (*csv) { while(*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); {
strncpy(line, csv, end - csv); line = (char *)malloc(end -csv + 1024);
} else { strncpy(line,csv,end-csv);
}else{
line = (char *)malloc(strlen(csv) + 1024); line = (char *)malloc(strlen(csv) + 1024);
strcpy(line, csv); strcpy(line, csv);
} }
if (even) { if(even){
printf("%s", "\033[37m"); printf("%s","\033[37m");
} }
printf("%s\n", line); printf("%s\n",line);
free(line); free(line);
if (even) { if(even){
printf("%s", "\033[0m"); printf("%s","\033[0m");
} }
even = !even; even = !even;
csv += end - csv; csv += end-csv;
if (*csv && *(csv + 1)) if(*csv && *(csv + 1))
csv++; csv++;
} }
} }
void sormfmtd(char *csv) { void sormfmtd(char * csv){
char *formatted = sormfmt(csv); char * formatted = sormfmt(csv);
printf("%s\n", formatted); printf("%s\n",formatted);
free(formatted); free(formatted);
} }
#endif
#endif
+58 -57
View File
@@ -1,40 +1,38 @@
import ctypes import ctypes
import csv import csv
from csv import DictReader from csv import DictReader
import io import io
import tempfile import tempfile
import time import time
class DictReader: class DictReader:
def get_column_types(self): def get_column_types(self):
types = [] types = []
for column in self.columns: for column in self.columns:
name = column.split("(")[0] name = column.split("(")[0]
type = column.split("(")[1] type = column.split("(")[1]
type = type.split(")")[0] type = type.split(")")[0]
if type == "integer": if type == "integer":
types.append(int) types.append(int)
if type == "text": if type == "text":
types.append(str) types.append(str)
return types return types
def get_column_names(self): def get_column_names(self):
names = [] names = []
for column in self.columns: for column in self.columns:
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]
self.rows.pop(0) self.rows.pop(0)
if type(data) == str: if type(data) == str:
@@ -43,42 +41,47 @@ class DictReader:
self.result = data self.result = data
self.column_types = self.get_column_types() self.column_types = self.get_column_types()
for row in self.rows: for row in self.rows:
for index, field in enumerate(row): for index,field in enumerate(row):
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
@@ -90,13 +93,13 @@ class SormDb(Sorm):
def __enter__(self): def __enter__(self):
self.c() self.c()
return self return self
def __exit__(self, *args, **kwargs): def __exit__(self,*args, **kwargs):
self.d() self.d()
def q(self, sql, *args) -> DictReader: def q(self, sql,*args) -> DictReader:
ctypes_list = [] ctypes_list = []
for arg in args: for arg in args:
if type(arg) == int: if type(arg) == int:
ctypes_list.append(ctypes.c_int) ctypes_list.append(ctypes.c_int)
if type(arg) == str: if type(arg) == str:
@@ -106,56 +109,54 @@ 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( params = tuple([self.conn, sql.encode()] + list(arg.encode() if type(arg) == str else arg for arg in args))
[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
def d(self): def d(self):
if not self.conn: if not self.conn:
return return
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( result = db.q("SELECT * FROM pony WHERE id > ?d AND name like ?s ORDER BY id",1337, "%hon Pon%");
"SELECT * FROM pony WHERE id > ?d AND name like ?s ORDER BY id", #for row in result:
1337,
"%hon Pon%",
)
# 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.
+16 -16
View File
@@ -1,19 +1,19 @@
#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;
size_t length; size_t length;
size_t buffer_size; size_t buffer_size;
size_t size; size_t size;
} sormstr_t; } sormstr_t;
sormstr_t *sormstrn(size_t buffer_size) { sormstr_t * sormstrn(size_t buffer_size){
sormstr_t *result = (sormstr_t *)malloc(sizeof(sormstr_t)); sormstr_t * result = (sormstr_t *)malloc(sizeof(sormstr_t));
result->length = 0; result->length = 0;
result->size = buffer_size; result->size = buffer_size;
result->buffer_size = buffer_size; result->buffer_size = buffer_size;
@@ -21,30 +21,30 @@ sormstr_t *sormstrn(size_t buffer_size) {
result->content[0] = 0; result->content[0] = 0;
return result; return result;
} }
void sormstra(sormstr_t *str, const char *to_append) { void sormstra(sormstr_t * str, const char * to_append){
size_t required_new_length = str->length + strlen(to_append); size_t required_new_length = str->length + strlen(to_append);
str->length += strlen(to_append); str->length += strlen(to_append);
if (required_new_length > str->size) { if(required_new_length > str->size){
str->size += required_new_length + str->buffer_size; str->size += required_new_length + str->buffer_size;
str->content = realloc(str->content, str->size + 1); str->content = realloc(str->content,str->size + 1);
} else { }else{
// printf("NO NDEED\n"); // printf("NO NDEED\n");
} }
strcat(str->content, to_append); strcat(str->content,to_append);
str->content[str->length] = 0; str->content[str->length] = 0;
} }
void sormstrd(sormstr_t *str) { void sormstrd(sormstr_t * str){
if (str->content) { if(str->content){
free(str->content); free(str->content);
} }
free(str); free(str);
} }
char *sormstrc(sormstr_t *str) { char * sormstrc(sormstr_t * str){
// sorm str convert // sorm str convert
char *content = str->content; char * content = str->content;
str->content = NULL; str->content = NULL;
sormstrd(str); sormstrd(str);
return content; return content;
} }
#endif #endif