/* * Copyright (C) 2010 Dennis Schafroth > * Copyright (C) 2010 Johannes Thoma * Copyright (C) 2010 - 2013 LINBIT Information Technologies GmbH * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "db_api.h" #include "config.h" #ifndef HAVE_SQLITE /* dummy function to implement a open that fails */ int db_sqlite2_open(const char *file, db_conn_p * conn_p) { return DB_ERROR; } #else #include #include #include #include #include #include #include #include "db_sqlite2.h" #include static struct db_sqlite_fns { sqlite *(*sqlite_open_fn) (const char *, int, char **); void (*sqlite_close_fn) (sqlite *); int (*sqlite_exec_fn) (sqlite *, char *, int (*)(void *, int, char **, char **), void *, char **); int (*sqlite_compile_fn) (sqlite *, const char *, const char **, sqlite_vm **, char **); int (*sqlite_step_fn) (sqlite_vm *, int *, const char ***, const char ***); int (*sqlite_finalize_fn) (sqlite_vm *, char **); } f; static char *errmsg; static void *dl_handle; static void db_sqlite_dlopen(void) { csync_debug(2, "Opening shared library libsqlite.so\n"); dl_handle = dlopen("libsqlite.so", RTLD_LAZY); if (dl_handle == NULL) { csync_debug(1, "Libsqlite.so not found, trying libsqlite.so.0\n"); dl_handle = dlopen("libsqlite.so.0", RTLD_LAZY); if (dl_handle == NULL) { csync_fatal ("Could not open libsqlite.so: %s\n" "Please install sqlite client library (libsqlite) or use other database (postgres, mysql)\n", dlerror()); } } csync_debug(2, "Opening shared library libsqlite.so\n"); LOOKUP_SYMBOL(dl_handle, sqlite_open); LOOKUP_SYMBOL(dl_handle, sqlite_close); LOOKUP_SYMBOL(dl_handle, sqlite_exec); LOOKUP_SYMBOL(dl_handle, sqlite_compile); LOOKUP_SYMBOL(dl_handle, sqlite_step); LOOKUP_SYMBOL(dl_handle, sqlite_finalize); } int db_sqlite2_open(const char *file, db_conn_p * conn_p) { db_sqlite_dlopen(); sqlite *db = f.sqlite_open_fn(file, 0, &errmsg); if (db == 0) { return DB_ERROR; }; db_conn_p conn = calloc(1, sizeof(*conn)); if (conn == NULL) { return DB_ERROR; } *conn_p = conn; conn->private = db; conn->close = db_sqlite2_close; conn->exec = db_sqlite2_exec; conn->prepare = db_sqlite2_prepare; conn->errmsg = NULL; conn->upgrade_to_schema = db_sqlite2_upgrade_to_schema; return DB_OK; } void db_sqlite2_close(db_conn_p conn) { if (!conn) return; if (!conn->private) return; f.sqlite_close_fn(conn->private); conn->private = 0; } const char *db_sqlite2_errmsg(db_conn_p conn) { if (!conn) return "(no connection)"; if (!conn->private) return "(no private data in conn)"; return errmsg; } int db_sqlite2_exec(db_conn_p conn, const char *sql) { int rc; if (!conn) return DB_NO_CONNECTION; if (!conn->private) { /* added error element */ return DB_NO_CONNECTION_REAL; } rc = f.sqlite_exec_fn(conn->private, (char *)sql, 0, 0, &errmsg); /* On error parse, create DB ERROR element */ return rc; } int db_sqlite2_prepare(db_conn_p conn, const char *sql, db_stmt_p * stmt_p, char **pptail) { int rc; sqlite *db; *stmt_p = NULL; if (!conn) return DB_NO_CONNECTION; if (!conn->private) { /* added error element */ return DB_NO_CONNECTION_REAL; } db = conn->private; db_stmt_p stmt = malloc(sizeof(*stmt)); sqlite_vm *sqlite_stmt = 0; rc = f.sqlite_compile_fn(db, sql, 0, &sqlite_stmt, &errmsg); if (rc != SQLITE_OK) return 0; stmt->private = sqlite_stmt; *stmt_p = stmt; stmt->get_column_text = db_sqlite2_stmt_get_column_text; stmt->get_column_blob = db_sqlite2_stmt_get_column_blob; stmt->get_column_int = db_sqlite2_stmt_get_column_int; stmt->next = db_sqlite2_stmt_next; stmt->close = db_sqlite2_stmt_close; stmt->db = conn; return DB_OK; } const char *db_sqlite2_stmt_get_column_text(db_stmt_p stmt, int column) { if (!stmt || !stmt->private) { return 0; } sqlite_vm *sqlite_stmt = stmt->private; const char **values = stmt->private2; return values[column]; } const void *db_sqlite2_stmt_get_column_blob(db_stmt_p stmt, int col) { return db_sqlite2_stmt_get_column_text(stmt, col); } int db_sqlite2_stmt_get_column_int(db_stmt_p stmt, int column) { sqlite_vm *sqlite_stmt = stmt->private; const char **values = stmt->private2; const char *str_value = values[column]; int value = 0; if (value) value = atoi(str_value); /* TODO missing way to return error */ return value; } int db_sqlite2_stmt_next(db_stmt_p stmt) { sqlite_vm *sqlite_stmt = stmt->private; const char **dataSQL_V, **dataSQL_N; const char **values; const char **names; int columns; int rc = f.sqlite_step_fn(sqlite_stmt, &columns, &values, &names); stmt->private2 = values; /* TODO error mapping */ return rc; // == SQLITE_ROW; } int db_sqlite2_stmt_close(db_stmt_p stmt) { sqlite_vm *sqlite_stmt = stmt->private; int rc = f.sqlite_finalize_fn(sqlite_stmt, &errmsg); free(stmt); return rc; } int db_sqlite2_upgrade_to_schema(int version) { if (version < 0) return DB_OK; if (version > 0) return DB_ERROR; csync_debug(2, "Upgrading database schema to version %d.\n", version); /* *INDENT-OFF* */ csync_db_sql("Creating file table", "CREATE TABLE file (" " filename, checktxt," " UNIQUE ( filename ) ON CONFLICT REPLACE" ")"); csync_db_sql("Creating dirty table", "CREATE TABLE dirty (" " filename, forced, myname, peername," " UNIQUE ( filename, peername ) ON CONFLICT IGNORE" ")"); csync_db_sql("Creating hint table", "CREATE TABLE hint (" " filename, recursive," " UNIQUE ( filename, recursive ) ON CONFLICT IGNORE" ")"); csync_db_sql("Creating action table", "CREATE TABLE action (" " filename, command, logfile," " UNIQUE ( filename, command ) ON CONFLICT IGNORE" ")"); csync_db_sql("Creating x509_cert table", "CREATE TABLE x509_cert (" " peername, certdata," " UNIQUE ( peername ) ON CONFLICT IGNORE" ")"); /* *INDENT-ON* */ return DB_OK; } #endif