#include "sqlite_database.h" #include "sqlite_statement.h" #include #include // std::exchange // Constructor: Opens the SQLite database SQLiteDatabase::SQLiteDatabase(const std::string &db_file) { // WARNING: The database is not blocked if (sqlite3_open(db_file.c_str(), &db_) != SQLITE_OK) { std::cerr << "Failed to open database:" << sqlite3_errmsg(db_) << std::endl; db_ = nullptr; } } // Destructor: Closes the database connection SQLiteDatabase::~SQLiteDatabase() { if (db_) { sqlite3_close(db_); } } SQLiteDatabase::SQLiteDatabase(SQLiteDatabase &&other) noexcept : db_(std::exchange(other.db_, nullptr)) {} SQLiteDatabase &SQLiteDatabase::operator=(SQLiteDatabase &&other) noexcept { if (this != &other) { if (db_) { sqlite3_close(db_); } db_ = std::exchange(other.db_, nullptr); } return *this; } // Helper function for executing non-SELECT queries int SQLiteDatabase::executeNonQuery( const std::string &query, const std::function &bindFunc) { SQLiteStatement stmt(db_, query); if (db_ == nullptr) { throw std::runtime_error("Database is not open"); } if (bindFunc) { bindFunc(stmt); } if (!stmt.execute()) { std::cerr << "Failed to execute query:" << sqlite3_errmsg(db_); } return stmt.changes(); } // Helper function for executing SELECT queries std::vector> SQLiteDatabase::executeSelectQuery( const std::string &query, const std::function &bindFunc) { std::vector> results; SQLiteStatement stmt(db_, query); if (db_ == nullptr) { throw std::runtime_error("Database is not open"); } if (bindFunc) { bindFunc(stmt); } while (stmt.step()) { std::vector row; for (int i = 0, count = stmt.getColumnCount(); i < count; ++i) { row.emplace_back(stmt.getColumnText(i)); } results.push_back(row); } return results; } // INFO: ----- GENRE ----- // Add a new genre bool SQLiteDatabase::addGenre(const NewGenre &genre) { const std::string query = "INSERT INTO genres (genre_name) VALUES (?);"; int changes = executeNonQuery(query, [&genre](SQLiteStatement &stmt) { stmt.bind(1, genre.genre_name); }); return changes > 0; } // Remove a genre by ID bool SQLiteDatabase::removeGenre(int genre_id) { const std::string query = "DELETE FROM genres WHERE genre_id = ?;"; int changes = executeNonQuery( query, [&genre_id](SQLiteStatement &stmt) { stmt.bind(1, genre_id); }); return changes > 0; } // Update an existing genre bool SQLiteDatabase::updateGenre(const Genre &genre) { const std::string query = "UPDATE genres SET genre_name = ? WHERE genre_id = ?;"; int changes = executeNonQuery(query, [&genre](SQLiteStatement &stmt) { stmt.bind(1, genre.genre_name); stmt.bind(2, genre.genre_id); }); return changes > 0; } // Get a genre by ID Genre SQLiteDatabase::getGenre(int genre_id) { const std::string query = "SELECT * FROM genres WHERE genre_id = ?;"; auto result = executeSelectQuery( query, [&genre_id](SQLiteStatement &stmt) { stmt.bind(1, genre_id); }); if (!result.empty()) { auto genre_id = std::stoi(result[0][0]); auto genre_name = result[0][1]; Genre genre(genre_id, genre_name); return genre; } return {}; } // Get all genres std::vector SQLiteDatabase::getAllGenres() { const std::string query = "SELECT * FROM genres;"; auto result = executeSelectQuery(query); std::vector genres; for (const auto &row : result) { genres.push_back({std::stoi(row[0]), row[1]}); } return genres; } // INFO: ----- MOVIE ----- // Add a new movie bool SQLiteDatabase::addMovie(const NewMovie &movie) { const std::string query = "INSERT INTO movies (title, genre_id, duration) VALUES (?, ?, ?);"; int changes = executeNonQuery(query, [&movie](SQLiteStatement &stmt) { stmt.bind(1, movie.title); stmt.bind(2, movie.genre_id); stmt.bind(3, movie.duration); }); return changes > 0; } // Remove a movie by ID bool SQLiteDatabase::removeMovie(int movie_id) { const std::string query = "DELETE FROM movies WHERE movie_id = ?;"; int changes = executeNonQuery( query, [&movie_id](SQLiteStatement &stmt) { stmt.bind(1, movie_id); }); return changes > 0; } // Update an existing movie bool SQLiteDatabase::updateMovie(const Movie &movie) { const std::string query = "UPDATE movies SET title = ?, genre_id = ?, duration = ? WHERE movie_id " "= ?;"; int changes = executeNonQuery(query, [&movie](SQLiteStatement &stmt) { stmt.bind(1, movie.title); stmt.bind(2, movie.genre_id); stmt.bind(3, movie.duration); stmt.bind(4, movie.movie_id); }); return changes > 0; } // Get a movie by ID Movie SQLiteDatabase::getMovie(int movie_id) { const std::string query = "SELECT * FROM movies WHERE movie_id = ?;"; auto result = executeSelectQuery( query, [&movie_id](SQLiteStatement &stmt) { stmt.bind(1, movie_id); }); if (!result.empty()) { auto movie_id = std::stoi(result[0][0]); auto title = result[0][1]; auto genre_id = std::stoi(result[0][2]); auto duration = std::stoi(result[0][3]); Movie movie(movie_id, title, genre_id, duration); return movie; } return {}; } // Get all movies std::vector SQLiteDatabase::getAllMovies() { const std::string query = "SELECT * FROM movies;"; auto result = executeSelectQuery(query); std::vector movies; for (const auto &row : result) { movies.push_back( {std::stoi(row[0]), row[1], std::stoi(row[2]), std::stoi(row[3])}); } return movies; } // INFO: ----- HALL ----- // Add a new hall bool SQLiteDatabase::addHall(const NewHall &hall) { const std::string query = "INSERT INTO halls (hall_name, capacity) VALUES (?, ?);"; int changes = executeNonQuery(query, [&hall](SQLiteStatement &stmt) { stmt.bind(1, hall.hall_name); stmt.bind(2, hall.capacity); }); return changes > 0; } // Remove a hall by ID bool SQLiteDatabase::removeHall(int hall_id) { const std::string query = "DELETE FROM halls WHERE hall_id = ?;"; int changes = executeNonQuery( query, [&hall_id](SQLiteStatement &stmt) { stmt.bind(1, hall_id); }); return changes > 0; } // Update an existing hall bool SQLiteDatabase::updateHall(const Hall &hall) { const std::string query = "UPDATE halls SET hall_name = ?, capacity = ? WHERE hall_id = ?;"; int changes = executeNonQuery(query, [&hall](SQLiteStatement &stmt) { stmt.bind(1, hall.hall_name); stmt.bind(2, hall.capacity); stmt.bind(3, hall.hall_id); }); return changes > 0; } // Get a hall by ID Hall SQLiteDatabase::getHall(int hall_id) { const std::string query = "SELECT * FROM halls WHERE hall_id = ?;"; auto result = executeSelectQuery( query, [&hall_id](SQLiteStatement &stmt) { stmt.bind(1, hall_id); }); if (!result.empty()) { auto hall_id = std::stoi(result[0][0]); auto hall_name = result[0][1]; auto capacity = std::stoi(result[0][2]); Hall hall(hall_id, hall_name, capacity); return hall; } return {}; } // Get all halls std::vector SQLiteDatabase::getAllHalls() { const std::string query = "SELECT * FROM halls;"; auto result = executeSelectQuery(query); std::vector halls; for (const auto &row : result) { halls.push_back({std::stoi(row[0]), row[1], std::stoi(row[2])}); } return halls; } // INFO: ----- SESSION ----- // Add a new session bool SQLiteDatabase::addSession(const NewSession &session) { const std::string query = "INSERT INTO sessions (movie_id, hall_id, " "begin_at, ticket_price) VALUES (?, ?, ?, ?);"; int changes = executeNonQuery(query, [&session](SQLiteStatement &stmt) { stmt.bind(1, session.movie_id); stmt.bind(2, session.hall_id); stmt.bind(3, session.begin_at); stmt.bind(4, session.ticket_price); }); return changes > 0; } // Remove a session by ID bool SQLiteDatabase::removeSession(int session_id) { const std::string query = "DELETE FROM sessions WHERE session_id = ?;"; int changes = executeNonQuery(query, [&session_id](SQLiteStatement &stmt) { stmt.bind(1, session_id); }); return changes > 0; } // Update an existing session bool SQLiteDatabase::updateSession(const Session &session) { const std::string query = "UPDATE sessions SET movie_id = ?, hall_id = ?, " "begin_at = ?, ticket_price = ? WHERE " "session_id = ?;"; int changes = executeNonQuery(query, [&session](SQLiteStatement &stmt) { stmt.bind(1, session.movie_id); stmt.bind(2, session.hall_id); stmt.bind(3, session.begin_at); stmt.bind(4, session.ticket_price); stmt.bind(5, session.session_id); }); return changes > 0; } // Get a session by ID Session SQLiteDatabase::getSession(int session_id) { const std::string query = "SELECT * FROM sessions WHERE session_id = ?;"; auto result = executeSelectQuery(query, [&session_id](SQLiteStatement &stmt) { stmt.bind(1, session_id); }); if (!result.empty()) { auto session_id = std::stoi(result[0][0]); auto movie_id = std::stoi(result[0][1]); auto hall_id = std::stoi(result[0][2]); auto begin_at = result[0][3]; auto ticket_price = std::stod(result[0][4]); Session session(session_id, movie_id, hall_id, begin_at, ticket_price); return session; } return {}; } // Get all sessions std::vector SQLiteDatabase::getAllSessions() { const std::string query = "SELECT * FROM sessions;"; auto result = executeSelectQuery(query); std::vector sessions; for (const auto &row : result) { sessions.push_back({std::stoi(row[0]), std::stoi(row[1]), std::stoi(row[2]), row[3], std::stod(row[4])}); } return sessions; } // INFO: ----- TICKET ----- // Add a new ticket bool SQLiteDatabase::addTicket(const NewTicket &ticket) { const std::string query = "INSERT INTO tickets (session_id, seat_number, " "sold_at) VALUES (?, ?, ?);"; int changes = executeNonQuery(query, [&ticket](SQLiteStatement &stmt) { stmt.bind(1, ticket.session_id); stmt.bind(2, ticket.seat_number); stmt.bind(3, ticket.sold_at); }); return changes > 0; } // Remove a ticket by ID bool SQLiteDatabase::removeTicket(int ticket_id) { const std::string query = "DELETE FROM tickets WHERE ticket_id = ?;"; int changes = executeNonQuery( query, [&ticket_id](SQLiteStatement &stmt) { stmt.bind(1, ticket_id); }); return changes > 0; } // Update an existing ticket bool SQLiteDatabase::updateTicket(const Ticket &ticket) { const std::string query = "UPDATE tickets SET session_id = ?, seat_number = " "?, sold_at = ? WHERE ticket_id = ?;"; int changes = executeNonQuery(query, [&ticket](SQLiteStatement &stmt) { stmt.bind(1, ticket.session_id); stmt.bind(2, ticket.seat_number); stmt.bind(3, ticket.sold_at); stmt.bind(4, ticket.ticket_id); }); return changes > 0; } // Get a ticket by ID Ticket SQLiteDatabase::getTicket(int ticket_id) { const std::string query = "SELECT * FROM tickets WHERE ticket_id = ?;"; auto result = executeSelectQuery( query, [&ticket_id](SQLiteStatement &stmt) { stmt.bind(1, ticket_id); }); if (!result.empty()) { auto ticket_id = std::stoi(result[0][0]); auto session_id = std::stoi(result[0][1]); auto seat_number = std::stoi(result[0][2]); auto sold_at = result[0][3]; Ticket ticket(ticket_id, session_id, seat_number, sold_at); return ticket; } return {}; } // Get all tickets std::vector SQLiteDatabase::getAllTickets() { const std::string query = "SELECT * FROM tickets;"; auto result = executeSelectQuery(query); std::vector tickets; for (const auto &row : result) { tickets.push_back( {std::stoi(row[0]), std::stoi(row[1]), std::stoi(row[2]), row[3]}); } return tickets; } // INFO: ----- REFUND ----- // Add a new refund bool SQLiteDatabase::addRefund(const NewRefund &refund) { const std::string query = "INSERT INTO refunds (ticket_id, refund_at, refund_amount) " "VALUES (?, ?, ?);"; int changes = executeNonQuery(query, [&refund](SQLiteStatement &stmt) { stmt.bind(1, refund.ticket_id); stmt.bind(2, refund.refund_at); stmt.bind(3, refund.refund_amount); }); return changes > 0; } // Remove a refund by ID bool SQLiteDatabase::removeRefund(int refund_id) { const std::string query = "DELETE FROM refunds WHERE refund_id = ?;"; int changes = executeNonQuery( query, [&refund_id](SQLiteStatement &stmt) { stmt.bind(1, refund_id); }); return changes > 0; } // Update an existing refund bool SQLiteDatabase::updateRefund(const Refund &refund) { const std::string query = "UPDATE refunds SET ticket_id = ?, refund_at = ?, refund_amount = ? " "WHERE refund_id = ?;"; int changes = executeNonQuery(query, [&refund](SQLiteStatement &stmt) { stmt.bind(1, refund.ticket_id); stmt.bind(2, refund.refund_at); stmt.bind(3, refund.refund_amount); stmt.bind(4, refund.refund_id); }); return changes > 0; } // Get a refund by ID Refund SQLiteDatabase::getRefund(int refund_id) { const std::string query = "SELECT * FROM refunds WHERE refund_id = ?;"; auto result = executeSelectQuery( query, [&refund_id](SQLiteStatement &stmt) { stmt.bind(1, refund_id); }); if (!result.empty()) { auto refund_id = std::stoi(result[0][0]); auto ticket_id = std::stoi(result[0][1]); auto refund_at = result[0][2]; auto refund_amount = std::stod(result[0][3]); Refund refund(refund_id, ticket_id, refund_at, refund_amount); return refund; } return {}; } // Get all refunds std::vector SQLiteDatabase::getAllRefunds() { const std::string query = "SELECT * FROM refunds;"; auto result = executeSelectQuery(query); std::vector refunds; for (const auto &row : result) { refunds.push_back( {std::stoi(row[0]), std::stoi(row[1]), row[2], std::stod(row[3])}); } return refunds; }