init here

This commit is contained in:
2025-11-26 21:32:41 +03:00
commit 33c97acade
91 changed files with 9155 additions and 0 deletions

160
си/sckulya.c Normal file
View File

@@ -0,0 +1,160 @@
#include "sckulya.h"
int64_t tri_sqlite_open(TString filename, TString *error) {
sqlite3* out_db = 0;
int rc = sqlite3_open((const char*) filename->body, &out_db);
if(rc != SQLITE_OK) {
if(out_db) {
sqlite3_close(out_db);
}
const char* msg = sqlite3_errmsg(out_db);
if(!msg) {
msg = "Unknown error";
}
int64_t len = (int64_t)strlen(msg);
*error = tri_newString(len, len, (char*)msg);
}
sqlite3_busy_timeout(out_db, 5000);
return (int64_t) out_db;
}
int tri_sqlite_close(int64_t db) {
if (!db) return SQLITE_MISUSE;
return sqlite3_close((sqlite3*) db);
}
void tri_sqlite_exec(int64_t db, TString query, TString *error) {
char* errmsg = NULL;
int rc = sqlite3_exec((sqlite3*) db, (const char*) query->body, NULL, NULL, &errmsg);
if (errmsg) {
int64_t len = (int64_t)strlen(errmsg);
*error = tri_newString(len, len, errmsg);
sqlite3_free(errmsg);
}
}
void escape_and_append (const unsigned char *s, char* buf, size_t* len) {
for (; *s; ++s) {
char esc = 0;
switch (*s) {
case '\\': esc = '\\'; break;
case '\b': esc = 'b'; break;
case '\f': esc = 'f'; break;
case '\n': esc = 'n'; break;
case '\r': esc = 'r'; break;
case '\t': esc = 't'; break;
default: break;
}
if (esc) {
buf[(*len)++] = '\\';
buf[(*len)++] = esc;
} else {
buf[(*len)++] = *s;
}
}
};
int tri_sqlite_query(int64_t db, TString query, TString *result, TString *error) {
sqlite3_stmt *stmt = NULL;
int rc = sqlite3_prepare_v2((sqlite3*)db, (const char*) query->body, -1, &stmt, NULL);
if (rc != SQLITE_OK) {
if (error) {
const char *msg = sqlite3_errmsg((sqlite3*)db);
if (!msg) msg = "Unknown error";
int64_t len = (int64_t)strlen(msg);
*error = tri_newString(len, len, (char*)msg);
}
return rc;
}
size_t cap = 1024;
size_t len = 0;
char *buf = malloc(cap);
if (!buf) {
sqlite3_finalize(stmt);
if (error) *error = tri_newString(0,0,"Out of memory");
return SQLITE_NOMEM;
}
buf[len++] = '[';
int first_row = 1;
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
if (!first_row) { buf[len++] = ','; } else first_row = 0;
buf[len++] = '{';
int ncol = sqlite3_column_count(stmt);
for (int i = 0; i < ncol; ++i) {
if (i) { buf[len++] = ','; }
const char *colname = sqlite3_column_name(stmt, i);
/* "colname": */
// strlen(colname) + 4;
buf[len++] = '\"';
escape_and_append((const unsigned char*)colname, buf, &len);
buf[len++] = '\"';
buf[len++] = ':';
int type = sqlite3_column_type(stmt, i);
if (type == SQLITE_INTEGER) {
long long v = sqlite3_column_int64(stmt, i);
char tmp[32];
int n = snprintf(tmp, sizeof(tmp), "%lld", v);
memcpy(buf + len, tmp, n); len += n;
} else if (type == SQLITE_FLOAT) {
double v = sqlite3_column_double(stmt, i);
char tmp[64];
int n = snprintf(tmp, sizeof(tmp), "%g", v);
memcpy(buf + len, tmp, n); len += n;
} else if (type == SQLITE_NULL) {
memcpy(buf + len, "null", 4); len += 4;
} else {
const unsigned char *txt = sqlite3_column_text(stmt, i);
if (!txt) {
memcpy(buf + len, "null", 4); len += 4;
} else {
buf[len++] = '\"';
escape_and_append(txt, buf, &len);
buf[len++] = '\"';
}
}
}
buf[len++] = '}';
}
/* finalize and handle errors */
if (rc != SQLITE_DONE) {
const char *msg = sqlite3_errmsg((sqlite3*)db);
if (error) {
if (!msg) msg = "Unknown error";
int64_t mlen = (int64_t)strlen(msg);
*error = tri_newString(mlen, mlen, (char*)msg);
}
sqlite3_finalize(stmt);
free(buf);
return rc;
}
buf[len++] = ']';
buf[len] = '\0';
sqlite3_finalize(stmt);
if (result) {
*result = tri_newString((int64_t)len, (int64_t)len, buf);
}
free(buf);
return SQLITE_OK;
}