Csilk 0.2.1
A lightweight, high-performance C HTTP web framework
Loading...
Searching...
No Matches
db.h File Reference
#include <stddef.h>
#include <stdint.h>
#include "csilk/csilk.h"
Include dependency graph for db.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  csilk_db_stats_t
 Database statistics. More...
 
struct  csilk_db_pool_t
 A (currently single-connection) database pool. More...
 
struct  csilk_db_row_t
 A single row of a query result. More...
 
struct  csilk_db_result_t
 A complete query result set. More...
 
struct  csilk_db_driver_t
 Virtual function table implemented by each database driver. More...
 

Functions

void csilk_db_get_stats (csilk_db_stats_t *stats)
 Get current database statistics.
 
csilk_db_pool_tcsilk_db_pool_new (const char *driver_name, const char *dsn)
 Create a new database pool and connect using the named driver.
 
void csilk_db_pool_free (csilk_db_pool_t *pool)
 Destroy a database pool and disconnect.
 
cJSON * csilk_db_query_json (csilk_db_pool_t *pool, const char *sql)
 Execute a SELECT query and return the rows as a JSON array.
 
int csilk_db_exec (csilk_db_pool_t *pool, const char *sql)
 Execute a statement that produces no result rows.
 
cJSON * csilk_db_query_param_json (csilk_db_pool_t *pool, const char *sql, const char **params)
 Execute a parameterised SELECT query with ? placeholders.
 
int csilk_db_register_driver (const char *name, csilk_db_driver_t *driver)
 Register a database driver implementation.
 
csilk_db_driver_t * csilk_db_get_driver (const char *name)
 Look up a registered driver by name.
 
void csilk_db_sqlite_init (void)
 Internal: Register the built-in SQLite3 driver.
 
void csilk_db_init (void)
 Internal: Register the built-in MySQL driver.
 

Data Structure Documentation

◆ csilk_db_stats_t

struct csilk_db_stats_t

Database statistics.

Data Fields
uint64_t duration_us_total

Cumulative duration in microseconds.

uint64_t errors_total

Total failed operations.

uint64_t execs_total

Total non-query statements (INSERT/UPDATE/etc).

uint64_t queries_total

Total SELECT queries executed.

◆ csilk_db_pool_t

struct csilk_db_pool_t

A (currently single-connection) database pool.

Wraps a driver + connection with a mutex for thread-safe access. All queries and statements go through this pool. The pool is created via csilk_db_pool_new (which opens the connection) and destroyed via csilk_db_pool_free (which closes it).

Thread Safety

The pool's mutex serialises all driver operations across libuv worker threads (uv_queue_work). Functions like csilk_db_query_json acquire the mutex automatically. Do NOT call driver functions directly without holding the mutex.

Note
The current implementation holds exactly one connection. A future version may support a true connection pool with multiple replicas.
Data Fields
void * connection

