freeswitch/src/mod/languages/mod_spidermonkey_core_db/mod_spidermonkey_core_db.c

310 lines
7.5 KiB
C

/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthmct@yahoo.com>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthmct@yahoo.com>
*
*
* mod_spidermonkey_DB.c -- DB Javascript Module
*
*/
#include "mod_spidermonkey.h"
static const char modname[] = "DB";
struct db_obj {
switch_memory_pool_t *pool;
switch_core_db_t *db;
switch_core_db_stmt_t *stmt;
char *dbname;
char code_buffer[2048];
JSContext *cx;
JSObject *obj;
};
/* DB Object */
/*********************************************************************************/
static JSBool db_construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
switch_memory_pool_t *pool;
switch_core_db_t *db;
struct db_obj *dbo;
if (argc > 0) {
char *dbname = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
switch_core_new_memory_pool(&pool);
if (! (db = switch_core_db_open_file(dbname))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot Open DB!\n");
switch_core_destroy_memory_pool(&pool);
return JS_FALSE;
}
dbo = switch_core_alloc(pool, sizeof(*dbo));
dbo->pool = pool;
dbo->dbname = switch_core_strdup(pool, dbname);
dbo->cx = cx;
dbo->obj = obj;
dbo->db = db;
JS_SetPrivate(cx, obj, dbo);
return JS_TRUE;
}
return JS_FALSE;
}
static void db_destroy(JSContext *cx, JSObject *obj)
{
struct db_obj *dbo = JS_GetPrivate(cx, obj);
if (dbo) {
switch_memory_pool_t *pool = dbo->pool;
if (dbo->stmt) {
switch_core_db_finalize(dbo->stmt);
dbo->stmt = NULL;
}
switch_core_db_close(dbo->db);
switch_core_destroy_memory_pool(&pool);
pool = NULL;
}
}
static int db_callback(void *pArg, int argc, char **argv, char **columnNames)
{
struct db_obj *dbo = pArg;
char code[1024];
jsval rval;
int x = 0;
snprintf(code, sizeof(code), "~var _Db_RoW_ = {}");
eval_some_js(code, dbo->cx, dbo->obj, &rval);
for(x=0; x < argc; x++) {
snprintf(code, sizeof(code), "~_Db_RoW_[\"%s\"] = \"%s\"", columnNames[x], argv[x]);
eval_some_js(code, dbo->cx, dbo->obj, &rval);
}
snprintf(code, sizeof(code), "~%s(_Db_RoW_)", dbo->code_buffer);
eval_some_js(code, dbo->cx, dbo->obj, &rval);
snprintf(code, sizeof(code), "~delete _Db_RoW_");
eval_some_js(code, dbo->cx, dbo->obj, &rval);
return 0;
}
static JSBool db_exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
struct db_obj *dbo = JS_GetPrivate(cx, obj);
*rval = BOOLEAN_TO_JSVAL( JS_TRUE );
if (argc > 0) {
char *sql = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
char *err = NULL;
void *arg = NULL;
switch_core_db_callback_func_t cb_func = NULL;
if (argc > 1) {
char *js_func = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
switch_copy_string(dbo->code_buffer, js_func, sizeof(dbo->code_buffer));
cb_func = db_callback;
arg = dbo;
}
switch_core_db_exec(dbo->db, sql, cb_func, arg, &err);
if (err) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error %s\n", err);
switch_core_db_free(err);
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
}
}
return JS_TRUE;
}
static JSBool db_next(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
struct db_obj *dbo = JS_GetPrivate(cx, obj);
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
if (dbo->stmt) {
int running = 1;
while (running < 5000) {
int result = switch_core_db_step(dbo->stmt);
if (result == SQLITE_ROW) {
*rval = BOOLEAN_TO_JSVAL( JS_TRUE );
break;
} else if (result == SQLITE_BUSY) {
running++;
continue;
}
switch_core_db_finalize(dbo->stmt);
dbo->stmt = NULL;
break;
}
}
return JS_TRUE;
}
static JSBool db_fetch(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
struct db_obj *dbo = JS_GetPrivate(cx, obj);
int colcount = switch_core_db_column_count(dbo->stmt);
char code[1024];
int x;
snprintf(code, sizeof(code), "~var _dB_RoW_DaTa_ = {}");
eval_some_js(code, dbo->cx, dbo->obj, rval);
if (*rval == JS_FALSE) {
return JS_TRUE;
}
for (x = 0; x < colcount; x++) {
snprintf(code, sizeof(code), "~_dB_RoW_DaTa_[\"%s\"] = \"%s\"",
(char *) switch_core_db_column_name(dbo->stmt, x),
(char *) switch_core_db_column_text(dbo->stmt, x));
eval_some_js(code, dbo->cx, dbo->obj, rval);
if (*rval == JS_FALSE) {
return JS_TRUE;
}
}
JS_GetProperty(cx, obj, "_dB_RoW_DaTa_", rval);
return JS_TRUE;
}
static JSBool db_prepare(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
struct db_obj *dbo = JS_GetPrivate(cx, obj);
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
if (dbo->stmt) {
switch_core_db_finalize(dbo->stmt);
dbo->stmt = NULL;
}
if (argc > 0) {
char *sql = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
if(switch_core_db_prepare(dbo->db, sql, 0, &dbo->stmt, 0)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error %s\n", switch_core_db_errmsg(dbo->db));
} else {
*rval = BOOLEAN_TO_JSVAL( JS_TRUE );
}
}
return JS_TRUE;
}
enum db_tinyid {
DB_NAME
};
static JSFunctionSpec db_methods[] = {
{"exec", db_exec, 1},
{"next", db_next, 0},
{"fetch", db_fetch, 1},
{"prepare", db_prepare, 0},
{0}
};
static JSPropertySpec db_props[] = {
{"path", DB_NAME, JSPROP_READONLY|JSPROP_PERMANENT},
{0}
};
static JSBool db_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
JSBool res = JS_TRUE;
struct db_obj *dbo = JS_GetPrivate(cx, obj);
char *name;
int param = 0;
name = JS_GetStringBytes(JS_ValueToString(cx, id));
/* numbers are our props anything else is a method */
if (name[0] >= 48 && name[0] <= 57) {
param = atoi(name);
} else {
return JS_TRUE;
}
switch(param) {
case DB_NAME:
*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, dbo->dbname));
break;
}
return res;
}
JSClass db_class = {
"DB", JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, db_getProperty, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, db_destroy, NULL, NULL, NULL,
db_construct
};
switch_status_t spidermonkey_load(JSContext *cx, JSObject *obj)
{
JS_InitClass(cx,
obj,
NULL,
&db_class,
db_construct,
3,
db_props,
db_methods,
db_props,
db_methods
);
return SWITCH_STATUS_SUCCESS;
}
const sm_module_interface_t DB_module_interface = {
/*.name = */ modname,
/*.spidermonkey_load*/ spidermonkey_load,
/*.next*/ NULL
};
SWITCH_MOD_DECLARE(switch_status_t) spidermonkey_init(const sm_module_interface_t **module_interface)
{
*module_interface = &DB_module_interface;
return SWITCH_STATUS_SUCCESS;
}