# DatabaseManager (`assignments::one::DatabaseManager`) ## Overview The `DatabaseManager` class is a PostgreSQL database interface for the ROS2 grade calculator. It handles all database operations including connection management, table creation and data insertion. ## Implementation Details ### Dependencies - **pqxx**: Modern C++ PostgreSQL library for database connectivity - **rclcpp**: ROS2 C++ client library for logging - **ConfigManager**: Configuration manager for database settings ### Key Components #### Constructor ```cpp DatabaseManager(rclcpp::Logger logger) ``` - Initializes the database manager with ROS2 logging - Creates a ConfigManager instance for configuration handling - Automatically calls `init_database()` to establish connection and setup #### Connection Management **`bool connect(const std::string& connection_string)`** > Returns `true` on successful connection, `false` on failure - Establishes connection to PostgreSQL database using connection information from the config TOML - Connection string format: `"host=localhost port=5432 dbname=grades user=postgres password=postgres"` **`bool is_connected() const`** > Returns `true` if connection exists and is open - Check for active database connection status #### Database Initialization **`void init_database()`** - Database setup process - Loads configuration from ConfigManager - Establishes connection using configuration settings - Creates necessary tables and inserts sample data - Error handling for configuration and connection failures **`void create_tables()`** - Creates all required database tables using SQL queries from `SQLQueries.hpp` - Tables created: - `enrollments`: Student course enrollments - `exam_results`: Individual exam scores - `course_results`: Final course grades and statistics - Uses transactions for atomic table creation **`void insert_sample_data()`** - Inserts predefined sample student data ### Data Operations #### Student Course Management **`std::vector queue_pending_combinations()`** > Returns vector of StudentCourse objects for processing queue - Gets all student-course combinations that need exam results generated - Executes complex SQL query to find missing exam results **`bool enroll_student_into_course(const StudentCourse& sc)`** > Returns `true` on successful enrollment, `false` on failure - Enrolls a student into a specific course #### Exam Result Processing **`bool store_exam_result(const std::string& student_name, const std::string& course_name, int grade)`** - Stores individual exam results in the database - Parameters: - `student_name`: Name of the student - `course_name`: Name of the course - `grade`: Exam score (10-100) **`bool store_final_course_result(const StudentCourse& sc, int exam_count, int final_grade)`** - Stores calculated final course results - Parameters: - `sc`: StudentCourse object containing student and course names - `exam_count`: Number of exams taken - `final_grade`: Calculated final grade - Used by grade calculation nodes for final result storage #### Grade Retrieval **`int get_final_course_grade(const StudentCourse& sc)`** > Returns: > - `> 0`: Valid final grade (rounded average) > - `-1`: No exams taken or no results found - Gets final calculated grade for a student-course combination - Performs average calculation with proper rounding - Used by nodes to check if final grading is complete ### Logging - Uses ROS2 logger with `[DBS]` prefix for database operations - Different log levels: - `INFO`: Successful operations, connection status - `ERROR`: SQL errors, connection failures, configuration issues - `WARN`: Non-critical issues, missing configurations ### Usage Examples #### Basic Database Setup ```cpp // Create DatabaseManager with ROS2 logger DatabaseManager db_manager(node->get_logger()); // Check connection status if (db_manager.is_connected()) { // Database ready for operations bool success = db_manager.store_exam_result("Wessel", "ROS2", 85); if (success) { RCLCPP_INFO(logger, "Exam result stored successfully"); } } ``` --- ## Unit Tests Unit tests for `DatabaseManager` are implemented in `src/g2_2025_grade_calculator_pkg/test/DatabaseManager.test.cpp` using Google Test and ROS2 test utilities. The tests are designed to work reliably whether a database connection is available or not, focusing on error handling and method behavior validation. ### Test Cases #### 1. ConstructorTest **Description:** Verifies that DatabaseManager can be created without crashing and proper initialization occurs. - **Test Action:** Create DatabaseManager instance with ROS2 logger - **Expected Result:** Instance created successfully without exceptions #### 2. ConnectionStatusTest **Description:** Tests that the `is_connected()` method returns a valid boolean value. - **Test Action:** Call `is_connected()` method - **Expected Result:** Returns either `true` or `false` (no crashes or invalid states) #### 3. QueuePendingCombinationsTest **Description:** Verifies retrieval of pending student-course combinations that need exam results. - **Test Action:** Call `queue_pending_combinations()` - **Expected Result:** Returns valid vector (empty if no database connection, populated if connected) #### 4. StoreExamResultTest **Description:** Tests exam result storage with graceful handling of connection states. - **Test Action:** - Student: `"TestStudent"` - Course: `"TestCourse"` - Grade: `85` - **Expected Result:** Returns `false` if no connection, `true` if connected and successful #### 5. EnrollStudentTest **Description:** Tests student enrollment into courses. - **Test Action:** - StudentCourse object with test data - **Expected Result:** Returns `false` if no connection, `true` if connected and successful #### 6. GetFinalGradeTest **Description:** Tests final grade retrieval for non-existent student-course combinations. - **Test Action:** - Student: `"NonExistentStudent"` - Course: `"NonExistentCourse"` - **Expected Result:** Returns `-1` (no results found or no connection) #### 7. StoreFinalResultTest **Description:** Tests storing calculated final course results. - **Test Action:** - StudentCourse object - Exam count: `3` - Final grade: `75` - **Expected Result:** Returns `false` if no connection, `true` if connected and successful