Files
ros2-assignments/doc/architecture/Managers/DatabaseManager.md
Vincent W 5e1df5367c Major feat(Documentation): Complete documentation rework
Split documentation into three folders: Architecture, Testing and
Installation.

Rework and expand architecture.md alongside interfaces.md

Split all parts to do with testing from Architecture md's into Test md's

Add parameter to ExamResultGenerator node documentation
2025-10-08 16:30:44 +02:00

192 lines
6.2 KiB
Markdown

# 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<StudentCourse> 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