12#define META_FILE_NAME "abrain.c"
28#define BrainT ((typeof(MqContextST)) BrainTT)
29#define BRAINCTX ((struct BrainCtxS*const)mqctx)
30#define MQCTX ((MQ_CTX*const)brain)
31#define META_CONTEXT_S mqctx
32#define SETUP_brain struct BrainCtxS*const brain = BRAINCTX
33#define SETUP_db sqlite3*const db = brain->db
37 register sqlite3_stmt *hdl= brain->sh
40 MK_STRN key; MK_SIZE klen; \
41 register sqlite3_stmt *hdl= brain->sh
42#define DbErrorCheck(f) \
43 if (unlikely((f) != SQLITE_OK)) { \
44 MkErrorSetC_4M (mqctx, sqlite3_errmsg(brain->db), __func__, sqlite3_extended_errcode(brain->db)); \
47#define CHECK_ARGS(s) \
48 if (MqReadGetNumItems(mqctx)) { \
49 return MkErrorSetV_4M (mqctx, __func__, SQLITE_ERROR, "usage: %s (%s)\n", __func__, s); \
51#define check_sqlite(E) \
52 if (unlikely((E) != SQLITE_OK))
53#define check_NULL(E) \
54 if (unlikely((E) == NULL))
56#define DB_PREPARE_MAX 100
80static void __attribute__ ((noreturn))
83 fprintf (stderr,
"usage: %s [OPTION]... [ARGUMENT]...\n", base);
85 fputs (
" This tool is the database server of NHI1.\n", stderr);
86 fputs (
" main: https://theBrain.nhi1.de\n", stderr);
87 fputs (
" tool: https://thebrain.nhi1.de/theBrain.htm\n", stderr);
89 fprintf (stderr,
" %s [ARGUMENT]... syntax:\n", base);
90 fprintf (stderr,
" aclient [OPTION]... %c %s [OPTION]... [ARGUMENT]\n",
MK_ALFA, base);
92 fputs (
MqHelp (NULL), stderr);
94 fprintf (stderr,
" %s [OPTION]:\n", base);
95 fputs (
" -h, --help print this help\n", stderr);
101#define READ_C(n) MK_STRN n; MkErrorCheck(MqReadSTR(mqctx,&n))
120#define IdxGet(...) IdxGet_RT(MK_RT_CALL __VA_ARGS__)
124 if (brain->prepStmt[idx] != NULL) {
126 brain->prepStmt[idx] = NULL;
128 brain->inEnd[idx] = NULL;
130 brain->outEnd[idx] = NULL;
137#define IdxFinalize(...) IdxFinalize_RT(MK_RT_CALL __VA_ARGS__)
150 MkErrorCheck (
IdxGet (mqctx, &idx));
152 MkErrorSetV_4M (mqctx, __func__, SQLITE_ERROR,
"the prepare-index '%i' was NOT defined", idx);
155 *pInType = brain->inType[idx];
156 *pInEnd = brain->inEnd[idx];
157 *pOutType = brain->outType[idx];
158 *pOutEnd = brain->outEnd[idx];
164#define HdlGet(...) HdlGet_RT(MK_RT_CALL __VA_ARGS__)
169 if (brain->db != NULL) {
170 for (
MK_I32 idx=0; idx<brain->prepare_start; idx++) {
173 brain->prepare_start=0;
183#define ctxCleanup(...) ctxCleanup_RT(MK_RT_CALL __VA_ARGS__)
224 switch (sqlite3_column_type(hdl,idx)) {
226 switch (sqlite3_column_bytes(hdl,idx)) {
235 case SQLITE_FLOAT:
return MK_DBLT;
236 case SQLITE_BLOB:
return MK_BINT;
237 case SQLITE_TEXT:
return MK_STRT;
238 case SQLITE_NULL:
return MK_BINT;
243#define case1(t,f,c) \
246 MkErrorCheck(MkBufferGet ## c(buf,&dat)); \
247 DbErrorCheck(f(hdl,idx,dat)); \
274#define GetFromDBnat(...) GetFromDBnat_RT(MK_RT_CALL __VA_ARGS__)
300#define GetFromDBary(...) GetFromDBary_RT(MK_RT_CALL __VA_ARGS__)
306 sqlite3_stmt *hdl=NULL;
307 MK_STRN inType=NULL, inEnd=NULL;
308 MK_STRN outType=NULL, outEnd=NULL;
311 MkErrorCheck(
HdlGet(mqctx, &hdl, &inType, &inEnd, &outType, &outEnd));
318 if (inType && inType < inEnd) {
322 "the buffer type '%c' does not match database type '%c'",
377 switch (sqlite3_step(hdl)) {
380 for (idx=0,pos=outType; idx<sqlite3_column_count(hdl); idx++,pos++) {
382 switch (sqlite3_column_type(hdl,idx)) {
404 MkErrorSetC_4M (mqctx, sqlite3_errmsg(brain->db), __func__, sqlite3_extended_errcode(brain->db));
419 DbErrorCheck(sqlite3_exec(brain->db,sql, NULL, NULL, NULL));
438 idx = brain->prepare_start;
445 while (sql != NULL && *sql !=
'\0') {
453 brain->inType[idx] = NULL;
454 brain->inEnd[idx] = NULL;
455 brain->outType[idx] = NULL;
456 brain->outEnd[idx] = NULL;
458 for (start=sql; start<end && *start !=
'/' && *start !=
';'; start++);
460 if (start == end || *start++ !=
'/' || *start++ !=
'*')
goto update;
464 for (; start<end && isspace(*start); start++);
466 if (start >= end-3 || strncmp(start,
"in:", 3))
goto out;
469 for (type=start; start<end && isupper(*start); start++);
470 if (start == end)
goto out;
473 brain->inEnd[idx] = brain->inType[idx] + (start-type);
474 *brain->inEnd[idx] =
'\0';
479 for (; start<end && isspace(*start); start++);
481 if (start >= end-4 || strncmp(start,
"out:", 4))
goto update;
484 for (type=start; start<end && isupper(*start); start++);
485 if (start == end)
goto update;
488 brain->outEnd[idx] = brain->outType[idx] + (start-type);
489 *brain->outEnd[idx] =
'\0';
493 brain->prepare_start=idx+1;
494 DbErrorCheck(sqlite3_prepare_v2(brain->db, sql, -1, &brain->prepStmt[idx], &sql));
509 MkErrorCheck(
IdxGet(mqctx, &idx));
532 MkErrorCheck(
MqReadSTR(mqctx,&dbstorage));
534 if (dbstorage == NULL) {
535 return MkErrorSetC_4M (mqctx,
"storage-file is empty or invalid", __func__, SQLITE_ERROR);
538 MkDLogV(mqctx,5,
"try to open database '%s'\n", dbstorage);
580 brain->prepare_start=0;
#define GetFromDBary(...)
static enum MkErrorE BrainCleanup(MQ_SERVICE_CALL_ARGS)
static enum MkErrorE HdlGet_RT(MK_RT mkrt, MQ_CTX const mqctx, sqlite3_stmt **phdl, MK_STRN *pInType, MK_STRN *pInEnd, MK_STRN *pOutType, MK_STRN *pOutEnd)
static enum MkErrorE FINA(MQ_SERVICE_CALL_ARGS)
int main(const int argc, MK_STRN argv[])
main entry-point for the tool
static enum MkErrorE OPEN(MQ_SERVICE_CALL_ARGS)
static enum MkErrorE STEP(MQ_SERVICE_CALL_ARGS)
static enum MkErrorE GetFromDBary_RT(MK_RT mkrt, MQ_CTX const mqctx, enum MkTypeE ntype, sqlite3_stmt *hdl, MK_I32 idx)
static enum MkErrorE BrainFactory(MQ_CALLBACK_FACTORY_CTOR_ARGS)
static enum MkErrorE IdxGet_RT(MK_RT mkrt, MQ_CTX const mqctx, MK_I32 *pidx)
static enum MkTypeE GetTypeE(MK_STRB t)
static MK_TYP BrainTT
link to the MqErrorS object
static enum MkErrorE BrainSetup(MQ_SERVICE_CALL_ARGS)
static enum MkErrorE EXEC(MQ_SERVICE_CALL_ARGS)
static enum MkTypeE GetTypeD(sqlite3_stmt *hdl, MK_I32 idx)
static void BrainHelp(const char *base)
display help using -h or --help command-line option
#define GetFromDBnat(...)
static MK_STRB GetTypeS(enum MkTypeE const ntype)
static enum MkErrorE IdxFinalize_RT(MK_RT mkrt, MQ_CTX const mqctx, MK_I32 idx)
static enum MkErrorE ctxCleanup_RT(MK_RT mkrt, MQ_CTX const mqctx)
static enum MkErrorE PREP(MQ_SERVICE_CALL_ARGS)
static enum MkErrorE GetFromDBnat_RT(MK_RT mkrt, MQ_CTX const mqctx, enum MkTypeE ntype, sqlite3_stmt *hdl, MK_I32 idx)
static enum MkErrorE CLOS(MQ_SERVICE_CALL_ARGS)
#define MkBufferGetSTR(...)
#define MkBufferGetI32(...)
#define MkBufferGetType1(...)
#define MkBufferCastTo_E(...)
#define MkBufferSetSTR(...)
#define MkBufferCreate(...)
#define MkBufferDelete(x)
#define MkBufferListCreateVC(...)
#define MkBufferListDelete(x)
#define MkErrorStack_1X(...)
#define MkErrorSetV_4M(m,...)
#define MkErrorSetC_4M(m,...)
static MkBinaryR MkBinaryCreate(MK_SIZE size, MK_BINN data)
#define MkDLogV(x, _debug, printfmt,...)
MK_STR MkSysStrNDup(MK_OBJN fmtobj, MK_STRN const str, MK_SIZE const len)
#define MkSysFree(pointer)
#define MQ_SERVICE_CALL_ARGS
#define MqLinkCreate_E(...)
#define MqProcessEvent_E(...)
bool MqReadItemExists(MQ_CTX const ctx)
#define MqSendL_START(...)
#define MqSendRETURN(...)
#define MqServiceCreate(...)
#define MqServiceDelete(...)
#define MqContextCreate(...)
#define MQ_CALLBACK_FACTORY_CTOR_ARGS
#define MqFactoryNew_E(...)
#define MqFactoryAdd_2(fct, ident)
MK_STR MqHelp(MK_STRN tool)
the local context of the server tool
sqlite3 * db
database handle
MK_STR inEnd[DB_PREPARE_MAX]
array prepared statement input types end pointer
MK_STR outType[DB_PREPARE_MAX]
array prepared statement output types string
MK_STRN storage
storage file
sqlite3_stmt * prepStmt[DB_PREPARE_MAX]
array prepared statement pointer
MK_STR outEnd[DB_PREPARE_MAX]
array prepared statement output types end pointer
MK_STR inType[DB_PREPARE_MAX]
array prepared statement input types string
MK_I32 prepare_start
point to the next empty prepare empty
MQ_CTXR mqctx
the LibMqMsgque context object
MK_BUF buf
context local storage
struct MkBufferS::@5 storage
struct MqCallbackS ServerCleanup
struct MqCallbackS ServerSetup