Opaque driver-specific connection handle (set by the driver's connect callback).

csilk_db_driver_t * driver

Pointer to the registered driver implementation (set by csilk_db_pool_new).

uv_mutex_t mutex

Mutex serialising access to connection across threads. Held automatically by pool-level functions.

◆ csilk_db_row_t

struct csilk_db_row_t

A single row of a query result.

Values are strings (human-readable representations of column data). NULL database values are represented as NULL pointers in the values array.

Data Fields
int count

Number of columns (length of values).

char ** values

Array of NUL-terminated string values, one per column. NULL if the SQL value was NULL.

◆ csilk_db_result_t

struct csilk_db_result_t

A complete query result set.

Contains all rows, column names, and dimension information. Allocated by the driver's query function and freed by free_result.

Collaboration diagram for csilk_db_result_t:
Data Fields
int column_count

Number of columns (length of column_names and each row's values).

char ** column_names

Array of column name strings (length column_count).

int row_count

Number of rows in rows.

csilk_db_row_t ** rows

Array of row pointers (length row_count).

Function Documentation

◆ csilk_db_exec()

int csilk_db_exec ( csilk_db_pool_t pool,
const char *  sql 
)

Execute a statement that produces no result rows.

Acquires the pool mutex and calls the driver's exec function.

Parameters
poolConnection pool.
sqlSQL statement (INSERT, UPDATE, DELETE, DDL).
Returns
0 on success, -1 on failure.

Execute a statement that produces no result rows.

Execute a statement that returns no result rows.

◆ csilk_db_get_driver()

csilk_db_driver_t * csilk_db_get_driver ( const char *  name)

Look up a registered driver by name.

Parameters
nameDriver identifier string.
Returns
Pointer to the registered csilk_db_driver_t, or NULL if not found.

◆ csilk_db_get_stats()

void csilk_db_get_stats ( csilk_db_stats_t stats)

Get current database statistics.

Parameters
stats[out] Pointer to stats struct to populate.

◆ csilk_db_init()

void csilk_db_init ( void  )

Internal: Register the built-in MySQL driver.

Called automatically by csilk_db_init. Requires libmysqlclient. Not intended for direct use.

Internal: Register the built-in PostgreSQL driver.

Called automatically by csilk_db_init. Requires libpq. Not intended for direct use.

Internal: Register the built-in MongoDB driver.

Called automatically by csilk_db_init. Requires libmongoc. Not intended for direct use.

Internal: Register the built-in Redis driver.

Called automatically by csilk_db_init. Requires hiredis. Not intended for direct use.

Initialise the database subsystem.

Registers all built-in drivers (SQLite3, MySQL, PostgreSQL, MongoDB, Redis). Must be called once before any csilk_db_pool_new call. Safe to call multiple times.

Internal: Register the built-in MySQL driver.

Registers all built-in drivers (SQLite3, MySQL, PostgreSQL, etc.). Must be called once before any csilk_db_pool_new call. Safe to call multiple times.

◆ csilk_db_pool_free()

void csilk_db_pool_free ( csilk_db_pool_t pool)

Destroy a database pool and disconnect.

Calls the driver's disconnect, frees internal resources, and deallocates the pool struct.

Parameters
poolPool to destroy. Must not be NULL.

Destroy a database pool and disconnect.

Free a database pool and disconnect.

Teardown

  1. Call driver->disconnect() — closes the database connection.
  2. Destroy the pool mutex.
  3. Free the pool struct.

The driver's free_result is not called here — any outstanding results must have been freed by the caller.

◆ csilk_db_pool_new()

csilk_db_pool_t * csilk_db_pool_new ( const char *  driver_name,
const char *  dsn 
)

Create a new database pool and connect using the named driver.

Looks up the driver by driver_name (must have been registered via csilk_db_register_driver or the built-in init), allocates a pool, and calls the driver's connect function.

Parameters
driver_nameDriver identifier (e.g., "sqlite"). Must not be NULL.
dsnData source name (driver-specific format).
Returns
A new csilk_db_pool_t on success, or NULL if the driver is unknown or the connection fails.

Create a new database pool and connect using the named driver.

Create a new database connection pool.

Pool creation

  1. Look up the driver by name in the global registry.
  2. calloc the pool struct, init the pool mutex.
  3. Call driver->connect() with the DSN — this may block for network round-trips.
  4. On success: return the pool. On failure: destroy mutex, free pool.

The pool holds exactly ONE connection (mutex-serialized access). This is intentional — the caller is expected to manage a pool of pools if concurrency is needed.

Parameters
driver_nameRegistered driver name (e.g., "sqlite3").
dsnData source name (e.g., "/tmp/test.db" or "host=...").

◆ csilk_db_query_json()

cJSON * csilk_db_query_json ( csilk_db_pool_t pool,
const char *  sql 
)

Execute a SELECT query and return the rows as a JSON array.

Internally acquires the pool mutex, calls the driver's query function, converts each row to a JSON object (keyed by column name), frees the native result, and returns the cJSON array.

Parameters
poolConnection pool.
sqlSQL SELECT statement.
Returns
A cJSON array of row objects, or NULL on failure. Caller must free with cJSON_Delete.

Execute a SELECT query and return the rows as a JSON array.

Execute a SELECT query and return the result as a JSON array.

◆ csilk_db_query_param_json()

cJSON * csilk_db_query_param_json ( csilk_db_pool_t pool,
const char *  sql,
const char **  params 
)

Execute a parameterised SELECT query with ? placeholders.

Each ? in sql is substituted with the corresponding value from params (escaping is handled by the driver). Results are returned as a JSON array.

Parameters
poolConnection pool.
sqlSQL with ? placeholders.
paramsNULL-terminated array of string values. The number of values must match the number of ? placeholders.
Returns
A cJSON array of row objects, or NULL on failure. Caller must free with cJSON_Delete.

Execute a parameterised SELECT query with ? placeholders.

String substitution algorithm

  1. Pre-compute the final SQL length: original SQL + sum of all param lengths + 2 bytes per param for surrounding single quotes.
  2. Allocate a buffer of that size.
  3. Walk the original SQL character by character:
    • '?' → replace with 'value' (single-quote wrapped)
    • any other char → copy verbatim.
  4. Execute the constructed SQL via csilk_db_query_json_locked().

Security caveat

This is naive string substitution — NOT prepared-statement binding. Parameter values are NOT escaped for SQL special characters. A parameter containing "' OR '1'='1" will inject into the SQL verbatim.

Parameters
poolDatabase pool.
sqlSQL pattern with ? placeholders.
paramsNULL-terminated array of string values.

◆ csilk_db_register_driver()

int csilk_db_register_driver ( const char *  name,
csilk_db_driver_t *  driver 
)

Register a database driver implementation.

Makes the driver available for use with csilk_db_pool_new. The name must be unique (earlier registrations are not overwritten).

Parameters
nameDriver identifier string (e.g., "postgres"). Must remain valid for the program lifetime.
driverPointer to a csilk_db_driver_t with all function pointers populated. The struct must remain valid for the program lifetime.
Returns
0 on success, -1 if a driver with name is already registered.

Register a database driver implementation.

◆ csilk_db_sqlite_init()

void csilk_db_sqlite_init ( void  )

Internal: Register the built-in SQLite3 driver.

Called automatically by csilk_db_init. Not intended for direct use.

Internal: Register the built-in SQLite3 driver.

Call this at startup (e.g., in the app init callback) to make the "sqlite" driver available for csilk_db_create() calls.

Note
This function is idempotent-safe but typically called once.