53 = { {
"film_rolls",
"id IN (SELECT film_id FROM main.images WHERE id = ?2)", NULL },
54 {
"images",
"id = ?2", NULL },
55 {
"history",
"imgid = ?2",
"imgid" },
56 {
"masks_history",
"imgid = ?2",
"imgid" },
57 {
"module_order",
"imgid = ?2",
"imgid" },
58 {
"tagged_images",
"imgid = ?2",
"imgid" },
59 {
"color_labels",
"imgid = ?2",
"imgid" },
60 {
"meta_data",
"id = ?2",
"id" },
61 {
"history_hash",
"imgid = ?2",
"imgid" } };
69 gchar *pragma = g_strdup_printf(
"PRAGMA memory.table_info('removed_%s')", table);
70 sqlite3_stmt *stmt = NULL;
75 GString *columns = g_string_new(NULL);
76 while(sqlite3_step(stmt) == SQLITE_ROW)
78 const char *
name = (
const char *)sqlite3_column_text(stmt, 1);
79 if(!g_strcmp0(
name,
"snap_id") || !g_strcmp0(
name,
"undo_imgid"))
continue;
80 if(columns->len > 0) g_string_append_c(columns,
',');
81 g_string_append(columns,
name);
83 sqlite3_finalize(stmt);
86 const gboolean empty = (columns->len == 0);
87 return g_string_free(columns, empty);
92static gboolean
_run(
const char *query,
const int snap_id,
const int32_t imgid)
94 sqlite3_stmt *stmt = NULL;
100 const gboolean ok = (sqlite3_step(stmt) == SQLITE_DONE);
101 sqlite3_finalize(stmt);
110 sqlite3_stmt *stmt = NULL;
112 "SELECT MAX(snap_id) FROM memory.removed_images WHERE undo_imgid = ?1",
119 if(sqlite3_step(stmt) == SQLITE_ROW) snap_id = sqlite3_column_int(stmt, 0) + 1;
120 sqlite3_finalize(stmt);
131static void _debug_memory(
const char *stage,
const int snap_id,
const int32_t imgid)
135 stage, snap_id, imgid, (
long long)sqlite3_memory_used());
140 gboolean all_ok =
TRUE;
151 const int snap_id =
_next_id(imgid);
163 gchar *query = g_strdup_printf(
"INSERT INTO memory.removed_%s (snap_id, undo_imgid, %s)"
164 " SELECT ?1, ?2, %s FROM main.%s WHERE %s",
167 all_ok =
_run(query, snap_id, imgid);
179 all_ok = all_ok &&
_run(
"INSERT INTO memory.removed_groups (snap_id, undo_imgid, id, group_id)"
180 " SELECT ?1, ?2, id, group_id FROM main.images"
181 " WHERE group_id = (SELECT group_id FROM main.images WHERE id = ?2)",
190 return all_ok ? snap_id : -1;
203 gboolean all_ok =
TRUE;
216 gchar *clear = g_strdup_printf(
"DELETE FROM main.%s WHERE %s = ?2",
218 all_ok =
_run(clear, snap_id, imgid);
224 gchar *query = g_strdup_printf(
"INSERT OR IGNORE INTO main.%s (%s)"
225 " SELECT %s FROM memory.removed_%s"
226 " WHERE snap_id = ?1 AND undo_imgid = ?2",
229 all_ok = all_ok &&
_run(query, snap_id, imgid);
238 all_ok = all_ok &&
_run(
"UPDATE main.images SET group_id ="
239 " (SELECT g.group_id FROM memory.removed_groups AS g"
240 " WHERE g.snap_id = ?1 AND g.undo_imgid = ?2 AND g.id = main.images.id)"
241 " WHERE id IN (SELECT id FROM memory.removed_groups"
242 " WHERE snap_id = ?1 AND undo_imgid = ?2)",
250 all_ok = all_ok &&
_run(
"UPDATE main.images SET group_id = id"
251 " WHERE id IN (SELECT id FROM memory.removed_groups"
252 " WHERE snap_id = ?1 AND undo_imgid = ?2)"
253 " AND group_id NOT IN (SELECT id FROM main.images)",
268 gchar *query = g_strdup_printf(
"DELETE FROM memory.removed_%s WHERE snap_id = ?1 AND undo_imgid = ?2",
270 _run(query, snap_id, imgid);
274 _run(
"DELETE FROM memory.removed_groups WHERE snap_id = ?1 AND undo_imgid = ?2", snap_id, imgid);
sqlite3 * dt_database_get_sqlite3_global(void)
void dt_database_rollback_transaction(void)
#define dt_database_start_transaction()
#define dt_database_release_transaction()
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
static const _removed_table_t _removed_tables[]
static gboolean _run(const char *query, const int snap_id, const int32_t imgid)
void dt_removed_image_repository_clear(const int snap_id, const int32_t imgid)
Drop snapshot snap_id of imgid, making the removal permanent.
static gchar * _columns_of(const char *table)
gboolean dt_removed_image_repository_restore(const int snap_id, const int32_t imgid)
Copy snapshot snap_id of imgid back into main, film roll included.
static void _debug_memory(const char *stage, const int snap_id, const int32_t imgid)
static int _next_id(const int32_t imgid)
int dt_removed_image_repository_create(const int32_t imgid)
Copy every row imgid owns out of main, so the removal about to happen can be undone.
memory.removed_*: the staging area behind "undo remove from library".
Checked wrappers around the sqlite3_* calls: trace the statement, assert the return code,...
#define DT_DEBUG_SQLITE3_PREPARE_V2(a, b, c, d, e)
#define DT_DEBUG_SQLITE3_BIND_INT(a, b, c)