From 2b9c5c937a24d33427d74ddea871e07e21e873df Mon Sep 17 00:00:00 2001
From: deurstann <tristan.derouet@gmail.com>
Date: Mon, 1 Feb 2021 17:19:46 +0100
Subject: [PATCH] Fixed move command

---
 src/database/queue.c | 141 +++++++++++++++++++++++++++++++++++++------
 1 file changed, 123 insertions(+), 18 deletions(-)

diff --git a/src/database/queue.c b/src/database/queue.c
index 65cf8444..a74fd073 100644
--- a/src/database/queue.c
+++ b/src/database/queue.c
@@ -444,30 +444,135 @@ database_queue_move(volatile sqlite3 *db, int from, int to)
      * 2. to
      * 3. from
      */
-    static const char *SQL_STMT =
+    static const char *SQL_TEMPLATE_toINFfrom =
+        "BEGIN TRANSACTION;"
+        "DELETE FROM queue_tmp;"
+        "INSERT INTO queue_tmp(position, kara_id,priority)"
+         "WITH TEMP_TABLE AS ("
+        "   SELECT ROW_NUMBER() OVER(ORDER BY priority DESC, position ASC) AS POSITION, kara_id, priority"
+        "   FROM queue)"
+        "   SELECT POSITION, kara_id, priority"
+        "   FROM TEMP_TABLE"
+        "   WHERE POSITION < %d AND POSITION != %d"
+        "   ORDER BY POSITION;"
+        "INSERT INTO queue_tmp(position, kara_id,priority)"
+        "   VALUES(%d,("
+        "           WITH TEMP_TABLE AS ("
+        "               SELECT ROW_NUMBER() OVER(ORDER BY priority DESC, position ASC) AS POSITION, kara_id, priority"
+        "               FROM queue)"
+        "             SELECT kara_id"
+        "            FROM TEMP_TABLE"
+        "            WHERE POSITION = %d"
+        "           ),("
+        "              WITH TEMP_TABLE AS ("
+        "                   SELECT ROW_NUMBER() OVER(ORDER BY priority DESC, position ASC) AS POSITION, kara_id, priority"
+        "                   FROM queue)"
+        "           SELECT priority"
+        "              FROM TEMP_TABLE"
+        "              WHERE POSITION = %d"
+        "           ));";
+    static const char *SQL_TEMPLATE_toSUPfrom_Part1 =
         "BEGIN TRANSACTION;"
