22 #include "opensync_internals.h" 24 void osync_db_trace(
void *data,
const char *query)
29 OSyncDB *osync_db_open(
char *filename,
OSyncError **error)
37 int rc = sqlite3_open(filename, &(db->db));
39 osync_error_set(error, OSYNC_ERROR_GENERIC,
"Cannot open database: %s", sqlite3_errmsg(db->db));
42 sqlite3_trace(db->db, osync_db_trace, NULL);
56 void osync_db_close(OSyncDB *db)
60 int ret = sqlite3_close(db->db);
67 int osync_db_count(OSyncDB *db,
char *query)
71 sqlite3_stmt *ppStmt = NULL;
72 if (sqlite3_prepare(db->db, query, -1, &ppStmt, NULL) != SQLITE_OK)
73 osync_debug(
"OSDB", 3,
"Unable prepare count! %s", sqlite3_errmsg(db->db));
74 ret = sqlite3_step(ppStmt);
75 if (ret != SQLITE_DONE && ret != SQLITE_ROW)
76 osync_debug(
"OSDB", 3,
"Unable step count! %s", sqlite3_errmsg(db->db));
77 if (ret == SQLITE_DONE)
79 ret = sqlite3_column_int64(ppStmt, 0);
80 sqlite3_finalize(ppStmt);
89 char *filename = g_strdup_printf(
"%s/changelog.db", group->configdir);
90 if (!(log_db = osync_db_open(filename, error))) {
96 osync_debug(
"OSDB", 3,
"Preparing to changelog from file %s", filename);
99 sqlite3 *sdb = log_db->db;
101 if (sqlite3_exec(sdb,
"CREATE TABLE tbl_log (uid VARCHAR, objtype VARCHAR, memberid INTEGER, changetype INTEGER)", NULL, NULL, NULL) != SQLITE_OK)
102 osync_debug(
"OSDB", 2,
"Unable create log table! %s", sqlite3_errmsg(sdb));
106 osync_bool osync_db_open_changelog(
OSyncGroup *group,
char ***uids,
char ***objtype,
long long int **memberids,
int **changetypes,
OSyncError **error)
110 OSyncDB *log_db = _open_changelog(group, error);
114 sqlite3 *sdb = log_db->db;
116 int count = osync_db_count(log_db,
"SELECT count(*) FROM tbl_log");
118 *uids = g_malloc0(
sizeof(
char *) * (count + 1));
119 *objtype = g_malloc0(
sizeof(
char *) * (count + 1));
120 *memberids = g_malloc0(
sizeof(
long long int) * (count + 1));
121 *changetypes = g_malloc0(
sizeof(
int) * (count + 1));
123 sqlite3_stmt *ppStmt = NULL;
124 sqlite3_prepare(sdb,
"SELECT uid, objtype, memberid, changetype FROM tbl_log", -1, &ppStmt, NULL);
126 while (sqlite3_step(ppStmt) == SQLITE_ROW) {
127 (*uids)[i] = g_strdup((gchar*)sqlite3_column_text(ppStmt, 0));
128 (*objtype)[i] = g_strdup((gchar*)sqlite3_column_text(ppStmt, 1));
129 (*memberids)[i] = sqlite3_column_int64(ppStmt, 2);
130 (*changetypes)[i] = sqlite3_column_int(ppStmt, 3);
134 (*objtype)[i] = NULL;
136 (*changetypes)[i] = 0;
137 sqlite3_finalize(ppStmt);
139 char *query = g_strdup_printf(
"DELETE FROM tbl_log");
140 if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK) {
141 osync_error_set(error, OSYNC_ERROR_PARAMETER,
"Unable to remove all logs! %s", sqlite3_errmsg(sdb));
147 osync_db_close(log_db);
152 osync_db_close(log_db);
163 OSyncDB *log_db = _open_changelog(group, error);
167 sqlite3 *sdb = log_db->db;
169 char *escaped_uid = osync_db_sql_escape(change->
uid);
170 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);
173 if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK) {
174 osync_error_set(error, OSYNC_ERROR_PARAMETER,
"Unable to insert log! %s", sqlite3_errmsg(sdb));
180 osync_db_close(log_db);
185 osync_db_close(log_db);
197 OSyncDB *log_db = _open_changelog(group, error);
201 sqlite3 *sdb = log_db->db;
203 char *escaped_uid = osync_db_sql_escape(change->
uid);
204 char *query = g_strdup_printf(
"DELETE FROM tbl_log WHERE uid='%s' AND memberid='%lli' AND objtype='%s'",
208 if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK) {
209 osync_error_set(error, OSYNC_ERROR_PARAMETER,
"Unable to remove log! %s", sqlite3_errmsg(sdb));
215 osync_db_close(log_db);
220 osync_db_close(log_db);
232 group->changes_path = g_strdup(group->configdir);
233 char *filename = g_strdup_printf(
"%s/change.db", group->changes_path);
234 if (!(group->changes_db = osync_db_open(filename, error))) {
238 osync_debug(
"OSDB", 3,
"Preparing to load changes from file %s", filename);
241 sqlite3 *sdb = group->changes_db->db;
243 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)
244 osync_debug(
"OSDB", 2,
"Unable create changes table! %s", sqlite3_errmsg(sdb));
246 int count = osync_db_count(group->changes_db,
"SELECT count(*) FROM tbl_changes");
247 *changes = g_malloc0(
sizeof(
OSyncChange *) * (count + 1));
249 sqlite3_stmt *ppStmt = NULL;
250 sqlite3_prepare(sdb,
"SELECT id, uid, objtype, format, memberid, mappingid FROM tbl_changes ORDER BY mappingid", -1, &ppStmt, NULL);
252 while (sqlite3_step(ppStmt) == SQLITE_ROW) {
254 change->
id = sqlite3_column_int64(ppStmt, 0);
255 change->
uid = g_strdup((gchar*)sqlite3_column_text(ppStmt, 1));
256 change->
objtype_name = g_strdup((gchar*)sqlite3_column_text(ppStmt, 2));
257 change->
format_name = g_strdup((gchar*)sqlite3_column_text(ppStmt, 3));
259 change->
mappingid = sqlite3_column_int64(ppStmt, 5);
260 long long int memberid = sqlite3_column_int64(ppStmt, 4);
263 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);
264 (*changes)[i] = change;
267 (*changes)[i] = NULL;
268 sqlite3_finalize(ppStmt);
281 osync_assert_msg(change,
"Need to set change");
286 osync_error_set(error, OSYNC_ERROR_PARAMETER,
"osync_db_save_change was called with wrong parameters");
293 char *escaped_uid = osync_db_sql_escape(change->
uid);
294 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);
297 if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK) {
298 osync_error_set(error, OSYNC_ERROR_PARAMETER,
"Unable to insert change! %s", sqlite3_errmsg(sdb));
302 change->
id = sqlite3_last_insert_rowid(sdb);
304 char *escaped_uid = osync_db_sql_escape(change->
uid);
306 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);
308 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);
311 if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK) {
312 osync_error_set(error, OSYNC_ERROR_PARAMETER,
"Unable to update change! %s", sqlite3_errmsg(sdb));
332 osync_error_set(error, OSYNC_ERROR_PARAMETER,
"osync_db_delete_change was called with wrong parameters");
337 char *query = g_strdup_printf(
"DELETE FROM tbl_changes WHERE id=%lli", change->
id);
338 if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK) {
339 osync_error_set(error, OSYNC_ERROR_PARAMETER,
"Unable to delete change! %s", sqlite3_errmsg(sdb));
356 if (!group || !objtype) {
357 osync_error_set(error, OSYNC_ERROR_PARAMETER,
"osync_db_reset_changes was called with wrong parameters");
360 sqlite3 *sdb = group->changes_db->db;
363 if (osync_conv_objtype_is_any(objtype)) {
364 query = g_strdup_printf(
"DELETE FROM tbl_changes");
366 query = g_strdup_printf(
"DELETE FROM tbl_changes WHERE objtype='%s'", objtype);
369 if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK) {
370 osync_error_set(error, OSYNC_ERROR_PARAMETER,
"Unable to reset changes! %s", sqlite3_errmsg(sdb));
391 osync_error_set(error, OSYNC_ERROR_PARAMETER,
"osync_db_reset_group was called with wrong parameters");
395 char *changesdb = g_strdup_printf(
"%s/change.db", group->configdir);
396 if (!(db = osync_db_open(changesdb, error))) {
401 if (sqlite3_exec(db->db,
"DELETE FROM tbl_changes", NULL, NULL, NULL) != SQLITE_OK) {
402 osync_error_set(error, OSYNC_ERROR_PARAMETER,
"Unable to reset changes! %s", sqlite3_errmsg(db->db));
427 osync_error_set(error, OSYNC_ERROR_PARAMETER,
"osync_db_reset_member was called with wrong parameters");
431 char *hashtable = g_strdup_printf(
"%s/hash.db", member->configdir);
432 if (g_file_test(hashtable, G_FILE_TEST_EXISTS)) {
433 if (!(db = osync_db_open(hashtable, error))) {
438 if (sqlite3_exec(db->db,
"DELETE FROM tbl_hash", NULL, NULL, NULL) != SQLITE_OK) {
439 osync_error_set(error, OSYNC_ERROR_PARAMETER,
"Unable to reset hashtable! %s", sqlite3_errmsg(db->db));
448 char *anchordb = g_strdup_printf(
"%s/anchor.db", member->configdir);
449 if (g_file_test(anchordb, G_FILE_TEST_EXISTS)) {
450 if (!(db = osync_db_open(anchordb, error))) {
455 if (sqlite3_exec(db->db,
"DELETE FROM tbl_anchor", NULL, NULL, NULL) != SQLITE_OK) {
456 osync_error_set(error, OSYNC_ERROR_PARAMETER,
"Unable to reset anchors! %s", sqlite3_errmsg(db->db));
477 void osync_db_close_changes(
OSyncGroup *group)
479 if (group->changes_db)
480 osync_db_close(group->changes_db);
487 char *filename = g_strdup_printf (
"%s/anchor.db", member->configdir);
488 if (!(sdb = osync_db_open(filename, error))) {
495 if (sqlite3_exec(sdb->db,
"CREATE TABLE tbl_anchor (id INTEGER PRIMARY KEY, anchor VARCHAR, objtype VARCHAR UNIQUE)", NULL, NULL, NULL) != SQLITE_OK)
496 osync_debug(
"OSDB", 3,
"Unable create anchor table! %s", sqlite3_errmsg(sdb->db));
501 void osync_db_close_anchor(OSyncDB *db)
506 void osync_db_get_anchor(OSyncDB *sdb,
const char *objtype,
char **retanchor)
508 sqlite3_stmt *ppStmt = NULL;
509 char *query = g_strdup_printf(
"SELECT anchor FROM tbl_anchor WHERE objtype='%s'", objtype);
510 if (sqlite3_prepare(sdb->db, query, -1, &ppStmt, NULL) != SQLITE_OK)
511 osync_debug(
"OSDB", 3,
"Unable prepare anchor! %s", sqlite3_errmsg(sdb->db));
512 int ret = sqlite3_step(ppStmt);
513 if (ret != SQLITE_DONE && ret != SQLITE_ROW)
514 osync_debug(
"OSDB", 3,
"Unable step count! %s", sqlite3_errmsg(sdb->db));
515 if (ret == SQLITE_DONE)
517 *retanchor = g_strdup((gchar*)sqlite3_column_text(ppStmt, 0));
518 sqlite3_finalize(ppStmt);
522 void osync_db_put_anchor(OSyncDB *sdb,
const char *objtype,
const char *anchor)
524 char *escaped_anchor = osync_db_sql_escape(anchor);
525 char *query = g_strdup_printf(
"REPLACE INTO tbl_anchor (objtype, anchor) VALUES('%s', '%s')", objtype, escaped_anchor);
526 g_free(escaped_anchor);
528 if (sqlite3_exec(sdb->db, query, NULL, NULL, NULL) != SQLITE_OK)
529 osync_debug(
"OSDB", 1,
"Unable put anchor! %s", sqlite3_errmsg(sdb->db));
538 char *filename = g_strdup_printf (
"%s/hash.db", member->configdir);
539 if (!(table->dbhandle = osync_db_open(filename, error))) {
546 sqlite3 *db = table->dbhandle->db;
548 if (sqlite3_exec(db,
"CREATE TABLE tbl_hash (id INTEGER PRIMARY KEY, uid VARCHAR, hash VARCHAR, objtype VARCHAR)", NULL, NULL, NULL) != SQLITE_OK)
549 osync_debug(
"OSDB", 3,
"Unable create hash table! %s", sqlite3_errmsg(db));
556 osync_db_close(table->dbhandle);
559 int exists_hashtable_id(
OSyncHashTable *table,
const char *uid,
const char *objtype)
561 g_assert(table->dbhandle);
562 sqlite3 *sdb = table->dbhandle->db;
566 char *exist = g_strdup_printf(
"SELECT id FROM tbl_hash WHERE uid='%s' AND objtype='%s'",uid, objtype);
568 sqlite3_stmt *ppStmt = NULL;
569 if (sqlite3_prepare(sdb, exist, -1, &ppStmt, NULL) != SQLITE_OK)
571 osync_debug(
"OSDB", 3,
"Unable prepare get id! %s", sqlite3_errmsg(sdb));
574 int ret = sqlite3_step(ppStmt);
575 if (ret != SQLITE_DONE && ret != SQLITE_ROW)
577 if (ret == SQLITE_DONE)
580 id = sqlite3_column_int64(ppStmt, 0);
581 sqlite3_finalize(ppStmt);
587 void osync_db_save_hash(
OSyncHashTable *table,
const char *uid,
const char *hash,
const char *objtype)
589 g_assert(table->dbhandle);
590 sqlite3 *sdb = table->dbhandle->db;
592 char *escaped_uid = osync_db_sql_escape(uid);
593 char *escaped_hash = osync_db_sql_escape(hash);
594 char *escaped_objtype = osync_db_sql_escape(objtype);
595 int id = exists_hashtable_id(table, escaped_uid, escaped_objtype);
598 query = g_strdup_printf(
599 "REPLACE INTO tbl_hash ('uid', 'hash', 'objtype') VALUES('%s', '%s', '%s')",
600 escaped_uid, escaped_hash, escaped_objtype);
602 query = g_strdup_printf(
603 "REPLACE INTO tbl_hash ('id', 'uid', 'hash', 'objtype') VALUES('%i', '%s', '%s', '%s')",
604 id, escaped_uid, escaped_hash, escaped_objtype);
607 if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK)
608 osync_debug(
"OSDB", 1,
"Unable to insert hash! uid = %s, hash = %s, error = %s", escaped_uid, escaped_hash, sqlite3_errmsg(sdb));
611 g_free(escaped_hash);
612 g_free(escaped_objtype);
619 g_assert(table->dbhandle);
620 sqlite3 *sdb = table->dbhandle->db;
622 char *escaped_uid = osync_db_sql_escape(uid);
623 char *query = g_strdup_printf(
"DELETE FROM tbl_hash WHERE uid='%s'", escaped_uid);
626 if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK)
627 osync_debug(
"OSDB", 1,
"Unable to delete hash! %s", sqlite3_errmsg(sdb));
631 char **osync_db_get_deleted_hash(
OSyncHashTable *table,
const char *objtype)
633 g_assert(table->dbhandle);
634 sqlite3 *sdb = table->dbhandle->db;
636 char **azResult = NULL;
640 if (osync_conv_objtype_is_any(objtype)) {
641 query = g_strdup_printf(
"SELECT uid, hash FROM tbl_hash");
643 query = g_strdup_printf(
"SELECT uid, hash FROM tbl_hash WHERE objtype='%s'", objtype);
645 sqlite3_get_table(sdb, query, &azResult, &numrows, NULL, NULL);
648 char **ret = g_malloc0((numrows + 1) *
sizeof(
char *));
653 for (i = 0; i < numrows; i++) {
654 char *uid = azResult[ccell];
657 if (!g_hash_table_lookup(table->used_entries, uid)) {
658 ret[num] = g_strdup(uid);
662 sqlite3_free_table(azResult);
666 void osync_db_get_hash(
OSyncHashTable *table,
const char *uid,
const char *objtype,
char **rethash)
668 sqlite3 *sdb = table->dbhandle->db;
669 sqlite3_stmt *ppStmt = NULL;
670 char *escaped_uid = osync_db_sql_escape(uid);
671 char *escaped_objtype = osync_db_sql_escape(objtype);
672 char *query = g_strdup_printf(
"SELECT hash FROM tbl_hash WHERE uid='%s' AND objtype='%s'", escaped_uid, escaped_objtype);
674 g_free(escaped_objtype);
676 if (sqlite3_prepare(sdb, query, -1, &ppStmt, NULL) != SQLITE_OK)
677 osync_debug(
"OSDB", 3,
"Unable prepare get hash! %s", sqlite3_errmsg(sdb));
678 int ret = sqlite3_step(ppStmt);
679 if (ret != SQLITE_DONE && ret != SQLITE_ROW)
680 osync_debug(
"OSDB", 3,
"Unable step get hash! %s", sqlite3_errmsg(sdb));
681 if (ret == SQLITE_DONE)
683 *rethash = g_strdup((gchar*)sqlite3_column_text(ppStmt, 0));
684 sqlite3_finalize(ppStmt);
688 void osync_db_reset_hash(
OSyncHashTable *table,
const char *objtype)
690 sqlite3 *sdb = table->dbhandle->db;
692 if (osync_conv_objtype_is_any(objtype)) {
693 query = g_strdup_printf(
"DELETE FROM tbl_hash");
695 query = g_strdup_printf(
"DELETE FROM tbl_hash WHERE objtype='%s'", objtype);
697 if (sqlite3_exec(sdb, query, NULL, NULL, NULL) != SQLITE_OK)
698 osync_debug(
"OSDB", 1,
"Unable to reset hash! %s", sqlite3_errmsg(sdb));
702 char *osync_db_sql_escape(
const char *s)
704 return osync_strreplace(s,
"'",
"''");
OSyncChangeType osync_change_get_changetype(OSyncChange *change)
Gets the changetype of a change.
char * initial_format_name
int osync_change_get_datasize(OSyncChange *change)
Gets the size of the data of a change.
Represent a group of members that should be synchronized.
OSyncChange * osync_change_new(void)
Spawns a new change object.
const char * osync_change_get_uid(OSyncChange *change)
Gets the uid of a change.
A member of a group which represent a single device.
OSyncObjFormat * osync_change_get_objformat(OSyncChange *change)
Gets the object format of a change.
void * osync_try_malloc0(unsigned int size, OSyncError **error)
Safely tries to malloc memory.
void osync_debug(const char *subpart, int level, const char *message,...)
Used for debugging.
void osync_error_update(OSyncError **error, const char *format,...)
Updates the error message.
const char * osync_objformat_get_name(OSyncObjFormat *format)
Returns the name of a object format.
void osync_change_set_member(OSyncChange *change, OSyncMember *member)
Sets the member of a change.
void osync_error_set(OSyncError **error, OSyncErrorType type, const char *format,...)
Sets the error.
const char * osync_error_print(OSyncError **error)
Returns the message of the error.
void osync_trace(OSyncTraceType type, const char *message,...)
Used for tracing the application.
const char * osync_objtype_get_name(OSyncObjType *type)
Returns the name of a object type.
OSyncObjType * osync_change_get_objtype(OSyncChange *change)
Gets the object type of a change.
OSyncMember * osync_member_from_id(OSyncGroup *group, int id)
Searches for a member by its id.
Represent a hashtable which can be used to check if changes have been modifed or deleted.
OSyncChangeType changetype
char * osync_change_get_data(OSyncChange *change)
Gets the data of a change.