diff --git a/src/commands.c b/src/commands.c index cc53c0c4a97f77739c24b2d270c2a7c276f1cf6b..709d7f4f8c7fbb475289f0d84b1832524ac75715 100644 --- a/src/commands.c +++ b/src/commands.c @@ -59,7 +59,7 @@ command_update(struct lkt_state *srv, size_t c, char *argv[LKT_MESSAGE_ARGS_MAX] } static inline void * -__rescan(void * arg) +__rescan(void *arg) { struct lkt_state *srv = arg; database_update(srv->db, srv->kara_prefix); diff --git a/src/database/queue.c b/src/database/queue.c index 477b7de1c397dcdd11a08a3c0919d0bba561c258..aba0e00df63b2d16178907f0c83c4a5dd0abe431 100644 --- a/src/database/queue.c +++ b/src/database/queue.c @@ -134,6 +134,7 @@ queue_add_with_col_like_str(volatile sqlite3 *db, const char *col, const char *v SQLITE_BIND_INT(db, stmt, 1, priority, error); SQLITE_BIND_TEXT(db, stmt, 2, val, error); SQLITE_STEP_DONE(db, stmt, error); + sqlite3_finalize(stmt); /* Reorder kara that are after the current one, do this shit only if priority > 1... */ if (priority > 1) @@ -141,7 +142,6 @@ queue_add_with_col_like_str(volatile sqlite3 *db, const char *col, const char *v /* End */ SQLITE_EXEC(db, "COMMIT;", error); - sqlite3_finalize(stmt); return true; error: @@ -153,24 +153,58 @@ error: bool database_queue_add_plt(volatile sqlite3 *db, const char *plt_name, int priority) { +#define CURRENT_POS_OR_0 /* To move karas after the current */ \ + "(SELECT CASE WHEN (SELECT current FROM queue_state) IS NULL THEN 0" \ + " ELSE (SELECT current FROM queue_state) END AS val LIMIT 1)" static const char *SQL_STMT = + /* Insert the playlist */ "INSERT INTO queue (kara_id, priority) " "SELECT kara.id, ?" - " FROM kara" - " JOIN kara_playlist ON kara_id = kara.id AND kara.available = 1" - " JOIN playlist ON playlist_id = playlist.id AND playlist.name = ?" - " ORDER BY RANDOM();"; - bool status = false; + " FROM kara" + " JOIN kara_playlist ON kara_id = kara.id AND kara.available = 1" + " JOIN playlist ON playlist_id = playlist.id AND playlist.name = ?" + " ORDER BY RANDOM();"; + static const char *SQL_REORDER = + /* Create temporary tables */ + "CREATE TEMPORARY TABLE queue_tmp" + " ( position INTEGER PRIMARY KEY AUTOINCREMENT CHECK(position > 0)" + " , kara_id INTEGER" + " , priority INTEGER NOT NULL DEFAULT 1 CHECK(priority > 0 AND priority < 6)" + " );" + /* Separate karas that are after the current one */ + "INSERT INTO queue_tmp (kara_id, priority) SELECT kara_id, priority FROM queue WHERE position > " CURRENT_POS_OR_0 ";" + "DELETE FROM queue WHERE position > " CURRENT_POS_OR_0 ";" + /* Insert back */ + "INSERT INTO queue (position, kara_id, priority)" + " SELECT position + " CURRENT_POS_OR_0 ", kara_id, priority" + " FROM queue_tmp" + " ORDER BY priority, position;" + /* Drop temporary tables */ + "DROP TABLE queue_tmp;" + "DELETE FROM sqlite_sequence WHERE name = 'queue_tmp';"; +#undef CURRENT_POS_OR_0 sqlite3_stmt *stmt = NULL; + /* Begin, transactions are atomic so we won't be anoyed by multi-threading */ + SQLITE_EXEC(db, "BEGIN TRANSACTION;", error); + SQLITE_PREPARE(db, stmt, SQL_STMT, error); SQLITE_BIND_INT(db, stmt, 1, priority, error); SQLITE_BIND_TEXT(db, stmt, 2, plt_name, error); SQLITE_STEP_DONE(db, stmt, error); - status = true; + sqlite3_finalize(stmt); + + /* Do the move shit only if the priority > 1 */ + if (priority > 1) + SQLITE_EXEC(db, SQL_REORDER, error); + + SQLITE_EXEC(db, "COMMIT;", error); + return true; + error: + SQLITE_DO_ROLLBACK(db); sqlite3_finalize(stmt); - return status; + return false; } bool