-        "UPDATE queue SET position = position + 1 WHERE position >= ?;"
-        "UPDATE queue SET position = ? WHERE position = ?;"
+        "DELETE FROM queue_tmp;"
+        "INSERT INTO queue_tmp(position, kara_id,priority)"
+         "WITH TEMP_TABLE AS ("
+        "   SELECT ROW_NUMBER() OVER(ORDER BY priority DESC, position ASC) AS POSITION, kara_id, priority"
+        "   FROM queue)"
+        "   SELECT POSITION, kara_id, priority"
+        "   FROM TEMP_TABLE"
+        "   WHERE POSITION < %d"
+        "   ORDER BY POSITION;"
+        "INSERT INTO queue_tmp(position, kara_id,priority)"
+         "WITH TEMP_TABLE AS ("
+        "   SELECT ROW_NUMBER() OVER(ORDER BY priority DESC, position ASC) AS POSITION, kara_id, priority"
+        "   FROM queue)"
+        "   SELECT POSITION-1, kara_id, priority"
+        "   FROM TEMP_TABLE"
+        "   WHERE POSITION > %d AND POSITION < %d"
+        "   ORDER BY POSITION;";
+        static const char *SQL_TEMPLATE_toSUPfrom_Part2 =
+        "INSERT INTO queue_tmp(position, kara_id,priority)"
+        "   VALUES(%d-1,("
+        "           WITH TEMP_TABLE AS ("
+        "               SELECT ROW_NUMBER() OVER(ORDER BY priority DESC, position ASC) AS POSITION, kara_id, priority"
+        "               FROM queue)"
+        "             SELECT kara_id"
+        "            FROM TEMP_TABLE"
+        "            WHERE POSITION = %d"
+        "           ),("
+        "              WITH TEMP_TABLE AS ("
+        "                   SELECT ROW_NUMBER() OVER(ORDER BY priority DESC, position ASC) AS POSITION, kara_id, priority"
+        "                   FROM queue)"
+        "           SELECT priority"
+        "               FROM TEMP_TABLE"
+        "              WHERE POSITION = "
+        "               CASE"
+        "               WHEN (SELECT COUNT(*) FROM TEMP_TABLE)>=%d THEN %d"
+        "               ELSE %d-1"
+        "               END"
+        "           ));";
+        static const char *SQL_TEMPLATE_PART_2_toINFfrom =
+        "INSERT INTO queue_tmp(position, kara_id,priority)"
+        "WITH TEMP_TABLE AS ("
+        "   SELECT ROW_NUMBER() OVER(ORDER BY priority DESC, position ASC) AS POSITION, kara_id, priority"
+        "   FROM queue)"
+        "   SELECT (POSITION+1) , kara_id, priority"
+        "   FROM TEMP_TABLE"
+        "   WHERE POSITION >= %d AND POSITION < %d"
+        "   ORDER BY POSITION;"
+        "INSERT INTO queue_tmp(position, kara_id,priority)"
+        "WITH TEMP_TABLE AS ("
+        "   SELECT ROW_NUMBER() OVER(ORDER BY priority DESC, position ASC) AS POSITION, kara_id, priority"
+        "   FROM queue)"
+        "   SELECT POSITION , kara_id, priority"
+        "   FROM TEMP_TABLE"
+        "   WHERE POSITION > %d AND POSITION >=%d"
+        "   ORDER BY POSITION;"
+        "DELETE FROM queue;"
+        "INSERT INTO queue(position, kara_id, priority)"
+        "   SELECT position, kara_id, priority"
+        "   FROM queue_tmp"
+        "   ORDER BY priority, position;"
+        "DELETE FROM queue_tmp;"
+        "COMMIT;";
+        static const char *SQL_TEMPLATE_PART_2_toSUPfrom =
+        "INSERT INTO queue_tmp(position, kara_id,priority)"
+        "WITH TEMP_TABLE AS ("
+        "   SELECT ROW_NUMBER() OVER(ORDER BY priority DESC, position ASC) AS POSITION, kara_id, priority"
+        "   FROM queue)"
+        "   SELECT POSITION , kara_id, priority"
+        "   FROM TEMP_TABLE"
+        "   WHERE POSITION >= %d AND POSITION != %d"
+        "   ORDER BY POSITION;"
+        "DELETE FROM queue;"
+        "INSERT INTO queue(position, kara_id, priority)"
+        "   SELECT position, kara_id, priority"
+        "   FROM queue_tmp"
+        "   ORDER BY priority, position;"
+        "DELETE FROM queue_tmp;"
         "COMMIT;";
-    sqlite3_stmt *stmt = 0;
     bool ret = false;
-    int code;
-
-    SQLITE_PREPARE(db, stmt, SQL_STMT, error);
-    SQLITE_BIND_INT(db, stmt, 1, to, error);
-    SQLITE_BIND_INT(db, stmt, 2, to, error);
-    SQLITE_BIND_INT(db, stmt, 3, from, error);
-
-    code = sqlite3_step(stmt);
-
-    if (code != SQLITE_ROW && code != SQLITE_DONE && code != SQLITE_OK) {
-        LOG_ERROR("DB", "Move failed");
-        goto error;
+    char SQL_Part1[LKT_MAX_SQLITE_STATEMENT];
+    char SQL_Part2[LKT_MAX_SQLITE_STATEMENT];
+    char SQL_Part3[LKT_MAX_SQLITE_STATEMENT];
+    if(to < from) {
+        safe_snprintf(SQL_Part1, LKT_MAX_SQLITE_STATEMENT, SQL_TEMPLATE_toINFfrom, to, from, to, from, to);
+        safe_snprintf(SQL_Part2, LKT_MAX_SQLITE_STATEMENT, SQL_TEMPLATE_PART_2_toINFfrom, to, from, from, to);
+        SQLITE_EXEC(db, SQL_Part1, error);
+        SQLITE_EXEC(db, SQL_Part2, error);
+    }
+    else {
+        safe_snprintf(SQL_Part1, LKT_MAX_SQLITE_STATEMENT, SQL_TEMPLATE_toSUPfrom_Part1, from, from, to);
+        safe_snprintf(SQL_Part2, LKT_MAX_SQLITE_STATEMENT, SQL_TEMPLATE_toSUPfrom_Part2, to, from, to,to,to);
+        safe_snprintf(SQL_Part3, LKT_MAX_SQLITE_STATEMENT, SQL_TEMPLATE_PART_2_toSUPfrom, to, from, from, to);
+        SQLITE_EXEC(db, SQL_Part1, error);
+        SQLITE_EXEC(db, SQL_Part2, error);
+        SQLITE_EXEC(db, SQL_Part3, error);
     }
-
     ret = true;
+    return true;
 error:
-    sqlite3_finalize(stmt);
+    SQLITE_DO_ROLLBACK(db);
     return ret;
 }
 
-- 
GitLab