All source listed below is under MIT license if no LICENSE file stating different is available.

SORM

Description

SORM stands for SQL ORM. I made this because i have a hate/love relationship with both. I combined it together to have the best of both worlds!

The naming of my functions and variables are something to get used to. They're all abbreviations, kinda like C stdlib style. It looks weird, but you get used to it quickly and in reality, you just use a few of them.

Examples of common used functions are:

  • sormc(char *path) connect to database. Returns int.
  • 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.

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

I use mainly native types and not custom structs. For example, the db parameter is an int. This is so it can easily conmmunicate 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. While the performance is nice, it's not written with performance in mind at all.

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

C API examples:

Connecting

int db = sormc("db.sqlite3");

Create table

This one should return true if executed.

sormq(db, "CREATE TABLE IF NOT EXISTS pony (id INTEGER  PRIMARY KEY AUTOINCREMENT,name,age);",NULL);

Inserting

sorm_pk iid = sormq(db, "INSERT INTO pony (id, name, age) VALUES (NULL, %s, %d);",
    "Retoorded retoor",
    42
);

Using ? is also possible for arguments like this (comfy for Python usage):

sorm_pk iid = sormq(db, "INSERT INTO pony (id, name, age) VALUES (NULL, ?s, ?d);",
    "Retoorded retoor",
    42
);

Selecting

IN query

sorm_str csv = sormq(db, "SELECT * FROM pony WHERE id in (?d,?d,?d)",1,2,3);
free(sorm_str);

LIKE query

sorm_str csv2 = sormq(db, "SELECT * FROM pony WHERE id > %d and age = %d AND name LIKE ?s", 1, 34, "%toor%"));
free(sorm_str);

Yes, you did see that right, you can use the default native free!

Disconnecting

sormd(db);
.clang-format
.gitignore
cli.h
main.c
Makefile
README.md
sorm
sorm.h
sorm.py
sorm.so
str.h