https://gitlab.synchro.net/main/sbbs/-/merge_requests/538#note_7225
What I'm trying to say is that from JavaScript, just use exec() or query() as needed, without needing to do a prepare.
Because the prepare is done directly within the C code.
So both methods in JS receive the string with the SQL as parameters.
The difference is that exec() can return true/false (or the number of rows affected) and query() can return an array of result rows.
Each method must be implemented in the C code, for example.
```c++
static JSBool
js_sqlite_exec(JSContext *cx, uintN argc, jsval *arglist)
{
    JSObject *obj = JS_THIS_OBJECT(cx, arglist);
    jsval *argv = JS_ARGV(cx, arglist);
    char *sql;
    sqlite3 *db;
    char *errmsg = NULL;
    int rc;
    if (!JS_ConvertArguments(cx, argc, argv, "s", &sql))
        return JS_FALSE;
    // Obtener la conexión a la base de datos desde el objeto JavaScript
    db = JS_GetPrivate(cx, obj);
    if (!db)
        return JS_FALSE;
    rc = sqlite3_exec(db, sql, NULL, NULL, &errmsg);
    if (rc != SQLITE_OK) {
        JS_ReportError(cx, "Error al ejecutar SQL: %s", errmsg);
        sqlite3_free(errmsg);
        return JS_FALSE;
    }
    JS_SET_RVAL(cx, arglist, JSVAL_TRUE);
    return JS_TRUE;
}
```
and query method
```c++
static JSBool
js_sqlite_query(JSContext *cx, uintN argc, jsval *arglist)
{
    JSObject *obj = JS_THIS_OBJECT(cx, arglist);
    jsval *argv = JS_ARGV(cx, arglist);
    char *sql;
    sqlite3 *db;
    sqlite3_stmt *stmt;
    int rc;
    if (!JS_ConvertArguments(cx, argc, argv, "s", &sql))
        return JS_FALSE;
    // Obtener la conexión a la base de datos desde el objeto JavaScript
    db = JS_GetPrivate(cx, obj);
    if (!db)
        return JS_FALSE;
    rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        JS_ReportError(cx, "Error al preparar la consulta: %s", sqlite3_errmsg(db));
        return JS_FALSE;
    }
    JSObject *resultArray = JS_NewArrayObject(cx, 0, NULL);
    int index = 0;
    while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
        int colCount = sqlite3_column_count(stmt);
        JSObject *rowObj = JS_NewObject(cx, NULL, NULL, NULL);
        for (int i = 0; i < colCount; i++) {
            const char *colName = sqlite3_column_name(stmt, i);
            const char *colValue = (const char *)sqlite3_column_text(stmt, i);
            jsval val = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, colValue ? colValue : ""));
            JS_SetProperty(cx, rowObj, colName, &val);
        }
        jsval rowVal = OBJECT_TO_JSVAL(rowObj);
        JS_SetElement(cx, resultArray, index++, &rowVal);
    }
    sqlite3_finalize(stmt);
    if (rc != SQLITE_DONE) {
        JS_ReportError(cx, "Error al ejecutar la consulta: %s", sqlite3_errmsg(db));
        return JS_FALSE;
    }
    JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(resultArray));
    return JS_TRUE;
}
```
---
 ï¿ Synchronet ï¿ Vertrauen ï¿ Home of Synchronet ï¿ [vert/cvs/bbs].synchro.net