@@ -786,6 +786,88 @@ void cloudsync_network_reset_sync_version (sqlite3_context *context, int argc, s
786786 dbutils_settings_set_key_value (db , context , CLOUDSYNC_KEY_SEND_SEQ , buf );
787787}
788788
789+ /**
790+ * Cleanup all local data from cloudsync-enabled tables, so the database can be safely reused
791+ * by another user without exposing any data from the previous session.
792+ *
793+ * Warning: this function deletes all data from the tables. Use with caution.
794+ */
795+ void cloudsync_network_logout (sqlite3_context * context , int argc , sqlite3_value * * argv ) {
796+ bool completed = false;
797+ char * errmsg = NULL ;
798+ sqlite3 * db = sqlite3_context_db_handle (context );
799+
800+ // if the network layer is enabled, remove the token or apikey
801+ sqlite3_exec (db , "SELECT cloudsync_network_set_token('');" , NULL , NULL , NULL );
802+
803+ // get the list of cloudsync-enabled tables
804+ char * sql = "SELECT tbl_name, key, value FROM cloudsync_table_settings;" ;
805+ char * * result = NULL ;
806+ int nrows , ncols ;
807+ int rc = sqlite3_get_table (db , sql , & result , & nrows , & ncols , NULL );
808+ if (rc != SQLITE_OK ) {
809+ errmsg = cloudsync_memory_mprintf ("Unable to get current cloudsync configuration. %s" , sqlite3_errmsg (db ));
810+ goto finalize ;
811+ }
812+
813+ // run everything in a savepoint
814+ rc = sqlite3_exec (db , "SAVEPOINT cloudsync_logout_sp;" , NULL , NULL , NULL );
815+ if (rc != SQLITE_OK ) {
816+ errmsg = cloudsync_memory_mprintf ("Unable to create cloudsync_logout savepoint. %s" , sqlite3_errmsg (db ));
817+ return ;
818+ }
819+
820+ // disable cloudsync for all the previously enabled tables: cloudsync_cleanup('*')
821+ rc = sqlite3_exec (db , "SELECT cloudsync_cleanup('*')" , NULL , NULL , NULL );
822+ if (rc != SQLITE_OK ) {
823+ errmsg = cloudsync_memory_mprintf ("Unable to cleanup current cloudsync configuration. %s" , sqlite3_errmsg (db ));
824+ goto finalize ;
825+ }
826+
827+ // delete all the local data for each previously enabled table
828+ // re-enable cloudsync on previously enabled tables
829+ for (int i = 1 ; i <= nrows ; i ++ ) {
830+ char * tbl_name = result [i * ncols + 0 ];
831+ char * key = result [i * ncols + 1 ];
832+ char * value = result [i * ncols + 2 ];
833+
834+ if (strcmp (key , "algo" ) != 0 ) continue ;
835+
836+ sql = cloudsync_memory_mprintf ("DELETE FROM \"%w\";" , tbl_name );
837+ rc = sqlite3_exec (db , sql , NULL , NULL , NULL );
838+ cloudsync_memory_free (sql );
839+ if (rc != SQLITE_OK ) {
840+ errmsg = cloudsync_memory_mprintf ("Unable to delete data from table %s. %s" , tbl_name , sqlite3_errmsg (db ));
841+ goto finalize ;
842+ }
843+
844+ sql = cloudsync_memory_mprintf ("SELECT cloudsync_init(\"%w\", \"%w\", 1);" , tbl_name , value );
845+ rc = sqlite3_exec (db , sql , NULL , NULL , NULL );
846+ cloudsync_memory_free (sql );
847+ if (rc != SQLITE_OK ) {
848+ errmsg = cloudsync_memory_mprintf ("Unable to enable cloudsync on table %s. %s" , tbl_name , sqlite3_errmsg (db ));
849+ goto finalize ;
850+ }
851+ }
852+
853+ completed = true;
854+
855+ finalize :
856+ if (completed ) {
857+ sqlite3_exec (db , "RELEASE cloudsync_logout_sp;" , NULL , NULL , NULL );
858+ } else {
859+ // cleanup:
860+ // ROLLBACK TO command reverts the state of the database back to what it was just after the corresponding SAVEPOINT
861+ // then RELEASE to remove the SAVEPOINT from the transaction stack
862+ sqlite3_exec (db , "ROLLBACK TO cloudsync_logout_sp;" , NULL , NULL , NULL );
863+ sqlite3_exec (db , "RELEASE cloudsync_logout_sp;" , NULL , NULL , NULL );
864+ sqlite3_result_error (context , errmsg , -1 );
865+ sqlite3_result_error_code (context , rc );
866+ }
867+ sqlite3_free_table (result );
868+ cloudsync_memory_free (errmsg );
869+ }
870+
789871// MARK: -
790872
791873int cloudsync_network_register (sqlite3 * db , char * * pzErrMsg , void * ctx ) {
@@ -821,6 +903,9 @@ int cloudsync_network_register (sqlite3 *db, char **pzErrMsg, void *ctx) {
821903 rc = dbutils_register_function (db , "cloudsync_network_reset_sync_version" , cloudsync_network_reset_sync_version , 0 , pzErrMsg , ctx , NULL );
822904 if (rc != SQLITE_OK ) return rc ;
823905
906+ rc = dbutils_register_function (db , "cloudsync_network_logout" , cloudsync_network_logout , 0 , pzErrMsg , ctx , NULL );
907+ if (rc != SQLITE_OK ) return rc ;
908+
824909 return rc ;
825910}
826911#endif
0 commit comments