Implemented deletion functionality, and lingering records are removed fixes #49
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
#ifndef ARTISTREPOSITORY_H_
|
#ifndef ARTISTREPOSITORY_H_
|
||||||
#define ARTISTREPOSITORY_H_
|
#define ARTISTREPOSITORY_H_
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "database/BaseRepository.h"
|
#include "database/BaseRepository.h"
|
||||||
@@ -16,14 +17,19 @@ namespace database
|
|||||||
|
|
||||||
std::vector<model::Artist> retrieveRecords();
|
std::vector<model::Artist> retrieveRecords();
|
||||||
|
|
||||||
|
std::pair<model::Artist, int> retrieveRecordWithSongCount(model::Artist&, type::ArtistFilter);
|
||||||
|
|
||||||
model::Artist retrieveRecord(model::Artist&, type::ArtistFilter);
|
model::Artist retrieveRecord(model::Artist&, type::ArtistFilter);
|
||||||
|
|
||||||
bool doesArtistExist(const model::Artist&, type::ArtistFilter);
|
bool doesArtistExist(const model::Artist&, type::ArtistFilter);
|
||||||
|
|
||||||
void saveRecord(const model::Artist&);
|
void saveRecord(const model::Artist&);
|
||||||
|
void deleteArtist(const model::Artist&, type::ArtistFilter);
|
||||||
private:
|
private:
|
||||||
std::vector<model::Artist> parseRecords(MYSQL_STMT*);
|
std::vector<model::Artist> parseRecords(MYSQL_STMT*);
|
||||||
|
|
||||||
|
std::pair<model::Artist, int> parseRecordWithSongCount(MYSQL_STMT*);
|
||||||
|
|
||||||
// TODO: After parseRecord(MYSQL_STMT*) is implemented
|
// TODO: After parseRecord(MYSQL_STMT*) is implemented
|
||||||
// remove parseRecord(MYSQL_RES*)
|
// remove parseRecord(MYSQL_RES*)
|
||||||
model::Artist parseRecord(MYSQL_RES*);
|
model::Artist parseRecord(MYSQL_RES*);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef GENREREPOSITORY_H_
|
#ifndef GENREREPOSITORY_H_
|
||||||
#define GENREREPOSITORY_H_
|
#define GENREREPOSITORY_H_
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "database/BaseRepository.h"
|
#include "database/BaseRepository.h"
|
||||||
@@ -16,14 +17,19 @@ namespace database
|
|||||||
|
|
||||||
std::vector<model::Genre> retrieveRecords();
|
std::vector<model::Genre> retrieveRecords();
|
||||||
|
|
||||||
|
std::pair<model::Genre, int> retrieveRecordWithSongCount(model::Genre&, type::GenreFilter);
|
||||||
|
|
||||||
model::Genre retrieveRecord(model::Genre&, type::GenreFilter);
|
model::Genre retrieveRecord(model::Genre&, type::GenreFilter);
|
||||||
|
|
||||||
bool doesGenreExist(const model::Genre&, type::GenreFilter);
|
bool doesGenreExist(const model::Genre&, type::GenreFilter);
|
||||||
|
|
||||||
void saveRecord(const model::Genre&);
|
void saveRecord(const model::Genre&);
|
||||||
|
void deleteRecord(const model::Genre&, type::GenreFilter);
|
||||||
private:
|
private:
|
||||||
std::vector<model::Genre> parseRecords(MYSQL_STMT*);
|
std::vector<model::Genre> parseRecords(MYSQL_STMT*);
|
||||||
|
|
||||||
|
std::pair<model::Genre, int> parseRecordWithSongCount(MYSQL_STMT*);
|
||||||
|
|
||||||
// TODO: After parseRecord(MYSQL_STMT*) is implemented
|
// TODO: After parseRecord(MYSQL_STMT*) is implemented
|
||||||
// remove parseRecord(MYSQL_RES*)
|
// remove parseRecord(MYSQL_RES*)
|
||||||
model::Genre parseRecord(MYSQL_RES*);
|
model::Genre parseRecord(MYSQL_RES*);
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace database
|
|||||||
|
|
||||||
model::Song retrieveRecord(model::Song&, type::SongFilter);
|
model::Song retrieveRecord(model::Song&, type::SongFilter);
|
||||||
|
|
||||||
void deleteRecord(const model::Song&);
|
bool deleteRecord(const model::Song&);
|
||||||
void saveRecord(const model::Song&);
|
void saveRecord(const model::Song&);
|
||||||
private:
|
private:
|
||||||
std::vector<model::Song> parseRecords(MYSQL_RES*); // TODO: to be removed
|
std::vector<model::Song> parseRecords(MYSQL_RES*); // TODO: to be removed
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef YEARREPOSITORY_H_
|
#ifndef YEARREPOSITORY_H_
|
||||||
#define YEARREPOSITORY_H_
|
#define YEARREPOSITORY_H_
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "database/BaseRepository.h"
|
#include "database/BaseRepository.h"
|
||||||
@@ -16,14 +17,19 @@ namespace database
|
|||||||
|
|
||||||
std::vector<model::Year> retrieveRecords();
|
std::vector<model::Year> retrieveRecords();
|
||||||
|
|
||||||
|
std::pair<model::Year, int> retrieveRecordWithSongCount(model::Year&, type::YearFilter);
|
||||||
|
|
||||||
model::Year retrieveRecord(model::Year&, type::YearFilter);
|
model::Year retrieveRecord(model::Year&, type::YearFilter);
|
||||||
|
|
||||||
bool doesYearExist(const model::Year&, type::YearFilter);
|
bool doesYearExist(const model::Year&, type::YearFilter);
|
||||||
|
|
||||||
void saveRecord(const model::Year&);
|
void saveRecord(const model::Year&);
|
||||||
|
void deleteYear(const model::Year&, type::YearFilter);
|
||||||
private:
|
private:
|
||||||
std::vector<model::Year> parseRecords(MYSQL_STMT*);
|
std::vector<model::Year> parseRecords(MYSQL_STMT*);
|
||||||
|
|
||||||
|
std::pair<model::Year, int> parseRecordWithSongCount(MYSQL_STMT*);
|
||||||
|
|
||||||
// TODO: After parseRecord(MYSQL_STMT*) is implemented
|
// TODO: After parseRecord(MYSQL_STMT*) is implemented
|
||||||
// remove parseRecord(MYSQL_RES*)
|
// remove parseRecord(MYSQL_RES*)
|
||||||
model::Year parseRecord(MYSQL_RES*);
|
model::Year parseRecord(MYSQL_RES*);
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ namespace manager
|
|||||||
model::Artist retrieveArtist(model::Artist&);
|
model::Artist retrieveArtist(model::Artist&);
|
||||||
model::Artist saveArtist(const model::Song&);
|
model::Artist saveArtist(const model::Song&);
|
||||||
|
|
||||||
|
void deleteArtist(const model::Song&);
|
||||||
|
|
||||||
static void printArtist(const model::Artist&);
|
static void printArtist(const model::Artist&);
|
||||||
private:
|
private:
|
||||||
model::BinaryPath m_bConf;
|
model::BinaryPath m_bConf;
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ namespace manager
|
|||||||
model::Genre retrieveGenre(model::Genre&);
|
model::Genre retrieveGenre(model::Genre&);
|
||||||
model::Genre saveGenre(const model::Song&);
|
model::Genre saveGenre(const model::Song&);
|
||||||
|
|
||||||
|
void deleteGenre(const model::Song&);
|
||||||
|
|
||||||
static void printGenre(const model::Genre&);
|
static void printGenre(const model::Genre&);
|
||||||
private:
|
private:
|
||||||
model::BinaryPath m_bConf;
|
model::BinaryPath m_bConf;
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ namespace manager
|
|||||||
model::Year retrieveYear(model::Year&);
|
model::Year retrieveYear(model::Year&);
|
||||||
model::Year saveYear(const model::Song&);
|
model::Year saveYear(const model::Song&);
|
||||||
|
|
||||||
|
void deleteYear(const model::Song&);
|
||||||
|
|
||||||
static void printYear(const model::Year&);
|
static void printYear(const model::Year&);
|
||||||
private:
|
private:
|
||||||
model::BinaryPath m_bConf;
|
model::BinaryPath m_bConf;
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ std::vector<model::Album> database::AlbumRepository::retrieveRecords()
|
|||||||
|
|
||||||
std::pair<model::Album, int> database::AlbumRepository::retrieveRecordWithSongCount(model::Album& album, type::AlbumFilter filter = type::AlbumFilter::id)
|
std::pair<model::Album, int> database::AlbumRepository::retrieveRecordWithSongCount(model::Album& album, type::AlbumFilter filter = type::AlbumFilter::id)
|
||||||
{
|
{
|
||||||
|
std::cout << "retrieving album with song count" << std::endl;
|
||||||
std::stringstream qry;
|
std::stringstream qry;
|
||||||
auto conn = setupMysqlConnection();
|
auto conn = setupMysqlConnection();
|
||||||
auto stmt = mysql_stmt_init(conn);
|
auto stmt = mysql_stmt_init(conn);
|
||||||
@@ -44,7 +45,7 @@ std::pair<model::Album, int> database::AlbumRepository::retrieveRecordWithSongCo
|
|||||||
|
|
||||||
switch (filter) {
|
switch (filter) {
|
||||||
case type::AlbumFilter::id:
|
case type::AlbumFilter::id:
|
||||||
qry << "alb.AlbumId = ?";
|
qry << "sng.AlbumId = ?";
|
||||||
|
|
||||||
params[0].buffer_type = MYSQL_TYPE_LONG;
|
params[0].buffer_type = MYSQL_TYPE_LONG;
|
||||||
params[0].buffer = (char*)&album.id;
|
params[0].buffer = (char*)&album.id;
|
||||||
@@ -62,15 +63,11 @@ std::pair<model::Album, int> database::AlbumRepository::retrieveRecordWithSongCo
|
|||||||
status = mysql_stmt_bind_param(stmt, params);
|
status = mysql_stmt_bind_param(stmt, params);
|
||||||
status = mysql_stmt_execute(stmt);
|
status = mysql_stmt_execute(stmt);
|
||||||
|
|
||||||
std::cout << "query has been performed" << std::endl;
|
|
||||||
|
|
||||||
auto albWSC = parseRecordWithSongCount(stmt);
|
auto albWSC = parseRecordWithSongCount(stmt);
|
||||||
|
|
||||||
mysql_stmt_close(stmt);
|
mysql_stmt_close(stmt);
|
||||||
mysql_close(conn);
|
mysql_close(conn);
|
||||||
|
|
||||||
std::cout << "record has been parsed" << std::endl;
|
|
||||||
|
|
||||||
return albWSC;
|
return albWSC;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,10 +334,14 @@ std::pair<model::Album, int> database::AlbumRepository::parseRecordWithSongCount
|
|||||||
std::cout << "parsing album record with song count" << std::endl;
|
std::cout << "parsing album record with song count" << std::endl;
|
||||||
mysql_stmt_store_result(stmt);
|
mysql_stmt_store_result(stmt);
|
||||||
auto rowCount = mysql_stmt_num_rows(stmt);
|
auto rowCount = mysql_stmt_num_rows(stmt);
|
||||||
std::cout << "result count " << rowCount << std::endl;
|
|
||||||
|
|
||||||
model::Album album;
|
model::Album album;
|
||||||
int songCount;
|
int songCount = 0;
|
||||||
|
|
||||||
|
if (rowCount == 0) {
|
||||||
|
std::cout << "no results" << std::endl;
|
||||||
|
return std::make_pair(album, songCount);
|
||||||
|
}
|
||||||
|
|
||||||
if (mysql_stmt_field_count(stmt) == 0) {
|
if (mysql_stmt_field_count(stmt) == 0) {
|
||||||
std::cout << "field count is 0, must be an incorrect query" << std::endl;
|
std::cout << "field count is 0, must be an incorrect query" << std::endl;
|
||||||
@@ -348,8 +349,8 @@ std::pair<model::Album, int> database::AlbumRepository::parseRecordWithSongCount
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto res = mysql_stmt_result_metadata(stmt);
|
auto res = mysql_stmt_result_metadata(stmt);
|
||||||
const auto valAmt = 4;
|
constexpr auto valAmt = 4;
|
||||||
const auto strLen = 1024;
|
constexpr auto strLen = 1024;
|
||||||
unsigned long len[valAmt];
|
unsigned long len[valAmt];
|
||||||
my_bool nullRes[valAmt];
|
my_bool nullRes[valAmt];
|
||||||
|
|
||||||
@@ -376,8 +377,8 @@ std::pair<model::Album, int> database::AlbumRepository::parseRecordWithSongCount
|
|||||||
|
|
||||||
val[3].buffer_type = MYSQL_TYPE_LONG;
|
val[3].buffer_type = MYSQL_TYPE_LONG;
|
||||||
val[3].buffer = (char*)&songCount;
|
val[3].buffer = (char*)&songCount;
|
||||||
val[3].length = &len[2];
|
val[3].length = &len[3];
|
||||||
val[3].is_null = &nullRes[2];
|
val[3].is_null = &nullRes[3];
|
||||||
|
|
||||||
auto status = mysql_stmt_bind_result(stmt, val);
|
auto status = mysql_stmt_bind_result(stmt, val);
|
||||||
status = mysql_stmt_fetch(stmt);
|
status = mysql_stmt_fetch(stmt);
|
||||||
|
|||||||
@@ -29,6 +29,49 @@ std::vector<model::Artist> database::ArtistRepository::retrieveRecords()
|
|||||||
return artists;
|
return artists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<model::Artist, int> database::ArtistRepository::retrieveRecordWithSongCount(model::Artist& artist, type::ArtistFilter filter = type::ArtistFilter::id)
|
||||||
|
{
|
||||||
|
std::cout << "retrieving artist record with song count" << std::endl;
|
||||||
|
std::stringstream qry;
|
||||||
|
auto conn = setupMysqlConnection();
|
||||||
|
auto stmt = mysql_stmt_init(conn);
|
||||||
|
|
||||||
|
qry << "SELECT art.*, COUNT(*) AS SongCount FROM Artist art LEFT JOIN ";
|
||||||
|
qry << "Song sng ON art.ArtistId=sng.ArtistId WHERE ";
|
||||||
|
|
||||||
|
MYSQL_BIND params[1];
|
||||||
|
std::memset(params, 0, sizeof(params));
|
||||||
|
|
||||||
|
switch (filter) {
|
||||||
|
case type::ArtistFilter::id:
|
||||||
|
qry << "sng.ArtistId = ?";
|
||||||
|
|
||||||
|
params[0].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
params[0].buffer = (char*)&artist.id;
|
||||||
|
params[0].length = 0;
|
||||||
|
params[0].is_null = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
qry << " GROUP BY art.ArtistId LIMIT 1";
|
||||||
|
|
||||||
|
const auto query = qry.str();
|
||||||
|
auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size());
|
||||||
|
status = mysql_stmt_bind_param(stmt, params);
|
||||||
|
status = mysql_stmt_execute(stmt);
|
||||||
|
|
||||||
|
std::cout << "Artist record with song count query ";
|
||||||
|
std::cout << "has been performed" << std::endl;
|
||||||
|
|
||||||
|
auto artWSC = parseRecordWithSongCount(stmt);
|
||||||
|
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
mysql_close(conn);
|
||||||
|
|
||||||
|
return artWSC;
|
||||||
|
}
|
||||||
|
|
||||||
model::Artist database::ArtistRepository::retrieveRecord(model::Artist& artist, type::ArtistFilter filter)
|
model::Artist database::ArtistRepository::retrieveRecord(model::Artist& artist, type::ArtistFilter filter)
|
||||||
{
|
{
|
||||||
@@ -160,6 +203,42 @@ void database::ArtistRepository::saveRecord(const model::Artist& artist)
|
|||||||
std::cout<< "inserted artist record" << std::endl;
|
std::cout<< "inserted artist record" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void database::ArtistRepository::deleteArtist(const model::Artist& artist, type::ArtistFilter filter = type::ArtistFilter::id) {
|
||||||
|
// TODO: implement this
|
||||||
|
std::cout << "delete Artist record" << std::endl;
|
||||||
|
std::stringstream qry;
|
||||||
|
auto conn = setupMysqlConnection();
|
||||||
|
auto stmt = mysql_stmt_init(conn);
|
||||||
|
|
||||||
|
qry << "DELETE FROM Artist WHERE ";
|
||||||
|
|
||||||
|
MYSQL_BIND params[1];
|
||||||
|
std::memset(params, 0, sizeof(params));
|
||||||
|
|
||||||
|
switch (filter) {
|
||||||
|
case type::ArtistFilter::id:
|
||||||
|
qry << "ArtistId = ?";
|
||||||
|
|
||||||
|
params[0].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
params[0].buffer = (char*)&artist.id;
|
||||||
|
params[0].length = 0;
|
||||||
|
params[0].is_null = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto query = qry.str();
|
||||||
|
|
||||||
|
auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size());
|
||||||
|
status = mysql_stmt_bind_param(stmt, params);
|
||||||
|
status = mysql_stmt_execute(stmt);
|
||||||
|
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
mysql_close(conn);
|
||||||
|
|
||||||
|
std::cout << "deleted artist record" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<model::Artist> database::ArtistRepository::parseRecords(MYSQL_STMT *stmt)
|
std::vector<model::Artist> database::ArtistRepository::parseRecords(MYSQL_STMT *stmt)
|
||||||
{
|
{
|
||||||
@@ -236,6 +315,55 @@ model::Artist database::ArtistRepository::parseRecord(MYSQL_RES* results)
|
|||||||
return artist;
|
return artist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<model::Artist, int> database::ArtistRepository::parseRecordWithSongCount(MYSQL_STMT *stmt)
|
||||||
|
{
|
||||||
|
std::cout << "parsing artist record with song count" << std::endl;
|
||||||
|
mysql_stmt_store_result(stmt);
|
||||||
|
|
||||||
|
const auto strLen = 1024;
|
||||||
|
const auto valAmt = 3;
|
||||||
|
unsigned long len[valAmt];
|
||||||
|
my_bool nullRes[valAmt];
|
||||||
|
|
||||||
|
model::Artist artist;
|
||||||
|
int songCount = 0;
|
||||||
|
|
||||||
|
if (mysql_stmt_num_rows(stmt) == 0) {
|
||||||
|
std::cout << "no results" << std::endl;
|
||||||
|
return std::make_pair(artist, songCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
MYSQL_BIND params[valAmt];
|
||||||
|
std::memset(params, 0, sizeof(params));
|
||||||
|
|
||||||
|
char art[strLen];
|
||||||
|
|
||||||
|
params[0].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
params[0].buffer = (char*)&artist.id;
|
||||||
|
params[0].length = &len[0];
|
||||||
|
params[0].is_null = &nullRes[0];
|
||||||
|
|
||||||
|
params[1].buffer_type = MYSQL_TYPE_STRING;
|
||||||
|
params[1].buffer = (char*)art;
|
||||||
|
params[1].buffer_length = strLen;
|
||||||
|
params[1].length = &len[1];
|
||||||
|
params[1].is_null = &nullRes[1];
|
||||||
|
|
||||||
|
params[2].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
params[2].buffer = (char*)&songCount;
|
||||||
|
params[2].length = &len[2];
|
||||||
|
params[2].is_null = &nullRes[2];
|
||||||
|
|
||||||
|
mysql_stmt_bind_result(stmt, params);
|
||||||
|
mysql_stmt_fetch(stmt);
|
||||||
|
|
||||||
|
artist.artist = std::move(art);
|
||||||
|
|
||||||
|
std::cout << "parsed artist record with song count" << std::endl;
|
||||||
|
|
||||||
|
return std::make_pair(artist, songCount);
|
||||||
|
}
|
||||||
|
|
||||||
model::Artist database::ArtistRepository::parseRecord(MYSQL_STMT *stmt)
|
model::Artist database::ArtistRepository::parseRecord(MYSQL_STMT *stmt)
|
||||||
{
|
{
|
||||||
std::cout << "parsing artist record" << std::endl;
|
std::cout << "parsing artist record" << std::endl;
|
||||||
|
|||||||
@@ -27,6 +27,49 @@ std::vector<model::Genre> database::GenreRepository::retrieveRecords()
|
|||||||
return genres;
|
return genres;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<model::Genre, int> database::GenreRepository::retrieveRecordWithSongCount(model::Genre& genre, type::GenreFilter filter = type::GenreFilter::id)
|
||||||
|
{
|
||||||
|
std::cout << "retrieving genre record with song count" << std::endl;
|
||||||
|
std::stringstream qry;
|
||||||
|
auto conn = setupMysqlConnection();
|
||||||
|
auto stmt = mysql_stmt_init(conn);
|
||||||
|
|
||||||
|
qry << "SELECT gnr.*, COUNT(*) AS SongCount FROM Genre gnr LEFT JOIN ";
|
||||||
|
qry << "Song sng ON gnr.GenreId=sng.GenreId WHERE ";
|
||||||
|
|
||||||
|
MYSQL_BIND params[1];
|
||||||
|
std::memset(params, 0, sizeof(params));
|
||||||
|
|
||||||
|
switch (filter) {
|
||||||
|
case type::GenreFilter::id:
|
||||||
|
qry << "sng.GenreId = ?";
|
||||||
|
|
||||||
|
params[0].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
params[0].buffer = (char*)&genre.id;
|
||||||
|
params[0].length = 0;
|
||||||
|
params[0].is_null = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
qry << " GROUP BY gnr.GenreId LIMIT 1";
|
||||||
|
|
||||||
|
const auto query = qry.str();
|
||||||
|
|
||||||
|
auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size());
|
||||||
|
status = mysql_stmt_bind_param(stmt, params);
|
||||||
|
status = mysql_stmt_execute(stmt);
|
||||||
|
|
||||||
|
auto gnrWSC = parseRecordWithSongCount(stmt);
|
||||||
|
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
mysql_close(conn);
|
||||||
|
|
||||||
|
std::cout << "retrieved genre record with song count" << std::endl;
|
||||||
|
|
||||||
|
return gnrWSC;
|
||||||
|
}
|
||||||
|
|
||||||
model::Genre database::GenreRepository::retrieveRecord(model::Genre& genre, type::GenreFilter filter)
|
model::Genre database::GenreRepository::retrieveRecord(model::Genre& genre, type::GenreFilter filter)
|
||||||
{
|
{
|
||||||
@@ -145,6 +188,44 @@ void database::GenreRepository::saveRecord(const model::Genre& genre)
|
|||||||
std::cout << "inserted record" << std::endl;
|
std::cout << "inserted record" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void database::GenreRepository::deleteRecord(const model::Genre& genre, type::GenreFilter filter = type::GenreFilter::id)
|
||||||
|
{
|
||||||
|
// TODO: implement this
|
||||||
|
std::cout << "deleting genre record" << std::endl;
|
||||||
|
std::stringstream qry;
|
||||||
|
auto conn = setupMysqlConnection();
|
||||||
|
auto stmt = mysql_stmt_init(conn);
|
||||||
|
|
||||||
|
qry << "DELETE FROM Genre WHERE ";
|
||||||
|
|
||||||
|
MYSQL_BIND params[1];
|
||||||
|
std::memset(params, 0, sizeof(params));
|
||||||
|
|
||||||
|
switch (filter) {
|
||||||
|
case type::GenreFilter::id:
|
||||||
|
qry << "GenreId = ?";
|
||||||
|
|
||||||
|
params[0].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
params[0].buffer = (char*)&genre.id;
|
||||||
|
params[0].length = 0;
|
||||||
|
params[0].is_null = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto query = qry.str();
|
||||||
|
|
||||||
|
auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size());
|
||||||
|
status = mysql_stmt_bind_param(stmt, params);
|
||||||
|
status = mysql_stmt_execute(stmt);
|
||||||
|
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
mysql_close(conn);
|
||||||
|
|
||||||
|
std::cout << "deleted genre record" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<model::Genre> database::GenreRepository::parseRecords(MYSQL_STMT *stmt)
|
std::vector<model::Genre> database::GenreRepository::parseRecords(MYSQL_STMT *stmt)
|
||||||
{
|
{
|
||||||
@@ -196,6 +277,55 @@ std::vector<model::Genre> database::GenreRepository::parseRecords(MYSQL_STMT *st
|
|||||||
return genres;
|
return genres;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<model::Genre, int> database::GenreRepository::parseRecordWithSongCount(MYSQL_STMT *stmt)
|
||||||
|
{
|
||||||
|
std::cout << "parsing genre record with song count" << std::endl;
|
||||||
|
mysql_stmt_store_result(stmt);
|
||||||
|
|
||||||
|
const auto strLen = 1024;
|
||||||
|
const auto valAmt = 3;
|
||||||
|
unsigned long len[valAmt];
|
||||||
|
my_bool nullRes[valAmt];
|
||||||
|
|
||||||
|
model::Genre genre;
|
||||||
|
int songCount = 0;
|
||||||
|
|
||||||
|
if (mysql_stmt_num_rows(stmt) == 0) {
|
||||||
|
std::cout << "no results" << std::endl;
|
||||||
|
return std::make_pair(genre, songCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
MYSQL_BIND val[valAmt];
|
||||||
|
std::memset(val, 0, sizeof(val));
|
||||||
|
|
||||||
|
char category[strLen] ;
|
||||||
|
|
||||||
|
val[0].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
val[0].buffer = (char*)&genre.id;
|
||||||
|
val[0].length = &len[0];
|
||||||
|
val[0].is_null = &nullRes[0];
|
||||||
|
|
||||||
|
val[1].buffer_type = MYSQL_TYPE_STRING;
|
||||||
|
val[1].buffer = (char*)category;
|
||||||
|
val[1].buffer_length = strLen;
|
||||||
|
val[1].length = &len[1];
|
||||||
|
val[1].is_null = &nullRes[1];
|
||||||
|
|
||||||
|
val[2].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
val[2].buffer = (char*)&songCount;
|
||||||
|
val[2].length = &len[2];
|
||||||
|
val[2].is_null = &nullRes[2];
|
||||||
|
|
||||||
|
mysql_stmt_bind_result(stmt, val);
|
||||||
|
mysql_stmt_fetch(stmt);
|
||||||
|
|
||||||
|
genre.category = std::move(category);
|
||||||
|
|
||||||
|
std::cout << "parsed genre record with song count" << std::endl;
|
||||||
|
|
||||||
|
return std::make_pair(genre, songCount);
|
||||||
|
}
|
||||||
|
|
||||||
model::Genre database::GenreRepository::parseRecord(MYSQL_RES* results)
|
model::Genre database::GenreRepository::parseRecord(MYSQL_RES* results)
|
||||||
{
|
{
|
||||||
std::cout << "parsing genre record" << std::endl;
|
std::cout << "parsing genre record" << std::endl;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ database::SongRepository::SongRepository(const std::string& path) : BaseReposito
|
|||||||
database::SongRepository::SongRepository(const model::BinaryPath& bConf) : BaseRepository(bConf)
|
database::SongRepository::SongRepository(const model::BinaryPath& bConf) : BaseRepository(bConf)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
std::vector<model::Song> database::SongRepository::retrieveRecords()
|
std::vector<model::Song> database::SongRepository::retrieveRecords()
|
||||||
{
|
{
|
||||||
auto conn = setupMysqlConnection();
|
auto conn = setupMysqlConnection();
|
||||||
@@ -134,7 +135,7 @@ bool database::SongRepository::doesSongExist(const model::Song& song, type::Song
|
|||||||
return (rowCount > 0) ? true : false;
|
return (rowCount > 0) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void database::SongRepository::deleteRecord(const model::Song& song)
|
bool database::SongRepository::deleteRecord(const model::Song& song)
|
||||||
{
|
{
|
||||||
auto conn = setupMysqlConnection();
|
auto conn = setupMysqlConnection();
|
||||||
auto status = 0;
|
auto status = 0;
|
||||||
@@ -144,6 +145,8 @@ void database::SongRepository::deleteRecord(const model::Song& song)
|
|||||||
auto result = performMysqlQuery(conn, query);
|
auto result = performMysqlQuery(conn, query);
|
||||||
|
|
||||||
mysql_close(conn);
|
mysql_close(conn);
|
||||||
|
|
||||||
|
return (result == 0) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void database::SongRepository::saveRecord(const model::Song& song)
|
void database::SongRepository::saveRecord(const model::Song& song)
|
||||||
|
|||||||
@@ -29,6 +29,50 @@ std::vector<model::Year> database::YearRepository::retrieveRecords()
|
|||||||
return yearRecs;
|
return yearRecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<model::Year, int> database::YearRepository::retrieveRecordWithSongCount(model::Year& year, type::YearFilter filter = type::YearFilter::id)
|
||||||
|
{
|
||||||
|
std::cout << "retrieving year record with song count" << std::endl;
|
||||||
|
std::stringstream qry;
|
||||||
|
auto conn = setupMysqlConnection();
|
||||||
|
auto stmt = mysql_stmt_init(conn);
|
||||||
|
|
||||||
|
qry << "SELECT yr.*, COUNT(*) AS SongCount FROM Year yr LEFT JOIN ";
|
||||||
|
qry << "Song sng ON yr.YearId=sng.YearId WHERE ";
|
||||||
|
|
||||||
|
MYSQL_BIND params[1];
|
||||||
|
std::memset(params, 0, sizeof(params));
|
||||||
|
|
||||||
|
switch (filter) {
|
||||||
|
case type::YearFilter::id:
|
||||||
|
qry << "sng.YearId = ?";
|
||||||
|
|
||||||
|
params[0].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
params[0].buffer = (char*)&year.id;
|
||||||
|
params[0].length = 0;
|
||||||
|
params[0].is_null = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
qry << " GROUP BY yr.YearId LIMIT 1";
|
||||||
|
|
||||||
|
const auto query = qry.str();
|
||||||
|
|
||||||
|
auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size());
|
||||||
|
status = mysql_stmt_bind_param(stmt, params);
|
||||||
|
status = mysql_stmt_execute(stmt);
|
||||||
|
|
||||||
|
auto yearWSC = parseRecordWithSongCount(stmt);
|
||||||
|
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
mysql_close(conn);
|
||||||
|
|
||||||
|
std::cout << "retrieved year record with song count" << std::endl;
|
||||||
|
|
||||||
|
return yearWSC;
|
||||||
|
}
|
||||||
|
|
||||||
model::Year database::YearRepository::retrieveRecord(model::Year& year, type::YearFilter filter)
|
model::Year database::YearRepository::retrieveRecord(model::Year& year, type::YearFilter filter)
|
||||||
{
|
{
|
||||||
// TODO: switch to prepared statements
|
// TODO: switch to prepared statements
|
||||||
@@ -140,6 +184,42 @@ void database::YearRepository::saveRecord(const model::Year& year)
|
|||||||
std::cout << "saved record" << std::endl;
|
std::cout << "saved record" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void database::YearRepository::deleteYear(const model::Year& year, type::YearFilter filter = type::YearFilter::id)
|
||||||
|
{
|
||||||
|
std::cout << "deleting year record" << std::endl;
|
||||||
|
std::stringstream qry;
|
||||||
|
auto conn = setupMysqlConnection();
|
||||||
|
auto stmt = mysql_stmt_init(conn);
|
||||||
|
|
||||||
|
qry << "DELETE FROM Year WHERE ";
|
||||||
|
|
||||||
|
MYSQL_BIND params[1];
|
||||||
|
std::memset(params, 0, sizeof(params));
|
||||||
|
|
||||||
|
switch (filter) {
|
||||||
|
case type::YearFilter::id:
|
||||||
|
qry << "YearId = ?";
|
||||||
|
|
||||||
|
params[0].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
params[0].buffer = (char*)&year.id;
|
||||||
|
params[0].length = 0;
|
||||||
|
params[0].is_null = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto query = qry.str();
|
||||||
|
|
||||||
|
auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size());
|
||||||
|
status = mysql_stmt_bind_param(stmt, params);
|
||||||
|
status = mysql_stmt_execute(stmt);
|
||||||
|
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
mysql_close(conn);
|
||||||
|
|
||||||
|
std::cout << "deleted year record" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<model::Year> database::YearRepository::parseRecords(MYSQL_STMT *stmt)
|
std::vector<model::Year> database::YearRepository::parseRecords(MYSQL_STMT *stmt)
|
||||||
{
|
{
|
||||||
@@ -185,6 +265,49 @@ std::vector<model::Year> database::YearRepository::parseRecords(MYSQL_STMT *stmt
|
|||||||
return yearRecs;
|
return yearRecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<model::Year, int> database::YearRepository::parseRecordWithSongCount(MYSQL_STMT *stmt)
|
||||||
|
{
|
||||||
|
std::cout << "parsing year record" << std::endl;
|
||||||
|
mysql_stmt_store_result(stmt);
|
||||||
|
|
||||||
|
constexpr auto valAmt = 3;
|
||||||
|
unsigned long len[valAmt];
|
||||||
|
my_bool nullRes[valAmt];
|
||||||
|
|
||||||
|
model::Year year;
|
||||||
|
int songCount = 0;
|
||||||
|
|
||||||
|
if (mysql_stmt_num_rows(stmt) == 0) {
|
||||||
|
std::cout << "no results" << std::endl;
|
||||||
|
return std::make_pair(year, songCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
MYSQL_BIND val[valAmt];
|
||||||
|
std::memset(val, 0, sizeof(val));
|
||||||
|
|
||||||
|
val[0].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
val[0].buffer = (char*)&year.id;
|
||||||
|
val[0].length = &len[0];
|
||||||
|
val[0].is_null = &nullRes[0];
|
||||||
|
|
||||||
|
val[1].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
val[1].buffer = (char*)&year.year;
|
||||||
|
val[1].length = &len[1];
|
||||||
|
val[1].is_null = &nullRes[1];
|
||||||
|
|
||||||
|
val[2].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
val[2].buffer = (char*)&songCount;
|
||||||
|
val[2].length = &len[2];
|
||||||
|
val[2].is_null = &nullRes[2];
|
||||||
|
|
||||||
|
mysql_stmt_bind_result(stmt, val);
|
||||||
|
mysql_stmt_fetch(stmt);
|
||||||
|
|
||||||
|
std::cout << "parsed year record from the database" << std::endl;
|
||||||
|
|
||||||
|
return std::make_pair(year, songCount);
|
||||||
|
}
|
||||||
|
|
||||||
model::Year database::YearRepository::parseRecord(MYSQL_RES *results)
|
model::Year database::YearRepository::parseRecord(MYSQL_RES *results)
|
||||||
{
|
{
|
||||||
std::cout << "parsing year record" << std::endl;
|
std::cout << "parsing year record" << std::endl;
|
||||||
|
|||||||
@@ -36,6 +36,23 @@ model::Artist manager::ArtistManager::saveArtist(const model::Song& song)
|
|||||||
return artist;
|
return artist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void manager::ArtistManager::deleteArtist(const model::Song& song)
|
||||||
|
{
|
||||||
|
model::Artist artist(song);
|
||||||
|
|
||||||
|
database::ArtistRepository artRepo(m_bConf);
|
||||||
|
auto artWSC = artRepo.retrieveRecordWithSongCount(artist, type::ArtistFilter::id);
|
||||||
|
|
||||||
|
if (artWSC.second > 1) {
|
||||||
|
std::cout << "artist still contain songs related to it";
|
||||||
|
std::cout << ", not delete" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "safe to delete the artist record" << std::endl;
|
||||||
|
artRepo.deleteArtist(artist, type::ArtistFilter::id);
|
||||||
|
}
|
||||||
|
|
||||||
void manager::ArtistManager::printArtist(const model::Artist& artist)
|
void manager::ArtistManager::printArtist(const model::Artist& artist)
|
||||||
{
|
{
|
||||||
std::cout << "\nartist record" << std::endl;
|
std::cout << "\nartist record" << std::endl;
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ void manager::DirectoryManager::deleteCoverArtFile(const std::string& covPath, c
|
|||||||
}
|
}
|
||||||
void manager::DirectoryManager::deleteDirectories(model::Song song, const std::string& rootPath)
|
void manager::DirectoryManager::deleteDirectories(model::Song song, const std::string& rootPath)
|
||||||
{
|
{
|
||||||
std::cout << "checking to for empty directories to delete" << std::endl;
|
std::cout << "checking for empty directories to delete" << std::endl;
|
||||||
const std::string art(rootPath + std::string("/") + song.artist);
|
const std::string art(rootPath + std::string("/") + song.artist);
|
||||||
const std::string alb(art + "/" + song.album);
|
const std::string alb(art + "/" + song.album);
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,23 @@ model::Genre manager::GenreManager::saveGenre(const model::Song& song)
|
|||||||
return genre;
|
return genre;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void manager::GenreManager::deleteGenre(const model::Song& song)
|
||||||
|
{
|
||||||
|
model::Genre genre(song);
|
||||||
|
|
||||||
|
database::GenreRepository gnrRepo(m_bConf);
|
||||||
|
auto gnrWSC = gnrRepo.retrieveRecordWithSongCount(genre, type::GenreFilter::id);
|
||||||
|
|
||||||
|
if (gnrWSC.second > 1) {
|
||||||
|
std::cout << "genre still contain songs related to it";
|
||||||
|
std::cout << ", will not delete" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "safe to delete the genre record" << std::endl;
|
||||||
|
gnrRepo.deleteRecord(genre, type::GenreFilter::id);
|
||||||
|
}
|
||||||
|
|
||||||
void manager::GenreManager::printGenre(const model::Genre& genre)
|
void manager::GenreManager::printGenre(const model::Genre& genre)
|
||||||
{
|
{
|
||||||
std::cout << "genre record" << std::endl;
|
std::cout << "genre record" << std::endl;
|
||||||
|
|||||||
@@ -50,15 +50,24 @@ void manager::SongManager::deleteSong(model::Song& song)
|
|||||||
// is deleted
|
// is deleted
|
||||||
database::SongRepository songRepo(m_bConf);
|
database::SongRepository songRepo(m_bConf);
|
||||||
|
|
||||||
|
if (!songRepo.doesSongExist(song, type::SongFilter::id)) {
|
||||||
|
std::cout << "song does not exist" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
song = songRepo.retrieveRecord(song, type::SongFilter::id);
|
song = songRepo.retrieveRecord(song, type::SongFilter::id);
|
||||||
|
|
||||||
auto paths = manager::DirectoryManager::pathConfigContent(m_bConf);
|
auto paths = manager::DirectoryManager::pathConfigContent(m_bConf);
|
||||||
|
|
||||||
|
auto deleted = songRepo.deleteRecord(song);
|
||||||
|
|
||||||
|
if (!deleted) {
|
||||||
|
std::cout << "song not deleted from databases" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
deleteMisc(song);
|
deleteMisc(song);
|
||||||
|
|
||||||
songRepo.deleteRecord(song);
|
|
||||||
|
|
||||||
fs::remove(song.songPath);
|
fs::remove(song.songPath);
|
||||||
|
|
||||||
manager::DirectoryManager::deleteDirectories(song, paths["root_music_path"].get<std::string>());
|
manager::DirectoryManager::deleteDirectories(song, paths["root_music_path"].get<std::string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,8 +172,11 @@ void manager::SongManager::deleteMisc(const model::Song& song)
|
|||||||
albMgr.deleteAlbum(song);
|
albMgr.deleteAlbum(song);
|
||||||
|
|
||||||
manager::ArtistManager artMgr(m_bConf);
|
manager::ArtistManager artMgr(m_bConf);
|
||||||
|
artMgr.deleteArtist(song);
|
||||||
|
|
||||||
manager::GenreManager gnrMgr(m_bConf);
|
manager::GenreManager gnrMgr(m_bConf);
|
||||||
|
gnrMgr.deleteGenre(song);
|
||||||
|
|
||||||
manager::YearManager yrMgr(m_bConf);
|
manager::YearManager yrMgr(m_bConf);
|
||||||
|
yrMgr.deleteYear(song);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,23 @@ model::Year manager::YearManager::saveYear(const model::Song& song)
|
|||||||
return year;
|
return year;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void manager::YearManager::deleteYear(const model::Song& song)
|
||||||
|
{
|
||||||
|
model::Year year(song);
|
||||||
|
|
||||||
|
database::YearRepository yrRepo(m_bConf);
|
||||||
|
auto yrWSC = yrRepo.retrieveRecordWithSongCount(year, type::YearFilter::id);
|
||||||
|
|
||||||
|
if (yrWSC.second > 1) {
|
||||||
|
std::cout << "year still contain songs related to it";
|
||||||
|
std::cout << ", will not delete" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "safe to delete the year record" << std::endl;
|
||||||
|
yrRepo.deleteYear(year, type::YearFilter::id);
|
||||||
|
}
|
||||||
|
|
||||||
void manager::YearManager::printYear(const model::Year& year)
|
void manager::YearManager::printYear(const model::Year& year)
|
||||||
{
|
{
|
||||||
std::cout << "\nyear record" << std::endl;
|
std::cout << "\nyear record" << std::endl;
|
||||||
|
|||||||
Reference in New Issue
Block a user