ores.cpp.generator.generator_impl
Table of Contents
faker-cxx generation per column type. generator profile. Uses faker-cxx to produce structurally-valid synthetic instances. Counter-suffixed keys guarantee uniqueness within a test run: text natural keys, text primary keys, and :unique: plain-string columns all carry the process counter (a faker-derived base is a process constant, so a :unique: column without the suffix would collide on its unique index from the second row on). Temporal fields are filled with plausible past timestamps via the generation context.
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_generator.cpp.mustache.
{{! GENERATED FILE — tangled from projects/ores.codegen/library/templates/cpp_domain.org. Edit the org source. }}
{{{cpp_license}}}
{{#domain_entity}}
#include "ores.{{component_include}}/{{generator_facet_name}}/{{entity_singular}}_generator.hpp"
#include <atomic>
#include <string>
#include <unordered_set>
{{#has_base64_columns}}
#include <cstdint>
#include <vector>
{{/has_base64_columns}}
#include <faker-cxx/faker.h> // IWYU pragma: keep.
{{#has_tenant_id}}
#include "ores.utility/uuid/tenant_id.hpp"
{{/has_tenant_id}}
#include "ores.utility/generation/generation_keys.hpp"
namespace ores::{{component}}::{{generator_facet_name}} {
using ores::utility::generation::generation_keys;
domain::{{entity_singular}} generate_synthetic_{{entity_singular}}(
utility::generation::generation_context& ctx) {
{{#needs_counter}}
[[maybe_unused]] static std::atomic<int> counter{0};
{{/needs_counter}}
{{#has_audit_columns}}
const auto modified_by = ctx.env().get_or(
std::string(generation_keys::modified_by), "system");
{{/has_audit_columns}}
{{#has_tenant_id}}
{{#nullable_tenant_id}}
const auto tid_str = ctx.env().get_or(
std::string(generation_keys::tenant_id), std::string(""));
{{/nullable_tenant_id}}
{{^nullable_tenant_id}}
const auto tid_str = ctx.env().get_or(
std::string(generation_keys::tenant_id), std::string("system"));
{{/nullable_tenant_id}}
{{/has_tenant_id}}
domain::{{entity_singular}} r;
{{#has_audit_columns}}
r.{{{scaffold_prefix}}}version = 0;
{{/has_audit_columns}}
{{#has_tenant_id}}
{{#nullable_tenant_id}}
if (!tid_str.empty())
r.{{{scaffold_prefix}}}tenant_id = utility::uuid::tenant_id::from_string(tid_str).value();
{{/nullable_tenant_id}}
{{^nullable_tenant_id}}
r.{{{scaffold_prefix}}}tenant_id = utility::uuid::tenant_id::from_string(tid_str)
.value_or(utility::uuid::tenant_id::system());
{{/nullable_tenant_id}}
{{/has_tenant_id}}
{{#has_workspace_id}}
r.{{{scaffold_prefix}}}workspace_id = utility::uuid::live_workspace_id();
{{/has_workspace_id}}
{{#primary_key.is_text}}
const auto idx = counter.fetch_add(1, std::memory_order_relaxed);
{{#primary_key.generator_expr}}
r.{{{scaffold_prefix}}}{{primary_key.column}} = {{{primary_key.generator_expr}}} + "-"
+ std::to_string(idx);
{{/primary_key.generator_expr}}
{{^primary_key.generator_expr}}
r.{{{scaffold_prefix}}}{{primary_key.column}} = std::string(faker::word::noun()) + "-"
+ std::to_string(idx);
{{/primary_key.generator_expr}}
{{/primary_key.is_text}}
{{#primary_key.is_uuid}}
r.{{{scaffold_prefix}}}{{primary_key.column}} = ctx.generate_uuid();
{{#has_text_natural_keys}}
const auto idx = counter.fetch_add(1, std::memory_order_relaxed);
{{/has_text_natural_keys}}
{{^has_text_natural_keys}}
{{#has_unique_suffix_columns}}
const auto idx = counter.fetch_add(1, std::memory_order_relaxed);
{{/has_unique_suffix_columns}}
{{/has_text_natural_keys}}
{{/primary_key.is_uuid}}
{{#primary_key.extra_columns}}
{{#is_uuid}}
r.{{{group_prefix}}}{{column}} = ctx.generate_uuid();
{{/is_uuid}}
{{#is_int}}
{{#generator_expr}}
r.{{{group_prefix}}}{{column}} = {{{generator_expr}}};
{{/generator_expr}}
{{^generator_expr}}
r.{{{group_prefix}}}{{column}} = 0;
{{/generator_expr}}
{{/is_int}}
{{#is_timestamp}}
{{#generator_expr}}
r.{{{group_prefix}}}{{column}} = {{{generator_expr}}};
{{/generator_expr}}
{{^generator_expr}}
r.{{{group_prefix}}}{{column}} = ctx.past_timepoint();
{{/generator_expr}}
{{/is_timestamp}}
{{#is_date}}
{{#generator_expr}}
r.{{{group_prefix}}}{{column}} = {{{generator_expr}}};
{{/generator_expr}}
{{^generator_expr}}
r.{{{group_prefix}}}{{column}} = std::chrono::year_month_day{
std::chrono::floor<std::chrono::days>(ctx.past_timepoint())};
{{/generator_expr}}
{{/is_date}}
{{^is_uuid}}
{{^is_int}}
{{^is_timestamp}}
{{^is_date}}
{{#generator_expr}}
r.{{{group_prefix}}}{{column}} = {{{generator_expr}}};
{{/generator_expr}}
{{^generator_expr}}
r.{{{group_prefix}}}{{column}} = std::string(faker::word::noun());
{{/generator_expr}}
{{/is_date}}
{{/is_timestamp}}
{{/is_int}}
{{/is_uuid}}
{{/primary_key.extra_columns}}
{{#natural_keys}}
{{#is_uuid}}
r.{{column}} = ctx.generate_uuid();
{{/is_uuid}}
{{#is_int}}
{{#generator_expr}}
r.{{column}} = {{{generator_expr}}};
{{/generator_expr}}
{{^generator_expr}}
r.{{column}} = 0;
{{/generator_expr}}
{{/is_int}}
{{#is_timestamp}}
{{#generator_expr}}
r.{{column}} = {{{generator_expr}}};
{{/generator_expr}}
{{^generator_expr}}
r.{{column}} = ctx.past_timepoint();
{{/generator_expr}}
{{/is_timestamp}}
{{#is_date}}
{{#generator_expr}}
r.{{column}} = {{{generator_expr}}};
{{/generator_expr}}
{{^generator_expr}}
r.{{column}} = std::chrono::year_month_day{
std::chrono::floor<std::chrono::days>(ctx.past_timepoint())};
{{/generator_expr}}
{{/is_date}}
{{^is_uuid}}
{{^is_int}}
{{^is_timestamp}}
{{^is_date}}
{{#generator_expr}}
{{#no_generator_suffix}}
r.{{column}} = {{{generator_expr}}};
{{/no_generator_suffix}}
{{^no_generator_suffix}}
r.{{column}} = {{{generator_expr}}} + "-"
+ std::to_string(idx);
{{/no_generator_suffix}}
{{/generator_expr}}
{{^generator_expr}}
r.{{column}} = std::string(faker::word::noun()) + "-"
+ std::to_string(idx);
{{/generator_expr}}
{{/is_date}}
{{/is_timestamp}}
{{/is_int}}
{{/is_uuid}}
{{/natural_keys}}
{{#columns}}
{{^sql_only}}
{{#generator_expr}}
{{#requires_unique_suffix}}
r.{{{group_prefix}}}{{name}} = {{{generator_expr}}} + "-"
+ std::to_string(idx);
{{/requires_unique_suffix}}
{{^requires_unique_suffix}}
r.{{{group_prefix}}}{{name}} = {{{generator_expr}}};
{{/requires_unique_suffix}}
{{/generator_expr}}
{{^generator_expr}}
{{#is_uuid}}
r.{{{group_prefix}}}{{name}} = ctx.generate_uuid();
{{/is_uuid}}
{{#is_plain_string}}
{{#requires_unique_suffix}}
r.{{{group_prefix}}}{{name}} = std::string(faker::word::noun()) + "-"
+ std::to_string(idx);
{{/requires_unique_suffix}}
{{^requires_unique_suffix}}
r.{{{group_prefix}}}{{name}} = std::string(faker::word::noun());
{{/requires_unique_suffix}}
{{/is_plain_string}}
{{#is_base64}}
r.{{{group_prefix}}}{{name}} = std::vector<std::uint8_t>{'<', 's', 'v', 'g', '/', '>'};
{{/is_base64}}
{{/generator_expr}}
{{/sql_only}}
{{/columns}}
{{#has_audit_columns}}
r.{{{audit_prefix}}}modified_by = modified_by;
r.{{{audit_prefix}}}performed_by = modified_by;
r.{{{audit_prefix}}}change_reason_code = "system.test";
r.{{{audit_prefix}}}change_commentary = "Synthetic test data";
r.{{{audit_prefix}}}recorded_at = ctx.past_timepoint();
{{/has_audit_columns}}
return r;
}
std::vector<domain::{{entity_singular}}>
generate_synthetic_{{entity_plural}}(std::size_t n,
utility::generation::generation_context& ctx) {
std::vector<domain::{{entity_singular}}> r;
r.reserve(n);
while (r.size() < n)
r.push_back(generate_synthetic_{{entity_singular}}(ctx));
return r;
}
<<paste:C2F8A4E3-7D5B-4C2F-8A1E-3D9C6B2E5F1A>>
}
{{/domain_entity}}
{{#junction}}
#include "ores.{{component_include}}/{{generator_facet_name}}/{{name_singular}}_generator.hpp"
{{#has_uuid_left_or_right}}
#include <boost/uuid/uuid_io.hpp>
{{/has_uuid_left_or_right}}
{{#needs_counter}}
#include <atomic>
{{/needs_counter}}
#include <faker-cxx/faker.h> // IWYU pragma: keep.
#include "ores.utility/generation/generation_keys.hpp"
namespace ores::{{component}}::{{generator_facet_name}} {
using ores::utility::generation::generation_keys;
domain::{{name_singular}} generate_synthetic_{{name_singular}}(
utility::generation::generation_context& ctx) {
{{#needs_counter}}
static std::atomic<int> counter{0};
const auto idx = counter.fetch_add(1, std::memory_order_relaxed);
{{/needs_counter}}
const auto modified_by = ctx.env().get_or(
generation_keys::modified_by, "system");
{{#has_tenant_id}}
const auto tenant_id = ctx.env().get_or(
generation_keys::tenant_id, "system");
{{/has_tenant_id}}
domain::{{name_singular}} r;
r.version = 0;
{{#has_tenant_id}}
r.tenant_id = tenant_id;
{{/has_tenant_id}}
r.{{left.column}} = {{{left.generator_expr}}};
r.{{right.column}} = {{{right.generator_expr}}};
{{#columns}}
r.{{name}} = {{{generator_expr}}};
{{/columns}}
r.modified_by = modified_by;
r.performed_by = modified_by;
r.change_reason_code = "system.test";
r.change_commentary = "Synthetic test data";
r.recorded_at = ctx.past_timepoint();
return r;
}
std::vector<domain::{{name_singular}}>
generate_synthetic_{{name}}(std::size_t n,
utility::generation::generation_context& ctx) {
std::vector<domain::{{name_singular}}> r;
r.reserve(n);
while (r.size() < n)
r.push_back(generate_synthetic_{{name_singular}}(ctx));
return r;
}
}
{{/junction}}
2. See also
- Parent facet: ores.cpp.domain
- Template variable reference