/* * SPL - The SPL Programming Language * Copyright (C) 2004, 2005 Clifford Wolf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * mod_sql_sqlite.c: Module for SQLite bindings */ /** * This module implements the SQLite database driver. * * Load this module and the [[sql:]] module and pass "sqlite" as backend * driver name to [[sql:sql_connect()]]; */ #include #include #include #include "spl.h" #include "compat.h" #include "mod_sql.h" extern void SPL_ABI(spl_mod_sql_sqlite_init)(struct spl_vm *vm, struct spl_module *mod, int restore); extern void SPL_ABI(spl_mod_sql_sqlite_done)(struct spl_vm *vm, struct spl_module *mod); struct callback_args { struct spl_task *task; struct spl_node *result; }; int callback(void *ca_vp, int argc, char **values, char **names) { struct callback_args *ca = ca_vp; struct spl_node *n = spl_get(0); for (int i=0; itask, n, name_base, values[i] ? SPL_NEW_STRING_DUP(values[i]) : spl_get(0), SPL_CREATE_LOCAL); } spl_create(ca->task, ca->result, NULL, n, SPL_CREATE_LOCAL); return 0; } static struct spl_node *sqlite_query_callback(struct spl_task *task, void *backend_data, const char *query) { sqlite3 *db = backend_data; char *errmsg = 0; int rc; struct spl_node *result = spl_get(0); struct callback_args ca; ca.task = task; ca.result = result; while (1) { rc = sqlite3_exec(db, query, callback, &ca, &errmsg); if ( rc != SQLITE_BUSY ) break; sleep(1); } if( rc != SQLITE_OK ) { spl_put(task->vm, result); spl_clib_exception(task, "SqlEx", "description", SPL_NEW_SPL_STRING(spl_string_printf(0, 0, 0, "SQLite: SQL Error on '%s': %s!\n", query, errmsg ? errmsg : "Unknown error")), NULL); return 0; } return result; } static void sqlite_close_callback(struct spl_vm UNUSED(*vm), void *backend_data) { sqlite3_close(backend_data); } static void sqlite_open_callback(struct spl_task *task, struct spl_node *node, const char *data) { struct sql_hnode_data *hnd = malloc(sizeof(struct sql_hnode_data)); char *filename; if (data[0] != '/') my_asprintf(&filename, "%s/%s", task->vm->current_dir_name ? task->vm->current_dir_name : ".", data); else filename = strdup(data); sqlite3 *backend_data; int rc = sqlite3_open(filename, &backend_data); hnd->backend_data = backend_data; if( rc ) { spl_clib_exception(task, "SqlEx", "description", SPL_NEW_SPL_STRING(spl_string_printf(0, 0, 0, "SQLite: Can't open database %s: %s!\n", data, sqlite3_errmsg(hnd->backend_data))), NULL); sqlite3_close((sqlite3*)hnd->backend_data); free(filename); free(hnd); return; } hnd->query_callback = sqlite_query_callback; hnd->close_callback = sqlite_close_callback; node->hnode_data = hnd; free(filename); } void SPL_ABI(spl_mod_sql_sqlite_init)(struct spl_vm *vm, struct spl_module UNUSED(*mod), int restore) { if (!restore) spl_module_load(vm, "sql", 0); sql_register_backend(vm, "sqlite", sqlite_open_callback); } void SPL_ABI(spl_mod_sql_sqlite_done)(struct spl_vm *vm, struct spl_module UNUSED(*mod)) { sql_unregister_backend(vm, "sqlite"); }