mf/subcommand_prune.cpp

39 lines
1.5 KiB
C++

#include "database.h"
#include "subcommands.h"
static inline void is_file(sqlite3_context* context, int argc, sqlite3_value** argv);
void subcommand_prune(const Parser& parser) {
if (parser.arguments.size() != 1) {
fprintf(stderr, HELP_TEXT, parser.program_name);
exit(1);
}
Database db = Database::find(false);
// https://stackoverflow.com/a/4929486
int error_code = sqlite3_create_function(db.db.get(), "is_file", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC | SQLITE_DIRECTONLY, &db.path, is_file, nullptr, nullptr);
if (error_code != SQLITE_OK) {
throw Sqlite3Exception(error_code, &db.db);
}
Sqlite3Statement delete_stmt(db.db, "DELETE FROM memes WHERE NOT is_file(path)");
db.db.exec(delete_stmt);
sqlite3_create_function(db.db.get(), "is_file", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC | SQLITE_DIRECTONLY, &db.path, nullptr, nullptr, nullptr);
Sqlite3Statement vacuum_stmt(db.db, "VACUUM");
db.db.exec(vacuum_stmt);
}
static inline void is_file(sqlite3_context* context, int argc, sqlite3_value** argv) {
if (argc != 1) {
sqlite3_result_error(context, "is_file() expects one argument", -1);
sqlite3_result_error_code(context, SQLITE_MISUSE);
return;
}
const std::filesystem::path* db_path = static_cast<const std::filesystem::path*>(sqlite3_user_data(context));
std::filesystem::path file_path = db_path->parent_path() / reinterpret_cast<const char*>(sqlite3_value_text(argv[0]));
sqlite3_result_int(context, std::filesystem::is_regular_file(file_path));
}