21 uint32_t predicate_count;
22 uint64_t symbolic_weight;
31static uint64_t cwist_db_integer_root(uint64_t value) {
32 if (value == 0)
return 0;
34 uint64_t y = (x + 1) >> 1;
37 y = (x + value / x) >> 1;
47static bool cwist_db_is_alpha(
char c) {
48 return (c >=
'A' && c <=
'Z') || (c >=
'a' && c <=
'z');
58static bool cwist_db_match_keyword(
const char *sql,
size_t pos,
const char *kw) {
61 char current = sql[pos + i];
62 if (!current)
return false;
63 if ((
char)toupper((
unsigned char)current) != kw[i]) {
69 char prev = sql[pos - 1];
70 if (cwist_db_is_alpha(prev))
return false;
72 char next = sql[pos + i];
73 if (cwist_db_is_alpha(next))
return false;
82static cwist_db_plan_hint cwist_db_analyze_sql(
const char *sql) {
83 cwist_db_plan_hint hint = {0, 0, 0};
84 if (!sql)
return hint;
85 size_t len = strlen(sql);
86 uint64_t accum = 0xcbf29ce484222325ULL;
88 for (
size_t i = 0; i < len; ++i) {
89 char upper = (char)toupper((
unsigned char)sql[i]);
90 accum ^= (uint64_t)upper;
91 accum *= 0x100000001b3ULL;
94 else if (upper ==
')' && depth > 0)
97 if (upper ==
'J' && cwist_db_match_keyword(sql, i,
"JOIN")) {
99 }
else if (upper ==
'W' && cwist_db_match_keyword(sql, i,
"WHERE")) {
100 hint.predicate_count++;
101 }
else if (upper ==
'A' && cwist_db_match_keyword(sql, i,
"AND")) {
102 hint.predicate_count++;
103 }
else if (upper ==
'O' && cwist_db_match_keyword(sql, i,
"OR")) {
104 hint.predicate_count++;
107 hint.symbolic_weight = accum ^ ((uint64_t)depth << 48);
116static void cwist_db_apply_hint(sqlite3 *conn,
const cwist_db_plan_hint *hint) {
117 if (!conn || !hint)
return;
118 uint64_t complexity = hint->symbolic_weight + ((uint64_t)hint->join_count * 131ULL) +
119 ((uint64_t)hint->predicate_count * 53ULL) + 1ULL;
120 uint64_t root = cwist_db_integer_root(complexity);
121 int busy_ms = 50 + (int)(root % 350);
122 sqlite3_busy_timeout(conn, busy_ms);
123 if (hint->join_count >= 2) {
124 sqlite3_exec(conn,
"PRAGMA temp_store = MEMORY;", NULL, NULL, NULL);
126 if (hint->predicate_count >= 3) {
127 sqlite3_exec(conn,
"PRAGMA cache_spill = 0;", NULL, NULL, NULL);
141 cJSON_AddNumberToObject(err.
error.
err_json,
"sqlite_rc", rc);
142 cJSON_AddStringToObject(err.
error.
err_json,
"message", msg ? msg :
"Unknown Error");
170 int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX;
171 if (strncmp(path,
"file:", 5) == 0) flags |= SQLITE_OPEN_URI;
172 int rc = sqlite3_open_v2(path, &(*db)->conn, flags, NULL);
174 cwist_error_t sql_err = make_sqlite_error(rc, (
char *)sqlite3_errmsg((*db)->conn));
175 sqlite3_close((*db)->conn);
200 if (!db || !buf || len == 0) {
212 sqlite3_open_v2(
":memory:", &(*db)->conn,
213 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, NULL);
215 cwist_error_t sql_err = make_sqlite_error(rc, (
char *)sqlite3_errmsg((*db)->conn));
216 sqlite3_close((*db)->conn);
224 unsigned char *image = (
unsigned char *)sqlite3_malloc64((sqlite3_uint64)len);
226 sqlite3_close((*db)->conn);
232 memcpy(image, buf, len);
234 unsigned flags = SQLITE_DESERIALIZE_FREEONCLOSE |
235 (readonly ? SQLITE_DESERIALIZE_READONLY : SQLITE_DESERIALIZE_RESIZEABLE);
236 rc = sqlite3_deserialize((*db)->conn,
"main", image, (sqlite3_int64)len, (sqlite3_int64)len,
238 if (rc != SQLITE_OK) {
239 cwist_error_t sql_err = make_sqlite_error(rc, (
char *)sqlite3_errmsg((*db)->conn));
240 sqlite3_close((*db)->conn);
259 if (!db || !db->
conn || !out || !out_len) {
266 sqlite3_int64 size = 0;
267 unsigned char *image = sqlite3_serialize(db->
conn,
"main", &size, 0);
268 if (!image || size <= 0) {
269 if (image) sqlite3_free(image);
282 memcpy(copy, image, (
size_t)size);
286 *out_len = (size_t)size;
298 sqlite3_close(db->
conn);
314 if (!db || !db->
conn || !sql) {
320 cwist_db_plan_hint hint = cwist_db_analyze_sql(sql);
321 cwist_db_apply_hint(db->
conn, &hint);
322 int rc = sqlite3_exec(db->
conn, sql, 0, 0, &zErrMsg);
324 if (rc != SQLITE_OK) {
326 sqlite3_free(zErrMsg);
347static int query_callback(
void *data,
int argc,
char **argv,
char **azColName) {
348 query_context *ctx = (query_context *)data;
349 cJSON *row = cJSON_CreateObject();
351 for (
int i = 0; i < argc; i++) {
356 cJSON_AddStringToObject(row, azColName[i], argv[i]);
358 cJSON_AddNullToObject(row, azColName[i]);
362 cJSON_AddItemToArray(ctx->rows, row);
381 if (!db || !db->
conn || !sql) {
388 ctx.rows = cJSON_CreateArray();
391 cwist_db_plan_hint hint = cwist_db_analyze_sql(sql);
392 cwist_db_apply_hint(db->
conn, &hint);
393 int rc = sqlite3_exec(db->
conn, sql, query_callback, &ctx, &zErrMsg);
395 if (rc != SQLITE_OK) {
396 cJSON_Delete(ctx.rows);
398 sqlite3_free(zErrMsg);
428static char *build_insert_sql(
const char *table,
const cJSON *obj) {
430 int count = cJSON_GetArraySize((cJSON *)obj);
431 if (
count <= 0)
return NULL;
434 char *cols_buf = (
char *)sqlite3_malloc(
count * 64 + 16);
435 char *vals_buf = (
char *)sqlite3_malloc(
count * 256 + 16);
436 if (!cols_buf || !vals_buf) {
437 sqlite3_free(cols_buf);
438 sqlite3_free(vals_buf);
444 const cJSON *child = obj->child;
449 snprintf(col_frag,
sizeof(col_frag), first ?
"\"%s\"" :
",\"%s\"", child->string);
450 size_t cols_cap = (size_t)(
count * 64 + 16);
451 size_t cols_used = strlen(cols_buf);
452 if (cols_used < cols_cap - 1) strncat(cols_buf, col_frag, cols_cap - 1 - cols_used);
455 char *val_frag = NULL;
456 if (cJSON_IsString(child)) {
457 val_frag = sqlite3_mprintf(first ?
"%Q" :
",%Q", child->valuestring);
458 }
else if (cJSON_IsNumber(child)) {
459 val_frag = sqlite3_mprintf(first ?
"%g" :
",%g", child->valuedouble);
460 }
else if (cJSON_IsTrue(child)) {
461 val_frag = sqlite3_mprintf(first ?
"1" :
",1");
462 }
else if (cJSON_IsFalse(child)) {
463 val_frag = sqlite3_mprintf(first ?
"0" :
",0");
464 }
else if (cJSON_IsNull(child)) {
465 val_frag = sqlite3_mprintf(first ?
"NULL" :
",NULL");
468 char *serialised = cJSON_PrintUnformatted(child);
470 val_frag = sqlite3_mprintf(first ?
"%Q" :
",%Q", serialised);
476 sqlite3_free(cols_buf);
477 sqlite3_free(vals_buf);
480 size_t vals_cap = (size_t)(
count * 256 + 16);
481 size_t vals_used = strlen(vals_buf);
482 if (vals_used < vals_cap - 1) strncat(vals_buf, val_frag, vals_cap - 1 - vals_used);
483 sqlite3_free(val_frag);
489 char *sql = sqlite3_mprintf(
"INSERT INTO \"%s\" (%s) VALUES (%s);", table, cols_buf, vals_buf);
490 sqlite3_free(cols_buf);
491 sqlite3_free(vals_buf);
510 if (!db || !table || !json_str)
return err;
515 effective_cfg = *heal_cfg;
517 memset(&effective_cfg, 0,
sizeof(effective_cfg));
520 if (schema && !effective_cfg.
schema) effective_cfg.
schema = schema;
525 fprintf(stderr,
"[CWIST-DB] insert_healed: healing failed for table '%s'\n", table);
532 cJSON *validated = NULL;
535 fprintf(stderr,
"[CWIST-DB] insert_healed: Zod validation failed for table '%s':\n",
541 if (validated) cJSON_Delete(validated);
545 cJSON *obj = cJSON_Parse(healed.
json);
547 if (!obj || !cJSON_IsObject(obj)) {
548 if (obj) cJSON_Delete(obj);
552 char *sql = build_insert_sql(table, obj);
554 if (!sql)
return err;
583 cJSON *conforming = cJSON_CreateArray();
591 cJSON_ArrayForEach(row, all) {
594 cJSON *clone = cJSON_Duplicate(row, 1);
595 if (clone) cJSON_AddItemToArray(conforming, clone);
600 *result = conforming;
Memory allocation wrappers backed by libttak.
void cwist_free(void *ptr)
Free memory obtained via cwist_alloc/cwist_strdup/etc.
void * cwist_alloc(size_t size)
Allocate zeroed memory tracked by libttak.
Database operations wrapper (SQLite3).
cwist_error_t cwist_db_query(cwist_db *db, const char *sql, cJSON **result)
Execute a SQL query and collect every row into a cJSON array.
cwist_error_t cwist_db_open(cwist_db **db, const char *path)
Open a SQLite database and wrap the resulting connection in a CWIST handle.
cwist_error_t cwist_db_exec(cwist_db *db, const char *sql)
Execute an arbitrary SQL statement string without returning rows.
cwist_error_t cwist_db_serialize(cwist_db *db, void **out, size_t *out_len)
Serialize a CWIST database into a freshly allocated image buffer.
cwist_error_t cwist_db_query_strict(cwist_db *db, const char *sql, cJSON **result, const cwist_schema_t *schema)
Execute a query and require the result rows to satisfy a CWIST schema.
cwist_error_t cwist_db_open_memory(cwist_db **db, const void *buf, size_t len, int readonly)
Open a CWIST database from an in-memory SQLite image.
void cwist_db_close(cwist_db *db)
Close a CWIST database wrapper and its underlying SQLite connection.
cwist_error_t cwist_db_insert_healed(cwist_db *db, const char *table, const char *json_str, const cwist_schema_t *schema, const cwist_heal_config_t *heal_cfg)
Heal, validate, and insert a JSON object into a table.
@ CWIST_ERR_INT16
used when checking common errcodes in Unix/Linux
cwist_error_t make_error(cwist_errtype_t type)
Creates an error object initialized with the specified type.
Self-Healing JSON Recovery Layer (CWIST)
void cwist_heal_result_free(cwist_heal_result_t *r)
Free resources owned by a cwist_heal_result_t.
cwist_heal_result_t cwist_json_heal(const char *input, const cwist_heal_config_t *cfg)
Attempt to heal a potentially broken JSON string.
Wrapper for Database Operations. Currently uses SQLite3.
Integrated error structure used throughout the system.
__prim_cwist_error_t error
Configuration passed to cwist_json_heal().
const cwist_schema_t * schema
Schema for L2 alignment (may be NULL).
double threshold
Min confidence (0.0–1.0) to accept recovery. Default: 0.8.
Result of a healing attempt.
char * json
Healed JSON string (free with cwist_heal_result_free). NULL on failure.
A complete schema: array of field descriptors + count.
Result returned by cwist_zod_validate() / cwist_zod_parse().
Unified error code and type definitions for the CWIST system layer.
Strict JSON schema validation (Zod-style) for CWIST.
cwist_zod_result_t cwist_zod_validate(const cJSON *json, const cwist_schema_t *schema)
Strictly validate an already-parsed cJSON object against a schema.
void cwist_zod_print_errors(const cwist_zod_result_t *r)
Print all validation errors to stderr.
cwist_zod_result_t cwist_zod_parse(const char *raw, const cwist_schema_t *schema, cJSON **out)
Parse a raw JSON string and validate it in one step.