Initial commit

This commit is contained in:
user
2026-07-12 14:34:52 +04:00
commit 3abf6bd9c2
557 changed files with 68706 additions and 0 deletions
@@ -0,0 +1,188 @@
#ifndef DATABASE_INTERFACE_H
#define DATABASE_INTERFACE_H
#include <string>
#include <vector>
// Data structures representing the entities
struct Genre {
int genre_id;
std::string genre_name;
Genre() = default;
Genre(int id, const std::string &name) : genre_id(id), genre_name(name) {}
};
struct Movie {
int movie_id;
std::string title;
int genre_id;
int duration; // Duration in minutes
Movie() = default;
Movie(int id, const std::string &title, int genre_id, int duration)
: movie_id(id), title(title), genre_id(genre_id), duration(duration) {}
};
struct Hall {
int hall_id;
std::string hall_name;
int capacity;
Hall() = default;
Hall(int id, const std::string &name, int capacity)
: hall_id(id), hall_name(name), capacity(capacity) {}
};
struct Session {
int session_id;
int movie_id;
int hall_id;
std::string begin_at; // Use appropriate date-time type if needed
double ticket_price;
Session() = default;
Session(int id, int movie_id, int hall_id, const std::string &begin_at,
double price)
: session_id(id), movie_id(movie_id), hall_id(hall_id),
begin_at(begin_at), ticket_price(price) {}
};
struct Ticket {
int ticket_id;
int session_id;
int seat_number;
std::string sold_at; // Use appropriate date-time type if needed
Ticket() = default;
Ticket(int id, int session_id, int seat_number, const std::string &time)
: ticket_id(id), session_id(session_id), seat_number(seat_number),
sold_at(time) {}
};
struct Refund {
int refund_id;
int ticket_id;
std::string refund_at; // Use appropriate date-time type if needed
double refund_amount;
Refund() = default;
Refund(int id, int ticket_id, const std::string &time, double amount)
: refund_id(id), ticket_id(ticket_id), refund_at(time),
refund_amount(amount) {}
};
// Structures for adding new records (without IDs)
struct NewGenre {
std::string genre_name;
NewGenre() = default;
NewGenre(const std::string &name) : genre_name(name) {}
};
struct NewMovie {
std::string title;
int genre_id;
int duration; // Duration in minutes
NewMovie() = default;
NewMovie(const std::string &title, int genre_id, int duration)
: title(title), genre_id(genre_id), duration(duration) {}
};
struct NewHall {
std::string hall_name;
int capacity;
NewHall() = default;
NewHall(const std::string &name, int capacity)
: hall_name(name), capacity(capacity) {}
};
struct NewSession {
int movie_id;
int hall_id;
std::string begin_at; // Use appropriate date-time type if needed
double ticket_price;
NewSession() = default;
NewSession(int movie_id, int hall_id, const std::string &begin_at,
double price)
: movie_id(movie_id), hall_id(hall_id), begin_at(begin_at),
ticket_price(price) {}
};
struct NewTicket {
int session_id;
int seat_number;
std::string sold_at; // Optional, can default to CURRENT_TIMESTAMP
NewTicket() = default;
NewTicket(int session_id, int seat_number, const std::string &time)
: session_id(session_id), seat_number(seat_number), sold_at(time) {}
};
struct NewRefund {
int ticket_id;
std::string refund_at; // Optional, can default to CURRENT_TIMESTAMP
double refund_amount;
NewRefund() = default;
NewRefund(int ticket_id, const std::string &time, double amount)
: ticket_id(ticket_id), refund_at(time), refund_amount(amount) {}
};
// Abstract interface for database operations
class DatabaseInterface {
public:
virtual ~DatabaseInterface() {}
// Verification of the database availability
virtual bool isDatabaseAvailable() = 0;
// Genre operations
virtual bool addGenre(const NewGenre &genre) = 0;
virtual bool removeGenre(int genre_id) = 0;
virtual bool updateGenre(const Genre &genre) = 0;
virtual Genre getGenre(int genre_id) = 0;
virtual std::vector<Genre> getAllGenres() = 0;
// Movie operations
virtual bool addMovie(const NewMovie &movie) = 0;
virtual bool removeMovie(int movie_id) = 0;
virtual bool updateMovie(const Movie &movie) = 0;
virtual Movie getMovie(int movie_id) = 0;
virtual std::vector<Movie> getAllMovies() = 0;
// Hall operations
virtual bool addHall(const NewHall &hall) = 0;
virtual bool removeHall(int hall_id) = 0;
virtual bool updateHall(const Hall &hall) = 0;
virtual Hall getHall(int hall_id) = 0;
virtual std::vector<Hall> getAllHalls() = 0;
// Session operations
virtual bool addSession(const NewSession &session) = 0;
virtual bool removeSession(int session_id) = 0;
virtual bool updateSession(const Session &session) = 0;
virtual Session getSession(int session_id) = 0;
virtual std::vector<Session> getAllSessions() = 0;
// Ticket operations
virtual bool addTicket(const NewTicket &ticket) = 0;
virtual bool removeTicket(int ticket_id) = 0;
virtual bool updateTicket(const Ticket &ticket) = 0;
virtual Ticket getTicket(int ticket_id) = 0;
virtual std::vector<Ticket> getAllTickets() = 0;
// Refund operations
virtual bool addRefund(const NewRefund &refund) = 0;
virtual bool removeRefund(int refund_id) = 0;
virtual bool updateRefund(const Refund &refund) = 0;
virtual Refund getRefund(int refund_id) = 0;
virtual std::vector<Refund> getAllRefunds() = 0;
};
#endif // DATABASE_INTERFACE_H
@@ -0,0 +1,23 @@
#include "file_reader.h"
#include <fstream>
#include <iostream>
#include <sstream>
// Read a SQL file
bool FileReader::read(const std::string &sqlFilePath, std::string &sql) {
// Try read the SQL file
std::ifstream file(sqlFilePath);
if (!file.is_open()) {
std::cerr << "Error opening file:" << sqlFilePath << std::endl;
return false;
}
std::stringstream buffer;
buffer << file.rdbuf();
sql = buffer.str();
file.close();
return true;
}
+12
View File
@@ -0,0 +1,12 @@
#ifndef FILE_READER_H
#define FILE_READER_H
#include "file_reader_interface.h"
#include <string>
class FileReader : virtual public FileReaderInterface {
public:
bool read(const std::string &sqlFilePath, std::string &sql) override;
};
#endif // FILE_READER_H
@@ -0,0 +1,12 @@
#ifndef FILE_READER_INTERFACE_H
#define FILE_READER_INTERFACE_H
#include <string>
class FileReaderInterface {
public:
virtual ~FileReaderInterface() = default;
virtual bool read(const std::string &sqlFilePath, std::string &data) = 0;
};
#endif // !FILE_READER_INTERFACE
@@ -0,0 +1,13 @@
#ifndef SQL_FILE_EXECUTOR_INTERFASE_H
#define SQL_FILE_EXECUTOR_INTERFASE_H
#include "file_reader_interface.h"
#include <string>
class SQLFileExecutorInterface : virtual public FileReaderInterface {
public:
virtual ~SQLFileExecutorInterface() {}
virtual void executeSQLFile(const std::string &sqlFilePath) = 0;
};
#endif // !SQL_FILE_EXECUTOR_INTERF
@@ -0,0 +1,487 @@
#include "sqlite_database.h"
#include "sqlite_statement.h"
#include <iostream>
#include <utility> // 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<void(SQLiteStatement &)> &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<std::vector<std::string>> SQLiteDatabase::executeSelectQuery(
const std::string &query,
const std::function<void(SQLiteStatement &)> &bindFunc) {
std::vector<std::vector<std::string>> 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<std::string> 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<Genre> SQLiteDatabase::getAllGenres() {
const std::string query = "SELECT * FROM genres;";
auto result = executeSelectQuery(query);
std::vector<Genre> 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<Movie> SQLiteDatabase::getAllMovies() {
const std::string query = "SELECT * FROM movies;";
auto result = executeSelectQuery(query);
std::vector<Movie> 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<Hall> SQLiteDatabase::getAllHalls() {
const std::string query = "SELECT * FROM halls;";
auto result = executeSelectQuery(query);
std::vector<Hall> 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<Session> SQLiteDatabase::getAllSessions() {
const std::string query = "SELECT * FROM sessions;";
auto result = executeSelectQuery(query);
std::vector<Session> 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<Ticket> SQLiteDatabase::getAllTickets() {
const std::string query = "SELECT * FROM tickets;";
auto result = executeSelectQuery(query);
std::vector<Ticket> 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<Refund> SQLiteDatabase::getAllRefunds() {
const std::string query = "SELECT * FROM refunds;";
auto result = executeSelectQuery(query);
std::vector<Refund> 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;
}
@@ -0,0 +1,85 @@
#ifndef SQLITE_DATABASE_H
#define SQLITE_DATABASE_H
#include "database_interface.h"
#include <functional>
#include <sqlite3.h>
// Forward declaration
class SQLiteStatement;
// SQLite implementation of the DatabaseInterface
class SQLiteDatabase : public DatabaseInterface {
private:
sqlite3 *db_; // Pointer to SQLite database connection
// Helper functions
int executeNonQuery(
const std::string &query,
const std::function<void(SQLiteStatement &)> &bindFunc = nullptr);
std::vector<std::vector<std::string>> executeSelectQuery(
const std::string &query,
const std::function<void(SQLiteStatement &)> &bindFunc = nullptr);
friend class SQLiteDatabaseForeignKeyTest;
friend class SQLiteDatabaseCRUDTest;
friend class SQLiteDatabaseTriggerTest;
public:
// Verification of the database availability
bool isDatabaseAvailable() override { return db_ != nullptr; }
public:
SQLiteDatabase(const std::string &db_file);
~SQLiteDatabase();
SQLiteDatabase(const SQLiteDatabase &) = delete;
SQLiteDatabase &operator=(const SQLiteDatabase &) = delete;
SQLiteDatabase(SQLiteDatabase &&) noexcept;
SQLiteDatabase &operator=(SQLiteDatabase &&) noexcept;
// Genre operations
bool addGenre(const NewGenre &genre) override;
bool removeGenre(int genre_id) override;
bool updateGenre(const Genre &genre) override;
Genre getGenre(int genre_id) override;
std::vector<Genre> getAllGenres() override;
// Movie operations
bool addMovie(const NewMovie &movie) override;
bool removeMovie(int movie_id) override;
bool updateMovie(const Movie &movie) override;
Movie getMovie(int movie_id) override;
std::vector<Movie> getAllMovies() override;
// Hall operations
bool addHall(const NewHall &hall) override;
bool removeHall(int hall_id) override;
bool updateHall(const Hall &hall) override;
Hall getHall(int hall_id) override;
std::vector<Hall> getAllHalls() override;
// Session operations
bool addSession(const NewSession &session) override;
bool removeSession(int session_id) override;
bool updateSession(const Session &session) override;
Session getSession(int session_id) override;
std::vector<Session> getAllSessions() override;
// Ticket operations
bool addTicket(const NewTicket &ticket) override;
bool removeTicket(int ticket_id) override;
bool updateTicket(const Ticket &ticket) override;
Ticket getTicket(int ticket_id) override;
std::vector<Ticket> getAllTickets() override;
// Refund operations
bool addRefund(const NewRefund &refund) override;
bool removeRefund(int refund_id) override;
bool updateRefund(const Refund &refund) override;
Refund getRefund(int refund_id) override;
std::vector<Refund> getAllRefunds() override;
};
#endif // SQLITE_DATABASE_H
@@ -0,0 +1,37 @@
#include "sqlite_file_executor.h"
#include "sqlite_statement.h"
#include <iostream>
SQLiteFileExecutor::SQLiteFileExecutor(const std::string &dbPath) {
// WARNING: The database is not blocked
if (sqlite3_open(dbPath.c_str(), &db_) != SQLITE_OK) {
std::cerr << "Failed to open database:" << sqlite3_errmsg(db_) << std::endl;
db_ = nullptr;
}
}
SQLiteFileExecutor::~SQLiteFileExecutor() {
if (db_) {
sqlite3_close(db_);
}
}
// Execute a SQL file
void SQLiteFileExecutor::executeSQLFile(const std::string &sqlFilePath) {
if (db_ == nullptr) {
throw std::runtime_error("Database is not open");
}
std::string sqlContent;
if (!read(sqlFilePath, sqlContent)) {
throw std::runtime_error("Failed to read SQL file: " + sqlFilePath);
}
char *errorMessage = nullptr;
if (sqlite3_exec(db_, sqlContent.c_str(), nullptr, nullptr, &errorMessage) !=
SQLITE_OK) {
std::cerr << "Error executing SQL:" << errorMessage << std::endl;
sqlite3_free(errorMessage);
}
}
@@ -0,0 +1,22 @@
#ifndef SQLITE_FILE_EXECUTOR_INTERFASE_H
#define SQLITE_FILE_EXECUTOR_INTERFASE_H
#include "sql_file_executor_interfase.h"
#include "file_reader.h"
#include "sqlite_statement.h"
#include <string>
class SQLiteFileExecutor : public SQLFileExecutorInterface, public FileReader {
private:
sqlite3 *db_;
public:
SQLiteFileExecutor(const std::string &dbPath);
~SQLiteFileExecutor() override;
public:
void executeSQLFile(const std::string &sqlFilePath) override;
};
#endif // !SQLITE_FILE_EXECUTOR_INTERFASE_H
@@ -0,0 +1,90 @@
#include "sqlite_statement.h"
#include <iostream>
// Constructor: Prepares the SQL statement
SQLiteStatement::SQLiteStatement(sqlite3 *db, const std::string &query)
: db_(db), stmt_(nullptr) {
if (db == nullptr) {
throw std::invalid_argument("Database connection is null");
}
if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt_, nullptr) != SQLITE_OK) {
std::cerr << "Error preparing SQL statement:" << "\"" + query + "\""
<< std::endl;
std::cerr << "Error message:" << sqlite3_errmsg(db) << std::endl;
if (stmt_) {
sqlite3_finalize(stmt_);
}
throw std::runtime_error("Failed to prepare SQLite statement: " + query);
}
}
// Destructor: Finalizes the statement
SQLiteStatement::~SQLiteStatement() { finalize(); }
// Bind integer value
bool SQLiteStatement::bind(int index, int value) {
return sqlite3_bind_int(stmt_, index, value) == SQLITE_OK;
}
// Bind double value
bool SQLiteStatement::bind(int index, double value) {
return sqlite3_bind_double(stmt_, index, value) == SQLITE_OK;
}
// Bind text value
bool SQLiteStatement::bind(int index, const std::string &value) {
return sqlite3_bind_text(stmt_, index, value.c_str(), -1, SQLITE_TRANSIENT) ==
SQLITE_OK;
}
// Bind NULL value
bool SQLiteStatement::bindNull(int index) {
return sqlite3_bind_null(stmt_, index) == SQLITE_OK;
}
// Run the statement
// step() returns true if there are more rows
bool SQLiteStatement::execute() { return step() == false; }
// Execute the statement
bool SQLiteStatement::step() {
int rc = sqlite3_step(stmt_);
if (rc == SQLITE_ROW) {
return true;
}
if (rc == SQLITE_DONE) {
return false;
}
std::cerr << "Failed to step:" << sqlite3_errmsg(db_) << std::endl;
return false;
}
// Get the number of rows affected
int SQLiteStatement::changes() { return sqlite3_changes(db_); }
// Reset the statement for re-use
void SQLiteStatement::reset() { sqlite3_reset(stmt_); }
// Finalize and clean up the statement
void SQLiteStatement::finalize() {
if (stmt_) {
sqlite3_finalize(stmt_);
stmt_ = nullptr;
}
}
// Adapter for sqlite3_column_count
int SQLiteStatement::getColumnCount() const {
return sqlite3_column_count(stmt_);
}
// Adapter for sqlite3_column_text
std::string SQLiteStatement::getColumnText(int column_index) const {
const unsigned char *text = sqlite3_column_text(stmt_, column_index);
return text ? reinterpret_cast<const char *>(text) : "";
}
@@ -0,0 +1,33 @@
#ifndef SQLITE_STATEMENT_H
#define SQLITE_STATEMENT_H
#include <sqlite3.h>
#include <string>
class SQLiteStatement {
private:
sqlite3 *db_;
sqlite3_stmt *stmt_; // Prepared statement
public:
SQLiteStatement(sqlite3 *db, const std::string &query);
~SQLiteStatement();
bool bind(int index, int value);
bool bind(int index, double value);
bool bind(int index, const std::string &value);
bool bindNull(int index);
bool execute();
bool step();
int changes();
void finalize();
void reset();
int getColumnCount() const;
std::string getColumnText(int column_index) const;
};
#endif // SQLITE_STATEMENT_H