Search Query Service
Relevant source files
The following files were used as context for generating this wiki page:
The Search Query Service is a core component of the SSA Consulta Rapida Cpp application, responsible for orchestrating the retrieval and filtering of SSA (Service Solicitation/Solicitação de Serviço) records. It acts as a middle layer between the presentation logic and the persistence infrastructure, ensuring that domain-specific query requirements are translated into executable repository actions.
Architecturally, this service resides in the src/query directory and adheres to the project's strict separation of concerns: it is independent of Qt and direct database access, relying on abstraction ports to interact with the underlying SQLite storage.
Sources: src/query/SsaQueryService.h:1-24, AGENTS.md:14-22
Core Architecture and Data Flow
The service follows a layered approach where high-level search requests are parsed, transformed into SQL-compatible structures, and finally executed.
Service Orchestration
The SsaQueryService class provides a clean API for the MainViewModel to perform searches, fetch specific record details, and retrieve distinct values for UI filters. It encapsulates a shared pointer to an ISsaRepository, which handles the actual data fetching.
This diagram illustrates the flow of a search request from the presentation layer through the query service to the repository.
Sources: src/query/SsaQueryService.cpp:11-28, src/presentation/MainViewModel.cpp:253-270
Query Compilation Logic
The SqlQueryBuilder and SearchParser are the primary engines behind the service. The parser breaks down raw user input into structured FilterTerm objects, while the builder constructs complex SQL statements with bound parameters to prevent SQL injection.
| Component | Responsibility | Relevant Files |
|---|---|---|
| SsaQueryService | High-level API for searching and record retrieval. | SsaQueryService.cpp |
| SearchParser | Parses string inputs into FilterTerm vectors using specific syntax (e.g., ^, !, =). | SearchParser.cpp |
| SqlQueryBuilder | Compiles SsaPageRequest into SqlQuery objects containing SQL and parameter bindings. | SqlQueryBuilder.cpp |
Sources: src/query/SearchParser.h:16-21, src/query/SqlQueryBuilder.h:26-33
Search Syntax and Parsing
The SearchParser implements a specialized syntax for filtering records. It splits input by commas (treating them as implicit AND conditions) and identifies prefixes to determine the matching mode.
Supported Match Modes
The following table describes how the parser interprets user input:
| Prefix/Suffix | Match Mode | SQL Equivalent | Description |
|---|---|---|---|
! or - | Negation | NOT LIKE / NOT IN | Excludes the term from results. |
^ | StartsWith | LIKE 'term%' | Matches records starting with the term. |
$ | EndsWith | LIKE '%term' | Matches records ending with the term. |
= | Equals | = ? | Performs an exact match. |
~ | Regex | REGEXP ? | Uses regular expression matching. |
| (None) | Contains | LIKE '%term%' | Default behavior: matches term anywhere. |
Sources: src/query/SearchParser.cpp:28-54, src/query/SqlQueryBuilder.cpp:45-66
Pattern Transformation
When building the query, search terms are normalized to uppercase to ensure case-insensitive matching in the SQLite database.
// Example of pattern generation in SqlQueryBuilder.cpp
std::string patternFor(const SearchTerm& term) {
std::string text = term.text;
std::ranges::transform(text, text.begin(), [](https://github.com/mauriciomenon/SsaConsultaRapidacpp/blob/98767361829d2bed8d6898d020d925d04e615bb2/unsigned%20char%20ch) {
return static_cast<char>(std::toupper(ch));
});
if (term.mode == domain::MatchMode::StartsWith) return text + "%";
// ...
}
Sources: src/query/SqlQueryBuilder.cpp:33-47
SQL Construction Process
The SqlQueryBuilder is responsible for generating the final SQL strings and the corresponding parameter bindings. This process involves several specialized steps:
- Column Selection: Determines which columns to include in the
SELECTclause based on theSsaPageRequest::visibleColumns. - Where Clause Building: Combines general search terms, column-specific filters, "Quick Sector" filters, and the default exclusion of specific statuses (
SCA,SES,STE). - Ordering: Applies sorting logic, including a special "status last" rule for specific columns like
numero_ssa. - Pagination: Appends
LIMITandOFFSETclauses using calculated values from the requested page size and index.
Query Structure Flow
The following sequence diagram shows how the builder processes a request:
Parameter Binding
To ensure security and performance, values are never concatenated directly into the SQL string. Instead, they are added to a bindings vector.
// Sample from SqlQueryBuilder.cpp showing parameter binding for pagination
SqlQuery page{select.str(), whereBindings};
page.bindings.push_back(std::to_string(request.pageSize));
page.bindings.push_back(std::to_string(request.pageIndex * request.pageSize));
Sources: src/query/SqlQueryBuilder.cpp:154-157
Domain Data Structures
The service relies on structures defined in src/domain/SsaTypes.h to maintain a strict contract between layers.
SsaPageRequest
Encapsulates all parameters for a search operation:
searchText: The raw string from the search bar.columnFilters: A map of column keys to filter strings.pageIndex/pageSize: Controls pagination.sort: ASortSpecstruct defining column key and direction.excludeScaSesSte: Boolean flag to filter out specific administrative statuses.
Sources: src/domain/SsaTypes.h:132-141
SsaPageResult
The output of a search operation:
rows: A vector ofSsaRecordobjects containing the data.totalRows: The total count of records matching the filter (ignoring pagination).pageIndex/pageSize: Metadata about the returned slice.
Sources: src/domain/SsaTypes.h:143-148
Summary
The Search Query Service provides a robust, testable, and secure mechanism for querying SSA data. By separating the parsing logic (SearchParser), the SQL generation (SqlQueryBuilder), and the service orchestration (SsaQueryService), the system maintains a clear boundary between domain rules and technical implementation details like SQLite syntax. This architecture allows for advanced features like regex searching and complex status-based exclusions while ensuring the UI remains responsive through paginated data retrieval.