ores.cpp.repository.entity_header
Table of Contents
The repository entity: a struct mirroring the table shape, with the column list the query builder binds. repository profile.
See the Template variable reference for the complete list of available variables and their semantics.
1. Template
The full template source. Edit here and re-tangle with
compass build --direct tangle_codegen_templates to regenerate
library/templates/cpp_domain_type_entity.hpp.mustache.
{{! GENERATED FILE — tangled from projects/ores.codegen/library/templates/cpp_repository.org. Edit the org source. }}
{{{cpp_license}}}
{{#domain_entity}}
#ifndef ORES_{{component_core_upper}}_REPOSITORY_{{entity_singular_upper}}_ENTITY_HPP
#define ORES_{{component_core_upper}}_REPOSITORY_{{entity_singular_upper}}_ENTITY_HPP
#include <string>
#include <optional>
#include <ostream>
#include <chrono>
#include "ores.database/repository/db_types.hpp"
#include "ores.database/query_builder/columns.hpp"
{{#has_uuid_columns}}
#include <boost/uuid/uuid.hpp>
{{/has_uuid_columns}}
{{#has_tenant_id}}
#include "ores.utility/uuid/tenant_id.hpp"
{{/has_tenant_id}}
{{#has_decimal_columns}}
#include "ores.utility/decimal/decimal.hpp"
{{/has_decimal_columns}}
{{#cpp.includes.entity}}
#include {{{.}}}
{{/cpp.includes.entity}}
namespace ores::{{component}}::repository {
using db_timestamp = ores::database::repository::db_timestamp;
/**
* @brief Represents a {{entity_title_lower}} in the database.
*
* Each member holds the type its column has, so the layer binds and reads it
* in the binary format and the mapper copies it to the domain member. A column
* whose type the layer has no codec for keeps its text, and the mapper converts
* it.
*/
struct {{entity_singular}}_entity {
constexpr static const char* schema = "public";
constexpr static const char* tablename = "{{sql.tablename}}";
{{#primary_key.columns}}
{{#is_uuid}}
boost::uuids::uuid {{column}};
{{/is_uuid}}
{{#is_timestamp}}
db_timestamp {{column}};
{{/is_timestamp}}
{{#is_int}}
int {{column}}{};
{{/is_int}}
{{#is_text}}
std::string {{column}};
{{/is_text}}
{{/primary_key.columns}}
{{#has_tenant_id}}
{{#nullable_tenant_id}}
std::optional<utility::uuid::tenant_id> tenant_id;
{{/nullable_tenant_id}}
{{^nullable_tenant_id}}
utility::uuid::tenant_id tenant_id = utility::uuid::tenant_id::system();
{{/nullable_tenant_id}}
{{/has_tenant_id}}
{{#has_audit_columns}}
int version = 0;
{{/has_audit_columns}}
{{#natural_keys}}
{{#is_optional_uuid}}
std::optional<boost::uuids::uuid> {{column}};
{{/is_optional_uuid}}
{{#is_uuid}}
{{^is_optional_uuid}}
boost::uuids::uuid {{column}}{{#default_value}} = {{{default_value}}}{{/default_value}};
{{/is_optional_uuid}}
{{/is_uuid}}
{{#is_optional_timestamp}}
std::optional<db_timestamp> {{column}};
{{/is_optional_timestamp}}
{{#is_date}}
std::chrono::year_month_day {{column}};
{{/is_date}}
{{#is_timestamp}}
{{^is_optional_timestamp}}
db_timestamp {{column}};
{{/is_optional_timestamp}}
{{/is_timestamp}}
{{^is_uuid}}{{^is_optional_uuid}}{{^is_date}}{{^is_timestamp}}{{^is_optional_timestamp}}
{{{cpp_type}}} {{column}}{{#default_value}} = {{{default_value}}}{{/default_value}}{{^default_value}}{{{cpp_value_init}}}{{/default_value}};
{{/is_optional_timestamp}}{{/is_timestamp}}{{/is_date}}{{/is_optional_uuid}}{{/is_uuid}}
{{/natural_keys}}
{{#columns}}
{{#is_optional_uuid}}
std::optional<boost::uuids::uuid> {{name}};
{{/is_optional_uuid}}
{{#is_uuid}}
boost::uuids::uuid {{name}};
{{/is_uuid}}
{{#is_optional_timestamp}}
std::optional<db_timestamp> {{name}};
{{/is_optional_timestamp}}
{{#is_required_timestamp}}
db_timestamp {{name}};
{{/is_required_timestamp}}
{{#is_optional_date}}
std::optional<std::chrono::year_month_day> {{name}};
{{/is_optional_date}}
{{#is_required_date}}
std::chrono::year_month_day {{name}};
{{/is_required_date}}
{{#is_optional_decimal}}
std::optional<ores::utility::decimal::decimal> {{name}};
{{/is_optional_decimal}}
{{#is_required_decimal}}
ores::utility::decimal::decimal {{name}};
{{/is_required_decimal}}
{{#is_required_inet}}
std::string {{name}};
{{/is_required_inet}}
{{#is_base64}}
std::string {{name}};
{{/is_base64}}
{{#is_nullable_string}}
std::optional<std::string> {{name}};
{{/is_nullable_string}}
{{#is_nullable_numeric}}
std::optional<{{{cpp_type}}}> {{name}};
{{/is_nullable_numeric}}
{{#is_already_optional}}
{{{cpp_type}}} {{name}};
{{/is_already_optional}}
{{#is_enum}}
std::string {{name}};
{{/is_enum}}
{{#is_value_type}}
std::string {{name}};
{{/is_value_type}}
{{#render_is_enum}}
{{^is_enum}}
std::optional<std::string> {{name}};
{{/is_enum}}
{{/render_is_enum}}
{{#is_simple}}
{{{cpp_type}}} {{name}}{{#default_value}} = {{{default_value}}}{{/default_value}}{{^default_value}}{{{cpp_value_init}}}{{/default_value}};
{{/is_simple}}
{{/columns}}
{{#has_audit_columns}}
std::string modified_by;
std::string performed_by;
std::string change_reason_code;
std::string change_commentary;
{{/has_audit_columns}}
{{^current_state}}
db_timestamp valid_from = db_timestamp::max();
db_timestamp valid_to = db_timestamp::max();
{{/current_state}}
/**
* @brief The columns of the table, named as the members, with the key.
*/
static constexpr auto columns() {
using e = {{entity_singular}}_entity;
namespace query_builder = ores::database::query_builder;
return query_builder::columns<e>()
{{#primary_key.columns}}
| query_builder::key("{{column}}", &e::{{column}})
{{/primary_key.columns}}
{{#has_tenant_id}}
| query_builder::bind("tenant_id", &e::tenant_id)
{{/has_tenant_id}}
{{#has_audit_columns}}
| query_builder::bind("version", &e::version)
{{/has_audit_columns}}
{{#natural_keys}}
{{#is_text_stored}}
| query_builder::bind_text("{{column}}", &e::{{column}})
{{/is_text_stored}}
{{^is_text_stored}}
| query_builder::bind("{{column}}", &e::{{column}})
{{/is_text_stored}}
{{/natural_keys}}
{{#columns}}
{{^sql_only}}
{{#is_text_stored}}
| query_builder::bind_text("{{name}}", &e::{{name}})
{{/is_text_stored}}
{{^is_text_stored}}
| query_builder::bind("{{name}}", &e::{{name}})
{{/is_text_stored}}
{{/sql_only}}
{{/columns}}
{{#has_audit_columns}}
| query_builder::bind("modified_by", &e::modified_by)
| query_builder::bind("performed_by", &e::performed_by)
| query_builder::bind("change_reason_code", &e::change_reason_code)
| query_builder::bind("change_commentary", &e::change_commentary)
{{/has_audit_columns}}
{{^current_state}}
| query_builder::bind("valid_from", &e::valid_from)
| query_builder::bind("valid_to", &e::valid_to)
{{/current_state}}
;
}
};
std::ostream& operator<<(std::ostream& s, const {{entity_singular}}_entity& v);
}
#endif
{{/domain_entity}}
{{#junction}}
#ifndef ORES_{{component_core_upper}}_REPOSITORY_{{name_singular_upper}}_ENTITY_HPP
#define ORES_{{component_core_upper}}_REPOSITORY_{{name_singular_upper}}_ENTITY_HPP
#include <string>
#include <optional>
#include <ostream>
#include <chrono>
#include "ores.database/repository/db_types.hpp"
#include "ores.database/query_builder/columns.hpp"
{{#has_uuid_left_or_right}}
#include <boost/uuid/uuid.hpp>
{{/has_uuid_left_or_right}}
{{#has_tenant_id}}
#include "ores.utility/uuid/tenant_id.hpp"
{{/has_tenant_id}}
{{#has_decimal_columns}}
#include "ores.utility/decimal/decimal.hpp"
{{/has_decimal_columns}}
{{#cpp.includes.entity}}
#include {{{.}}}
{{/cpp.includes.entity}}
namespace ores::{{component}}::repository {
using db_timestamp = ores::database::repository::db_timestamp;
/**
* @brief Represents a {{name_title_lower}} in the database.
*
* Junction table with composite primary key ({{left.column}}, {{right.column}}, valid_from).
*/
struct {{name_singular}}_entity {
constexpr static const char* schema = "public";
constexpr static const char* tablename = "{{sql.tablename}}";
{{#left.is_uuid}}
boost::uuids::uuid {{left.column}};
{{/left.is_uuid}}
{{#left.is_date}}
std::chrono::year_month_day {{left.column}};
{{/left.is_date}}
{{^left.is_uuid}}{{^left.is_date}}
std::string {{left.column}};
{{/left.is_date}}{{/left.is_uuid}}
{{#has_tenant_id}}
std::string tenant_id;
{{/has_tenant_id}}
{{#right.is_uuid}}
boost::uuids::uuid {{right.column}};
{{/right.is_uuid}}
{{#right.is_date}}
std::chrono::year_month_day {{right.column}};
{{/right.is_date}}
{{^right.is_uuid}}{{^right.is_date}}
std::string {{right.column}};
{{/right.is_date}}{{/right.is_uuid}}
int version = 0;
{{#columns}}
{{#is_uuid}}
boost::uuids::uuid {{name}};
{{/is_uuid}}
{{#is_optional_uuid}}
std::optional<boost::uuids::uuid> {{name}};
{{/is_optional_uuid}}
{{#is_optional_timestamp}}
std::optional<db_timestamp> {{name}};
{{/is_optional_timestamp}}
{{#is_required_timestamp}}
db_timestamp {{name}};
{{/is_required_timestamp}}
{{#is_date}}
std::chrono::year_month_day {{name}};
{{/is_date}}
{{#is_base64}}
std::string {{name}};
{{/is_base64}}
{{^is_uuid}}{{^is_optional_uuid}}{{^is_optional_timestamp}}{{^is_required_timestamp}}{{^is_date}}{{^is_base64}}
{{{cpp_type}}} {{name}}{{#default_value}} = {{{default_value}}}{{/default_value}}{{^default_value}}{{{cpp_value_init}}}{{/default_value}};
{{/is_base64}}{{/is_date}}{{/is_required_timestamp}}{{/is_optional_timestamp}}{{/is_optional_uuid}}{{/is_uuid}}
{{/columns}}
std::string modified_by;
std::string performed_by;
std::string change_reason_code;
std::string change_commentary;
db_timestamp valid_from = db_timestamp::max();
db_timestamp valid_to = db_timestamp::max();
{{#history}}
std::optional<std::string> closed_by;
{{/history}}
/**
* @brief The columns of the table, named as the members, with the key.
*/
static constexpr auto columns() {
using e = {{name_singular}}_entity;
namespace query_builder = ores::database::query_builder;
return query_builder::columns<e>()
| query_builder::key("{{left.column}}", &e::{{left.column}})
{{#has_tenant_id}}
| query_builder::bind_text("tenant_id", &e::tenant_id)
{{/has_tenant_id}}
| query_builder::bind("{{right.column}}", &e::{{right.column}})
| query_builder::bind("version", &e::version)
{{#columns}}
{{^sql_only}}
{{#is_text_stored}}
| query_builder::bind_text("{{name}}", &e::{{name}})
{{/is_text_stored}}
{{^is_text_stored}}
| query_builder::bind("{{name}}", &e::{{name}})
{{/is_text_stored}}
{{/sql_only}}
{{/columns}}
| query_builder::bind("modified_by", &e::modified_by)
| query_builder::bind("performed_by", &e::performed_by)
| query_builder::bind("change_reason_code", &e::change_reason_code)
| query_builder::bind("change_commentary", &e::change_commentary)
| query_builder::bind("valid_from", &e::valid_from)
| query_builder::bind("valid_to", &e::valid_to)
{{#history}}
| query_builder::bind("closed_by", &e::closed_by)
{{/history}}
;
}
};
std::ostream& operator<<(std::ostream& s, const {{name_singular}}_entity& v);
}
#endif
{{/junction}}
2. Design notes
2.1. Org entity includes feed the header (2026-09-06)
The {{#cpp.includes.entity}} arm emits the org-declared "Entity includes"
block after the template's standard include set. The org_loader filters
out the standard tokens, so only includes the template cannot derive –
e.g. the header of a domain-enum column type such as
ores.trading.api/domain/product_type.hpp for trade_type's
product_type column – reach the emitted header. Org blocks that merely
repeat the standard set leave regeneration byte-identical.
The filter (org_loader's _ENTITY_HEADER_STANDARD_INCLUDES) also drops
the tokens org blocks add that no emitted member can require, and
applies to junction entity headers as well as domain ones:
boost/uuid/uuid.hppis never needed in an org block: the template emits it underhas_uuid_columns, which counts every uuid-typed member the header declares, including a junction's PK and FK sides;<cstdint>is a stale transcription of headers no entity member needs; the canonical entity headers compile without it and the drift registry pins them byte-for-byte.
Without these drops, the whole-estate drift check flags the four
registered-component headers whose orgs declare them (compute
app_version_platform, iam account_party, reporting
report_definition and report_instance). A real future need for one of
these headers in the entity header belongs in this template's fixed
include set, not in an org block.
2.2. Domain entity and junction
Both the {{#domain_entity}} and {{#junction}} sections use the
db_timestamp type (ores::database::repository::db_timestamp, from
db_types.hpp) for valid_from and valid_to, and both use the
component_core_upper-based include guard.
3. See also
- Parent facet: ores.cpp.repository
- Template variable reference