ores.cpp.repository.repository_header
Repository declarations with custom-member paste points. repository profile. Database access layer using Qt SQL parameterised queries, tracking `valid_from`/`valid_to`.
See the Template variable reference for the complete list of available variables and their semantics.
Template
The full template source. Edit here and re-tangle with
compass build --direct tangle_codegen_templates to regenerate
library/templates/cpp_domain_type_repository.hpp.mustache.
{{! GENERATED FILE — tangled from projects/ores.codegen/library/templates/ores.cpp.repository.repository_header.org. Edit the org source. }}
{{{cpp_license}}}
{{#domain_entity}}
#ifndef ORES_{{component_core_upper}}_REPOSITORY_{{entity_singular_upper}}_REPOSITORY_HPP
#define ORES_{{component_core_upper}}_REPOSITORY_{{entity_singular_upper}}_REPOSITORY_HPP
#include <chrono>
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
#include <sqlgen/postgres.hpp>
#include "ores.logging/make_logger.hpp"
#include "ores.database/domain/context.hpp"
#include "ores.{{component_include}}/domain/{{entity_singular}}.hpp"
#include "ores.{{component_core}}/export.hpp"
{{#has_parent_id}}
#include "ores.utility/domain/hierarchy.hpp"
#include <boost/uuid/uuid.hpp>
{{/has_parent_id}}
namespace ores::{{component}}::repository {
/**
* @brief Reads and writes {{entity_plural_words}} to data storage.
*/
class ORES_{{component_core_upper}}_EXPORT {{entity_singular}}_repository {
private:
inline static std::string_view logger_name =
"ores.{{component}}.repository.{{entity_singular}}_repository";
[[nodiscard]] static auto& lg() {
using namespace ores::logging;
static auto instance = make_logger(logger_name);
return instance;
}
public:
using context = ores::database::context;
/**
* @brief Returns the SQL created by sqlgen to construct the table.
*/
std::string sql();
/**
* @brief Writes {{entity_plural_words}} to database.
*/
/**@{*/
void write(context ctx, const domain::{{entity_singular}}& v);
void write(context ctx, const std::vector<domain::{{entity_singular}}>& v);
/**@}*/
/**
* @brief Reads latest {{entity_plural_words}}, possibly filtered by primary key.
*/
/**@{*/
std::vector<domain::{{entity_singular}}> read_latest(context ctx);
std::vector<domain::{{entity_singular}}>
read_latest(context ctx, {{{primary_key.params}}});
{{#has_batch_read}}
std::vector<domain::{{entity_singular}}>
read_latest(context ctx, {{{primary_key.batch_params}}});
{{/has_batch_read}}
/**@}*/
{{#service_find_by_code}}
{{#parent_column}}
/**
* @brief Reads latest {{entity_plural_words}} filtered by {{parent_column}} and {{column}}.
*/
std::vector<domain::{{entity_singular}}>
read_latest_by_code(context ctx, const std::string& {{parent_column}}, const std::string& {{column}});
{{/parent_column}}
{{^parent_column}}
/**
* @brief Reads latest {{entity_plural_words}} filtered by {{column}}.
*/
std::vector<domain::{{entity_singular}}>
read_latest_by_code(context ctx, const std::string& {{column}});
{{/parent_column}}
{{/service_find_by_code}}
{{#has_as_of_lookup}}
/**
* @brief Reads {{entity_plural_words}} as they stood at a specific
* timepoint — valid_from <= as_of < valid_to — possibly filtered by
* {{primary_key.column}}. Distinct from read_at_version (a specific
* version number) and from a parent/child *_as_of query (a validity
* window overlap): this resolves what this entity's own row meant at
* a single instant in time.
*/
/**@{*/
std::vector<domain::{{entity_singular}}> read_at_timepoint(context ctx, const std::string& as_of);
std::vector<domain::{{entity_singular}}>
read_at_timepoint(context ctx, const std::string& as_of, const std::string& {{primary_key.column}});
/**@}*/
{{/has_as_of_lookup}}
/**
* @brief Reads all {{entity_plural_words}}, possibly filtered by primary key.
*/
std::vector<domain::{{entity_singular}}>
read_all(context ctx, {{{primary_key.params}}});
{{#has_audit_columns}}
/**
* @brief Reads a single {{entity_singular_words}} as it stood at a specific
* version — the version's own [valid_from, valid_to) window is returned
* verbatim, so the caller can compose child entities "as of" the same
* window. See the "Temporal composite entity versioning" architecture
* doc.
* @param ctx Repository context with database connection
* @param version The version to fetch
*/
std::optional<domain::{{entity_singular}}>
read_at_version(context ctx, {{{primary_key.params}}}, std::uint32_t version);
{{/has_audit_columns}}
{{#foreign_keys}}
{{#list_by}}
/**
* @brief Reads latest {{entity_plural_words}} filtered by {{column}}, with pagination.
* @param ctx Repository context with database connection
* @param {{column}} The {{column}} to filter by
* @param offset Number of records to skip
* @param limit Maximum number of records to return
*/
std::vector<domain::{{entity_singular}}>
read_latest_by_{{column}}(context ctx, const std::string& {{column}},
std::uint32_t offset, std::uint32_t limit);
/**
* @brief Gets the total count of active {{entity_plural_words}} filtered by {{column}}.
*/
std::uint32_t get_total_{{entity_singular_short}}_count_by_{{column}}(context ctx,
const std::string& {{column}});
{{/list_by}}
{{#list_by_as_of}}
/**
* @brief Reads {{entity_plural_words}} filtered by {{column}} that were live at
* any point during [valid_from_bound, valid_to_bound) — i.e. the set of
* {{entity_plural_words}} that compose a parent entity's state as of one of
* its own historical versions. See the "Temporal composite entity
* versioning" architecture doc.
* @param ctx Repository context with database connection
* @param {{column}} The {{column}} to filter by
* @param valid_from_bound The parent version's own valid_from
* @param valid_to_bound The parent version's own valid_to
*/
std::vector<domain::{{entity_singular}}>
read_by_{{column}}_as_of(context ctx, const std::string& {{column}},
std::chrono::system_clock::time_point valid_from_bound,
std::chrono::system_clock::time_point valid_to_bound);
{{/list_by_as_of}}
{{/foreign_keys}}
/**
* @brief Reads latest {{entity_plural_words}} with pagination support.
* @param ctx Repository context with database connection
* @param offset Number of records to skip
* @param limit Maximum number of records to return
*/
std::vector<domain::{{entity_singular}}>
read_latest(context ctx, std::uint32_t offset, std::uint32_t limit);
/**
* @brief Gets the total count of active {{entity_plural_words}}.
* @param ctx Repository context with database connection
* @return Total number of active {{entity_plural_words}}
*/
std::uint32_t get_total_{{entity_singular_short}}_count(context ctx);
/**
* @brief Deletes a {{entity_singular_words}} by closing its temporal validity.
*/
void remove(context ctx, {{{primary_key.params}}});
/**
* @brief Deletes {{entity_plural_words}} by closing their temporal validity.
*/
void remove(context ctx, {{{primary_key.batch_params}}});
{{#has_parent_id}}
/**
* @brief Reads the {{entity_singular}} hierarchy as a flat set of {id,
* parent_id, name} rows, via {{sql_name_base}}_hierarchy_fn.
*
* @param ctx Repository context with database connection (tenant is
* derived from ctx.tenant_id()).
* @param root_id The {{entity_singular}} to start from.
* @param from_root If true, first walks up to the ultimate ancestor and
* returns the whole tree the given node belongs to, instead of just its
* subtree.
* @return Flat hierarchy rows, ready for ores::utility::domain::build_tree.
*/
std::vector<ores::utility::domain::hierarchy_flat_row>
get_hierarchy(context ctx, const boost::uuids::uuid& root_id, bool from_root);
{{/has_parent_id}}
<<paste:DCA78C69-E508-48D9-9972-A9B8094D91FB>>
};
}
#endif
{{/domain_entity}}
{{#junction}}
#ifndef ORES_{{component_core_upper}}_REPOSITORY_{{name_singular_upper}}_REPOSITORY_HPP
#define ORES_{{component_core_upper}}_REPOSITORY_{{name_singular_upper}}_REPOSITORY_HPP
#include <string>
#include <vector>
#include <sqlgen/postgres.hpp>
{{#has_uuid_left_or_right}}
#include <boost/uuid/uuid.hpp>
{{/has_uuid_left_or_right}}
#include "ores.logging/make_logger.hpp"
#include "ores.database/domain/context.hpp"
#include "ores.{{component_include}}/domain/{{name_singular}}.hpp"
#include "ores.{{component_core}}/export.hpp"
namespace ores::{{component}}::repository {
/**
{{#read_only}}
* @brief Reads {{name_words}} from data storage. Read-only: this
* junction's rows are managed via SQL provisioning, not application
* writes.
{{/read_only}}
{{^read_only}}
* @brief Reads and writes {{name_words}} to data storage.
{{/read_only}}
*/
class ORES_{{component_core_upper}}_EXPORT {{name_singular}}_repository {
private:
inline static std::string_view logger_name =
"ores.{{component}}.repository.{{name_singular}}_repository";
[[nodiscard]] static auto& lg() {
using namespace ores::logging;
static auto instance = make_logger(logger_name);
return instance;
}
public:
using context = ores::database::context;
explicit {{name_singular}}_repository(context ctx);
std::string sql();
{{^read_only}}
void write(const domain::{{name_singular}}& {{name_singular_short}});
void write(const std::vector<domain::{{name_singular}}>& {{name_short}});
{{/read_only}}
std::vector<domain::{{name_singular}}> read_latest();
std::vector<domain::{{name_singular}}>
{{#left.is_uuid}}
read_latest_by_{{left.column_short}}(const boost::uuids::uuid& {{left.column}});
{{/left.is_uuid}}
{{^left.is_uuid}}
read_latest_by_{{left.column_short}}(const std::string& {{left.column}});
{{/left.is_uuid}}
{{#left.list_by}}
/**
* @brief Reads latest {{name_words}} filtered by {{left.column}}, with pagination.
*/
std::vector<domain::{{name_singular}}>
{{#left.is_uuid}}
read_latest_by_{{left.column_short}}(const boost::uuids::uuid& {{left.column}},
std::uint32_t offset, std::uint32_t limit);
{{/left.is_uuid}}
{{^left.is_uuid}}
read_latest_by_{{left.column_short}}(const std::string& {{left.column}},
std::uint32_t offset, std::uint32_t limit);
{{/left.is_uuid}}
/**
* @brief Gets the total count of active {{name_words}} filtered by {{left.column}}.
*/
std::uint32_t get_total_{{name_singular_short}}_count_by_{{left.column_short}}(
{{#left.is_uuid}}
const boost::uuids::uuid& {{left.column}});
{{/left.is_uuid}}
{{^left.is_uuid}}
const std::string& {{left.column}});
{{/left.is_uuid}}
{{/left.list_by}}
std::vector<domain::{{name_singular}}>
{{#right.is_uuid}}
read_latest_by_{{right.column_short}}(const boost::uuids::uuid& {{right.column}});
{{/right.is_uuid}}
{{^right.is_uuid}}
read_latest_by_{{right.column_short}}(const std::string& {{right.column}});
{{/right.is_uuid}}
{{#right.list_by}}
/**
* @brief Reads latest {{name_words}} filtered by {{right.column}}, with pagination.
*/
std::vector<domain::{{name_singular}}>
{{#right.is_uuid}}
read_latest_by_{{right.column_short}}(const boost::uuids::uuid& {{right.column}},
std::uint32_t offset, std::uint32_t limit);
{{/right.is_uuid}}
{{^right.is_uuid}}
read_latest_by_{{right.column_short}}(const std::string& {{right.column}},
std::uint32_t offset, std::uint32_t limit);
{{/right.is_uuid}}
/**
* @brief Gets the total count of active {{name_words}} filtered by {{right.column}}.
*/
std::uint32_t get_total_{{name_singular_short}}_count_by_{{right.column_short}}(
{{#right.is_uuid}}
const boost::uuids::uuid& {{right.column}});
{{/right.is_uuid}}
{{^right.is_uuid}}
const std::string& {{right.column}});
{{/right.is_uuid}}
{{/right.list_by}}
{{^read_only}}
{{#left.is_uuid}}
{{#right.is_uuid}}
void remove(const boost::uuids::uuid& {{left.column}},
const boost::uuids::uuid& {{right.column}});
void remove_by_{{left.column_short}}(const boost::uuids::uuid& {{left.column}});
{{/right.is_uuid}}
{{^right.is_uuid}}
void remove(const boost::uuids::uuid& {{left.column}},
const std::string& {{right.column}});
void remove_by_{{left.column_short}}(const boost::uuids::uuid& {{left.column}});
{{/right.is_uuid}}
{{/left.is_uuid}}
{{^left.is_uuid}}
{{#right.is_uuid}}
void remove(const std::string& {{left.column}},
const boost::uuids::uuid& {{right.column}});
void remove_by_{{left.column_short}}(const std::string& {{left.column}});
{{/right.is_uuid}}
{{^right.is_uuid}}
void remove(const std::string& {{left.column}},
const std::string& {{right.column}});
void remove_by_{{left.column_short}}(const std::string& {{left.column}});
{{/right.is_uuid}}
{{/left.is_uuid}}
{{/read_only}}
private:
context ctx_;
};
}
#endif
{{/junction}}
See also
- Parent facet: ores.cpp.repository
- Template variable reference