OpenSync 0.22
opensync/opensync_db.c
00001 /*
00002  * libopensync - A synchronization framework
00003  * Copyright (C) 2004-2005  Armin Bauer <armin.bauer@opensync.org>
00004  * 
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  * 
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  * 
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00018  * 
00019  */
00020  
00021 #include "opensync.h"
00022 #include "opensync_internals.h"
00023 
00024 void osync_db_trace(void *data, const char *query)
00025 {
00026         osync_trace(TRACE_INTERNAL, "query executed: %s", query);
00027 }
00028 
00029 OSyncDB *osync_db_open(char *filename, OSyncError **error)
00030 {
00031         osync_trace(TRACE_ENTRY, "%s(%s, %p)", __func__, filename, error);
00032         
00033         OSyncDB *db = osync_try_malloc0(sizeof(OSyncDB), error);
00034         if (!db)
00035                 goto error;
00036                 
00037         int rc = sqlite3_open(filename, &(db->db));
00038         if (rc) {
00039                 osync_error_set(error, OSYNC_ERROR_GENERIC, "Cannot open database: %s", sqlite3_errmsg(db->db));
00040                 goto error_close;
00041         }
00042         sqlite3_trace(db->db, osync_db_trace, NULL);
00043         
00044         osync_trace(TRACE_EXIT, "%s: %p", __func__, db);
00045         return db;
00046 
00047 error_close:
00048         osync_db_close(db);
00049 //error_free:
00050         g_free(db);
00051 error:
00052         osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00053         return NULL;
00054 }
00055 
00056 void osync_db_close(OSyncDB *db)
00057 {
00058         osync_trace(TRACE_ENTRY, "%s(%p)", __func__, db);
00059         
00060         int ret = sqlite3_close(db->db);
00061         if (ret != SQLITE_OK)
00062                 osync_trace(TRACE_INTERNAL, "Can't close database: %s", sqlite3_errmsg(db->db));
00063         
00064         osync_trace(TRACE_EXIT, "%s", __func__);
00065 }
00066 
00067 int osync_db_count(OSyncDB *db, char *query)
00068 {
00069         int ret = 0;
00070 
00071         sqlite3_stmt *ppStmt = NULL;
00072         if (sqlite3_prepare(db->db, query, -1, &ppStmt, NULL) != SQLITE_OK)
00073                 osync_debug("OSDB", 3, "Unable prepare count! %s", sqlite3_errmsg(db->db));
00074         ret = sqlite3_step(ppStmt);
00075         if (ret != SQLITE_DONE && ret != SQLITE_ROW)
00076                 osync_debug("OSDB", 3, "Unable step count! %s", sqlite3_errmsg(db->db));
00077         if (ret == SQLITE_DONE)
00078                 osync_debug("OSDB", 3, "No row found!");
00079         ret = sqlite3_column_int64(ppStmt, 0);
00080         sqlite3_finalize(ppStmt);
00081         return ret;
00082 }
00083 
00084 OSyncDB *_open_changelog(OSyncGroup *group, OSyncError **error)
00085 {
00086         g_assert(group);
00087         OSyncDB *log_db;
00088 
00089         char *filename = g_strdup_printf("%s/changelog.db", group->configdir);
00090         if (!(log_db = osync_db_open(filename, error))) {
00091                 osync_error_update(error, "Unable to load changelog: %s", osync_error_print(error));
00092                 g_free(filename);
00093                 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00094                 return NULL;
00095         }
00096         osync_debug("OSDB", 3, "Preparing to changelog from file %s", filename);
00097         g_free(filename);
00098         
00099         sqlite3 *sdb = log_db->db;
00100         
00101         if (sqlite3_exec(sdb, "CREATE TABLE tbl_log (uid VARCHAR, objtype VARCHAR, memberid INTEGER, changetype INTEGER)", NULL, NULL, NULL) != SQLITE_OK)
00102                 osync_debug("OSDB", 2, "Unable create log table! %s", sqlite3_errmsg(sdb));
00103         return log_db;
00104 }
00105 
00106 osync_bool osync_db_open_changelog(OSyncGroup *group, char ***uids, char ***objtype, long long int **memberids, int **changetypes, OSyncError **error)
00107 {
00108         osync_trace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, group, uids, changetypes, error);
00109         
00110         OSyncDB *log_db = _open_changelog(group, error);
00111         if (!log_db) {
00112                 goto error;
00113         }
00114         sqlite3 *sdb = log_db->db;
00115         
00116         int count = osync_db_count(log_db, "SELECT count(*) FROM tbl_log");
00117 
00118         *uids = g_malloc0(sizeof(char *) * (count + 1));
00119         *objtype = g_malloc0(sizeof(char *) * (count + 1));
00120         *memberids = g_malloc0(sizeof(long long int) * (count + 1));
00121         *changetypes = g_malloc0(sizeof(int) * (count + 1));
00122 
00123         sqlite3_stmt *ppStmt = NULL;
00124         sqlite3_prepare(sdb, "SELECT uid, objtype, memberid, changetype FROM tbl_log", -1, &ppStmt, NULL);
00125         int i = 0;
00126         while (sqlite3_step(ppStmt) == SQLITE_ROW) {
00127                 (*uids)[i] = g_strdup((gchar*)sqlite3_column_text(ppStmt, 0));
00128                 (*objtype)[i] = g_strdup((gchar*)sqlite3_column_text(ppStmt, 1));
00129                 (*memberids)[i] = sqlite3_column_int64(ppStmt, 2);
00130                 (*changetypes)[i] = sqlite3_column_int(ppStmt, 3);
00131                 i++;
00132         }
00133         (*uids)[i] = NULL;
00134         (*objtype)[i] = NULL;
00135         (*memberids)[i] = 0;
00136         (*changetypes)[i] = 0;
00137         sqlite3_finalize(ppStmt);
00138 
00139         char *query = g_strdup_printf("DELETE FROM tbl_log");
00140         if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK) {
00141                 osync_error_set(error, OSYNC_ERROR_PARAMETER, "Unable to remove all logs! %s", sqlite3_errmsg(sdb));
00142                 g_free(query);
00143                 goto error_db_close;
00144         }
00145         g_free(query);
00146         
00147         osync_db_close(log_db);
00148         osync_trace(TRACE_EXIT, "%s", __func__);
00149         return TRUE;
00150 
00151 error_db_close:
00152         osync_db_close(log_db);
00153 
00154 error:
00155         osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00156         return FALSE;
00157 }
00158 
00159 osync_bool osync_db_save_changelog(OSyncGroup *group, OSyncChange *change, OSyncError **error)
00160 {
00161         osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, group, change, error);
00162         
00163         OSyncDB *log_db = _open_changelog(group, error);
00164         if (!log_db) {
00165                 goto error;
00166         }
00167         sqlite3 *sdb = log_db->db;
00168         
00169         char *escaped_uid = osync_db_sql_escape(change->uid);
00170         char *query = g_strdup_printf("INSERT INTO tbl_log (uid, objtype, memberid, changetype) VALUES('%s', '%s', '%lli', '%i')", escaped_uid, osync_change_get_objtype(change)->name, change->member->id, change->changetype);
00171         g_free(escaped_uid);
00172         
00173         if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK) {
00174                 osync_error_set(error, OSYNC_ERROR_PARAMETER, "Unable to insert log! %s", sqlite3_errmsg(sdb));
00175                 g_free(query);
00176                 goto error_db_close;
00177         }
00178         g_free(query);
00179         
00180         osync_db_close(log_db);
00181         osync_trace(TRACE_EXIT, "%s", __func__);
00182         return TRUE;
00183 
00184 error_db_close:
00185         osync_db_close(log_db);
00186 
00187 error:
00188         osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00189         return FALSE;
00190 
00191 }
00192 
00193 osync_bool osync_db_remove_changelog(OSyncGroup *group, OSyncChange *change, OSyncError **error)
00194 {
00195         osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, group, change, error);
00196         
00197         OSyncDB *log_db = _open_changelog(group, error);
00198         if (!log_db) {
00199                 goto error;
00200         }
00201         sqlite3 *sdb = log_db->db;
00202         
00203         char *escaped_uid = osync_db_sql_escape(change->uid);
00204         char *query = g_strdup_printf("DELETE FROM tbl_log WHERE uid='%s' AND memberid='%lli' AND objtype='%s'", 
00205         escaped_uid, change->member->id, osync_change_get_objtype(change)->name);
00206         g_free(escaped_uid);
00207         
00208         if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK) {
00209                 osync_error_set(error, OSYNC_ERROR_PARAMETER, "Unable to remove log! %s", sqlite3_errmsg(sdb));
00210                 g_free(query);
00211                 goto error_db_close;
00212         }
00213         g_free(query);
00214         
00215         osync_db_close(log_db);
00216         osync_trace(TRACE_EXIT, "%s", __func__);
00217         return TRUE;
00218 
00219 error_db_close:
00220         osync_db_close(log_db); 
00221 
00222 error:
00223         osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00224         return FALSE;
00225 }
00226 
00227 osync_bool osync_db_open_changes(OSyncGroup *group, OSyncChange ***changes, OSyncError **error)
00228 {
00229         osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, group, changes, error);
00230         g_assert(group);
00231 
00232         group->changes_path = g_strdup(group->configdir);
00233         char *filename = g_strdup_printf("%s/change.db", group->changes_path);
00234         if (!(group->changes_db = osync_db_open(filename, error))) {
00235                 osync_error_update(error, "Unable to load changes: %s", osync_error_print(error));
00236                 goto error;
00237         }
00238         osync_debug("OSDB", 3, "Preparing to load changes from file %s", filename);
00239         g_free(filename);
00240         
00241         sqlite3 *sdb = group->changes_db->db;
00242         
00243         if (sqlite3_exec(sdb, "CREATE TABLE tbl_changes (id INTEGER PRIMARY KEY, uid VARCHAR, objtype VARCHAR, format VARCHAR, memberid INTEGER, mappingid INTEGER)", NULL, NULL, NULL) != SQLITE_OK)
00244                 osync_debug("OSDB", 2, "Unable create changes table! %s", sqlite3_errmsg(sdb));
00245         
00246         int count = osync_db_count(group->changes_db, "SELECT count(*) FROM tbl_changes");
00247         *changes = g_malloc0(sizeof(OSyncChange *) * (count + 1));
00248         
00249         sqlite3_stmt *ppStmt = NULL;
00250         sqlite3_prepare(sdb, "SELECT id, uid, objtype, format, memberid, mappingid FROM tbl_changes ORDER BY mappingid", -1, &ppStmt, NULL);
00251         int i = 0;
00252         while (sqlite3_step(ppStmt) == SQLITE_ROW) {
00253                 OSyncChange *change = osync_change_new();
00254                 change->id = sqlite3_column_int64(ppStmt, 0);
00255                 change->uid = g_strdup((gchar*)sqlite3_column_text(ppStmt, 1));
00256                 change->objtype_name = g_strdup((gchar*)sqlite3_column_text(ppStmt, 2));
00257                 change->format_name = g_strdup((gchar*)sqlite3_column_text(ppStmt, 3));
00258                 change->initial_format_name = g_strdup(change->format_name);
00259                 change->mappingid = sqlite3_column_int64(ppStmt, 5);
00260                 long long int memberid = sqlite3_column_int64(ppStmt, 4);
00261                 change->changes_db = group->changes_db;
00262         osync_change_set_member(change, osync_member_from_id(group, memberid));
00263                 osync_trace(TRACE_INTERNAL, "Loaded change with uid %s, changetype %i, data %p, size %i, objtype %s and format %s from member %lli", osync_change_get_uid(change), osync_change_get_changetype(change), osync_change_get_data(change), osync_change_get_datasize(change), osync_change_get_objtype(change) ? osync_objtype_get_name(osync_change_get_objtype(change)) : "None", osync_change_get_objformat(change) ? osync_objformat_get_name(osync_change_get_objformat(change)) : "None", memberid);
00264                 (*changes)[i] = change;
00265                 i++;
00266         }
00267         (*changes)[i] = NULL;
00268         sqlite3_finalize(ppStmt);
00269         
00270         osync_trace(TRACE_EXIT, "%s", __func__);
00271         return TRUE;
00272 
00273 error:
00274         osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00275         return FALSE;
00276 }
00277 
00278 osync_bool osync_db_save_change(OSyncChange *change, osync_bool save_format, OSyncError **error)
00279 {
00280         osync_trace(TRACE_ENTRY, "%s(%p, %i, %p) (Table: %p)", __func__, change, save_format, error, change->changes_db);
00281         osync_assert_msg(change, "Need to set change");
00282         osync_assert_msg(osync_change_get_objtype(change), "change->objtype was NULL while saving");
00283         osync_assert_msg(osync_change_get_objformat(change), "change->objformat was NULL while saving");
00284         
00285         if (!change || !change->changes_db) {
00286                 osync_error_set(error, OSYNC_ERROR_PARAMETER, "osync_db_save_change was called with wrong parameters");
00287                 goto error;
00288         }
00289         sqlite3 *sdb = change->changes_db->db;
00290         
00291         char *query = NULL;
00292         if (!change->id) {
00293                 char *escaped_uid = osync_db_sql_escape(change->uid);
00294                 query = g_strdup_printf("INSERT INTO tbl_changes (uid, objtype, format, memberid, mappingid) VALUES('%s', '%s', '%s', '%lli', '%lli')", escaped_uid, osync_change_get_objtype(change)->name, osync_change_get_objformat(change)->name, change->member->id, change->mappingid);
00295                 g_free(escaped_uid);
00296                 
00297                 if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK) {
00298                         osync_error_set(error, OSYNC_ERROR_PARAMETER, "Unable to insert change! %s", sqlite3_errmsg(sdb));
00299                         g_free(query);
00300                         goto error;
00301                 }
00302                 change->id = sqlite3_last_insert_rowid(sdb);
00303         } else {
00304                 char *escaped_uid = osync_db_sql_escape(change->uid);
00305                 if (save_format)
00306                         query = g_strdup_printf("UPDATE tbl_changes SET uid='%s', objtype='%s', format='%s', memberid='%lli', mappingid='%lli' WHERE id=%lli", escaped_uid, osync_change_get_objtype(change)->name, osync_change_get_objformat(change)->name, change->member->id, change->mappingid, change->id);
00307                 else
00308                         query = g_strdup_printf("UPDATE tbl_changes SET uid='%s', memberid='%lli', mappingid='%lli' WHERE id=%lli", escaped_uid, change->member->id, change->mappingid, change->id);
00309                 g_free(escaped_uid);
00310                 
00311                 if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK) {
00312                         osync_error_set(error, OSYNC_ERROR_PARAMETER, "Unable to update change! %s", sqlite3_errmsg(sdb));
00313                         g_free(query);
00314                         goto error;
00315                 }
00316         }
00317         g_free(query);
00318         osync_trace(TRACE_EXIT, "%s", __func__);
00319         return TRUE;
00320 
00321 error:
00322         osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00323         return FALSE;
00324 
00325 }
00326 
00327 osync_bool osync_db_delete_change(OSyncChange *change, OSyncError **error)
00328 {
00329         osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, change, error);
00330         
00331         if (!change || !change->changes_db) {
00332                 osync_error_set(error, OSYNC_ERROR_PARAMETER, "osync_db_delete_change was called with wrong parameters");
00333                 goto error;
00334         }
00335         sqlite3 *sdb = change->changes_db->db;
00336         
00337         char *query = g_strdup_printf("DELETE FROM tbl_changes WHERE id=%lli", change->id);
00338         if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK) {
00339                 osync_error_set(error, OSYNC_ERROR_PARAMETER, "Unable to delete change! %s", sqlite3_errmsg(sdb));
00340                 g_free(query);
00341                 goto error;
00342         }
00343         g_free(query);
00344         osync_trace(TRACE_EXIT, "%s", __func__);
00345         return TRUE;
00346 
00347 error:  
00348         osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00349         return FALSE;
00350 }
00351 
00352 osync_bool osync_db_reset_changes(OSyncGroup *group, const char *objtype, OSyncError **error)
00353 {
00354         osync_trace(TRACE_ENTRY, "%s(%p, %s, %p)", __func__, group, objtype, error);
00355         
00356         if (!group || !objtype) {
00357                 osync_error_set(error, OSYNC_ERROR_PARAMETER, "osync_db_reset_changes was called with wrong parameters");
00358                 goto error;
00359         }
00360         sqlite3 *sdb = group->changes_db->db;
00361 
00362         char *query = NULL;
00363         if (osync_conv_objtype_is_any(objtype)) {
00364                 query = g_strdup_printf("DELETE FROM tbl_changes");
00365         } else {
00366                 query = g_strdup_printf("DELETE FROM tbl_changes WHERE objtype='%s'", objtype);
00367         }
00368 
00369         if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK) {
00370                 osync_error_set(error, OSYNC_ERROR_PARAMETER, "Unable to reset changes! %s", sqlite3_errmsg(sdb));
00371                 g_free(query);
00372                 goto error;
00373         }
00374 
00375         g_free(query);
00376         osync_trace(TRACE_EXIT, "%s", __func__);
00377         return TRUE;
00378 
00379 error:
00380         osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00381         return FALSE;
00382         
00383 }
00384 
00385 osync_bool osync_db_reset_group(OSyncGroup *group, OSyncError **error)
00386 {
00387         osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, group, error);
00388         OSyncDB *db = NULL;
00389         
00390         if (!group) {
00391                 osync_error_set(error, OSYNC_ERROR_PARAMETER, "osync_db_reset_group was called with wrong parameters");
00392                 goto error;
00393         }
00394         
00395         char *changesdb = g_strdup_printf("%s/change.db", group->configdir);
00396         if (!(db = osync_db_open(changesdb, error))) {
00397                 g_free(changesdb);
00398                 goto error;
00399         }
00400 
00401         if (sqlite3_exec(db->db, "DELETE FROM tbl_changes", NULL, NULL, NULL) != SQLITE_OK) {
00402                 osync_error_set(error, OSYNC_ERROR_PARAMETER, "Unable to reset changes! %s", sqlite3_errmsg(db->db));
00403                 g_free(changesdb);
00404                 goto error_db_close;
00405         }
00406         
00407         osync_db_close(db);
00408         g_free(changesdb);
00409         
00410         osync_trace(TRACE_EXIT, "%s", __func__);
00411         return TRUE;
00412 
00413 error_db_close: 
00414         osync_db_close(db);
00415 
00416 error:  
00417         osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00418         return FALSE;
00419 }
00420 
00421 osync_bool osync_db_reset_member(OSyncMember *member, OSyncError **error)
00422 {
00423         osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, member, error);
00424         OSyncDB *db = NULL;
00425         
00426         if (!member) {
00427                 osync_error_set(error, OSYNC_ERROR_PARAMETER, "osync_db_reset_member was called with wrong parameters");
00428                 goto error;
00429         }
00430         
00431         char *hashtable = g_strdup_printf("%s/hash.db", member->configdir);
00432         if (g_file_test(hashtable, G_FILE_TEST_EXISTS)) {
00433                 if (!(db = osync_db_open(hashtable, error))) {
00434                         g_free(hashtable);
00435                         goto error;
00436                 }
00437         
00438                 if (sqlite3_exec(db->db, "DELETE FROM tbl_hash", NULL, NULL, NULL) != SQLITE_OK) {
00439                         osync_error_set(error, OSYNC_ERROR_PARAMETER, "Unable to reset hashtable! %s", sqlite3_errmsg(db->db));
00440                         g_free(hashtable);
00441                         goto error_db_close;
00442                 }
00443                 
00444                 osync_db_close(db);
00445         }
00446         g_free(hashtable);
00447         
00448         char *anchordb = g_strdup_printf("%s/anchor.db", member->configdir);
00449         if (g_file_test(anchordb, G_FILE_TEST_EXISTS)) {
00450                 if (!(db = osync_db_open(anchordb, error))) {
00451                         g_free(anchordb);
00452                         goto error;
00453                 }
00454         
00455                 if (sqlite3_exec(db->db, "DELETE FROM tbl_anchor", NULL, NULL, NULL) != SQLITE_OK) {
00456                         osync_error_set(error, OSYNC_ERROR_PARAMETER, "Unable to reset anchors! %s", sqlite3_errmsg(db->db));
00457                         g_free(anchordb);
00458                         goto error_db_close;
00459                 }
00460                 
00461                 osync_db_close(db);
00462         }
00463         g_free(anchordb);
00464         
00465         osync_trace(TRACE_EXIT, "%s", __func__);
00466         return TRUE;
00467 
00468 error_db_close: 
00469         osync_db_close(db);
00470 
00471 error:
00472         osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00473         return FALSE;
00474 
00475 }
00476 
00477 void osync_db_close_changes(OSyncGroup *group)
00478 {
00479         if (group->changes_db)
00480                 osync_db_close(group->changes_db);
00481 }
00482 
00483 OSyncDB *osync_db_open_anchor(OSyncMember *member, OSyncError **error)
00484 {
00485         g_assert(member);
00486         OSyncDB *sdb = NULL;
00487         char *filename = g_strdup_printf ("%s/anchor.db", member->configdir);
00488         if (!(sdb = osync_db_open(filename, error))) {
00489                 g_free(filename);
00490                 osync_error_update(error, "Unable to open anchor table: %s", (*error)->message);
00491                 return NULL;
00492         }
00493         g_free(filename);
00494         
00495         if (sqlite3_exec(sdb->db, "CREATE TABLE tbl_anchor (id INTEGER PRIMARY KEY, anchor VARCHAR, objtype VARCHAR UNIQUE)", NULL, NULL, NULL) != SQLITE_OK)
00496                 osync_debug("OSDB", 3, "Unable create anchor table! %s", sqlite3_errmsg(sdb->db));
00497         
00498         return sdb;
00499 }
00500 
00501 void osync_db_close_anchor(OSyncDB *db)
00502 {
00503         osync_db_close(db);
00504 }
00505 
00506 void osync_db_get_anchor(OSyncDB *sdb, const char *objtype, char **retanchor)
00507 {
00508         sqlite3_stmt *ppStmt = NULL;
00509         char *query = g_strdup_printf("SELECT anchor FROM tbl_anchor WHERE objtype='%s'", objtype);
00510         if (sqlite3_prepare(sdb->db, query, -1, &ppStmt, NULL) != SQLITE_OK)
00511                 osync_debug("OSDB", 3, "Unable prepare anchor! %s", sqlite3_errmsg(sdb->db));
00512         int ret = sqlite3_step(ppStmt);
00513         if (ret != SQLITE_DONE && ret != SQLITE_ROW)
00514                 osync_debug("OSDB", 3, "Unable step count! %s", sqlite3_errmsg(sdb->db));
00515         if (ret == SQLITE_DONE)
00516                 osync_debug("OSDB", 3, "No row found!");
00517         *retanchor = g_strdup((gchar*)sqlite3_column_text(ppStmt, 0));
00518         sqlite3_finalize(ppStmt);
00519         g_free(query);
00520 }
00521 
00522 void osync_db_put_anchor(OSyncDB *sdb, const char *objtype, const char *anchor)
00523 {
00524         char *escaped_anchor = osync_db_sql_escape(anchor);
00525         char *query = g_strdup_printf("REPLACE INTO tbl_anchor (objtype, anchor) VALUES('%s', '%s')", objtype, escaped_anchor);
00526         g_free(escaped_anchor);
00527         
00528         if (sqlite3_exec(sdb->db, query, NULL, NULL, NULL) != SQLITE_OK)
00529                 osync_debug("OSDB", 1, "Unable put anchor! %s", sqlite3_errmsg(sdb->db));
00530 
00531         g_free(query);
00532 }
00533 
00534 
00535 osync_bool osync_db_open_hashtable(OSyncHashTable *table, OSyncMember *member, OSyncError **error)
00536 {
00537         g_assert(member);
00538         char *filename = g_strdup_printf ("%s/hash.db", member->configdir);
00539         if (!(table->dbhandle = osync_db_open(filename, error))) {
00540                 g_free(filename);
00541                 osync_error_update(error, "Unable to open hashtable: %s", (*error)->message);
00542                 return FALSE;
00543         }
00544         g_free(filename);
00545         
00546         sqlite3 *db = table->dbhandle->db;
00547         
00548         if (sqlite3_exec(db, "CREATE TABLE tbl_hash (id INTEGER PRIMARY KEY, uid VARCHAR, hash VARCHAR, objtype VARCHAR)", NULL, NULL, NULL) != SQLITE_OK)
00549                 osync_debug("OSDB", 3, "Unable create hash table! %s", sqlite3_errmsg(db));
00550         
00551         return TRUE; //FIXME
00552 }
00553 
00554 void osync_db_close_hashtable(OSyncHashTable *table)
00555 {
00556         osync_db_close(table->dbhandle);
00557 }
00558 
00559 int exists_hashtable_id(OSyncHashTable *table, const char *uid, const char *objtype)
00560 {
00561         g_assert(table->dbhandle);
00562         sqlite3 *sdb = table->dbhandle->db;
00563         
00564         int id = -1;
00565 
00566         char *exist = g_strdup_printf("SELECT id FROM tbl_hash WHERE uid='%s' AND objtype='%s'",uid, objtype);
00567 
00568         sqlite3_stmt *ppStmt = NULL;
00569         if (sqlite3_prepare(sdb, exist, -1, &ppStmt, NULL) != SQLITE_OK)
00570         {
00571                 osync_debug("OSDB", 3, "Unable prepare get id! %s", sqlite3_errmsg(sdb));
00572                 return (id);
00573         }
00574         int ret = sqlite3_step(ppStmt);
00575         if (ret != SQLITE_DONE && ret != SQLITE_ROW)
00576                 return (id);
00577         if (ret == SQLITE_DONE)
00578                 return (id);
00579         
00580         id = sqlite3_column_int64(ppStmt, 0);
00581         sqlite3_finalize(ppStmt);
00582         g_free(exist);
00583 
00584         return(id);
00585 }
00586 
00587 void osync_db_save_hash(OSyncHashTable *table, const char *uid, const char *hash, const char *objtype)
00588 {
00589         g_assert(table->dbhandle);
00590         sqlite3 *sdb = table->dbhandle->db;
00591         
00592         char *escaped_uid = osync_db_sql_escape(uid);
00593         char *escaped_hash = osync_db_sql_escape(hash);
00594         char *escaped_objtype = osync_db_sql_escape(objtype);
00595         int id = exists_hashtable_id(table, escaped_uid, escaped_objtype);
00596         char *query = NULL;
00597         if(id < 0){
00598                 query = g_strdup_printf(
00599                         "REPLACE INTO tbl_hash ('uid', 'hash', 'objtype') VALUES('%s', '%s', '%s')", 
00600                         escaped_uid, escaped_hash, escaped_objtype);
00601         }else{
00602                 query = g_strdup_printf(
00603                         "REPLACE INTO tbl_hash ('id', 'uid', 'hash', 'objtype') VALUES('%i', '%s', '%s', '%s')", 
00604                         id, escaped_uid, escaped_hash, escaped_objtype);
00605         }
00606         
00607         if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK)
00608                 osync_debug("OSDB", 1, "Unable to insert hash! uid = %s, hash = %s, error = %s", escaped_uid, escaped_hash, sqlite3_errmsg(sdb));
00609                 
00610         g_free(escaped_uid);
00611         g_free(escaped_hash);
00612         g_free(escaped_objtype);
00613         g_free(query);
00614 }
00615 
00616 
00617 void osync_db_delete_hash(OSyncHashTable *table, const char *uid)
00618 {
00619         g_assert(table->dbhandle);
00620         sqlite3 *sdb = table->dbhandle->db;
00621         
00622         char *escaped_uid = osync_db_sql_escape(uid);
00623         char *query = g_strdup_printf("DELETE FROM tbl_hash WHERE uid='%s'", escaped_uid);
00624         g_free(escaped_uid);
00625 
00626         if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK)
00627                 osync_debug("OSDB", 1, "Unable to delete hash! %s", sqlite3_errmsg(sdb));
00628         g_free(query);
00629 }
00630 
00631 char **osync_db_get_deleted_hash(OSyncHashTable *table, const char *objtype)
00632 {
00633         g_assert(table->dbhandle);
00634         sqlite3 *sdb = table->dbhandle->db;
00635         
00636         char **azResult = NULL;
00637         int numrows = 0;
00638         char *query = NULL;
00639         
00640         if (osync_conv_objtype_is_any(objtype)) {
00641                 query = g_strdup_printf("SELECT uid, hash FROM tbl_hash");
00642         } else {
00643                 query = g_strdup_printf("SELECT uid, hash FROM tbl_hash WHERE objtype='%s'", objtype);
00644         }
00645         sqlite3_get_table(sdb, query, &azResult, &numrows, NULL, NULL);
00646         g_free(query);
00647         
00648         char **ret = g_malloc0((numrows + 1) * sizeof(char *));
00649         
00650         int i;
00651         int ccell = 2;
00652         int num = 0;
00653         for (i = 0; i < numrows; i++) {
00654                 char *uid = azResult[ccell];
00655                 ccell += 2;
00656                 
00657                 if (!g_hash_table_lookup(table->used_entries, uid)) {
00658                         ret[num] = g_strdup(uid);
00659                         num++;
00660                 }
00661         }
00662         sqlite3_free_table(azResult);
00663         return ret;
00664 }       
00665 
00666 void osync_db_get_hash(OSyncHashTable *table, const char *uid, const char *objtype, char **rethash)
00667 {
00668         sqlite3 *sdb = table->dbhandle->db;
00669         sqlite3_stmt *ppStmt = NULL;
00670         char *escaped_uid = osync_db_sql_escape(uid);
00671         char *escaped_objtype = osync_db_sql_escape(objtype);
00672         char *query = g_strdup_printf("SELECT hash FROM tbl_hash WHERE uid='%s' AND objtype='%s'", escaped_uid, escaped_objtype);
00673         g_free(escaped_uid);
00674         g_free(escaped_objtype);
00675 
00676         if (sqlite3_prepare(sdb, query, -1, &ppStmt, NULL) != SQLITE_OK)
00677                 osync_debug("OSDB", 3, "Unable prepare get hash! %s", sqlite3_errmsg(sdb));
00678         int ret = sqlite3_step(ppStmt);
00679         if (ret != SQLITE_DONE && ret != SQLITE_ROW)
00680                 osync_debug("OSDB", 3, "Unable step get hash! %s", sqlite3_errmsg(sdb));
00681         if (ret == SQLITE_DONE)
00682                 osync_debug("OSDB", 3, "No row found!");
00683         *rethash = g_strdup((gchar*)sqlite3_column_text(ppStmt, 0));
00684         sqlite3_finalize(ppStmt);
00685         g_free(query);
00686 }
00687 
00688 void osync_db_reset_hash(OSyncHashTable *table, const char *objtype)
00689 {
00690         sqlite3 *sdb = table->dbhandle->db;
00691         char *query = NULL;
00692         if (osync_conv_objtype_is_any(objtype)) {
00693                 query = g_strdup_printf("DELETE FROM tbl_hash");
00694         } else {
00695                 query = g_strdup_printf("DELETE FROM tbl_hash WHERE objtype='%s'", objtype);
00696         }
00697         if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK)
00698                 osync_debug("OSDB", 1, "Unable to reset hash! %s", sqlite3_errmsg(sdb));
00699         g_free(query);
00700 }
00701 
00702 char *osync_db_sql_escape(const char *s)
00703 {
00704         return osync_strreplace(s, "'", "''");
00705 }
00706