Templating¶
db-gen output is generated entirely from Go templates you control. The tool stays language-agnostic — the template decides the syntax. This page covers the core templates, the data they receive, the helper functions, and per-routine overrides.
For the full struct definitions, see the Template data reference.
Core templates¶
Configured in db-gen.json:
| Key | Receives | Generates |
|---|---|---|
DbContextTemplate |
all routines (Functions) |
the database-call code |
ModelTemplate |
one routine | a model per routine return shape |
ProcessorTemplate |
one routine | a mapper from db reader → model |
For anything else (TypeScript types, providers, …) use Additional Generators. For bulk-COPY code, see Copy Targets.
Template data¶
Every template can access Config (the full configuration), BuildInfo (version/build metadata), and routine data. The DbContext template gets all routines; Model/Processor templates get one.
type DbContextData struct {
Config *Config
Functions []Routine
BuildInfo *version.BuildInformation
}
type Routine struct {
FunctionName string
DbFullFunctionName string
ModelName string
ProcessorName string
Schema string
DbFunctionName string
HasReturn bool
IsProcedure bool
Parameters []Property // all parameters, in order
ReturnProperties []Property
UsesUserContext bool
ContextParameters []Property // params mapped to the context object
RegularParameters []Property // params not mapped to context
}
See the Template data reference for Property and the rest.
Template functions¶
Default output is camelCase. Use these helpers to change case or clean names:
| Function | Example result |
|---|---|
pascalCased |
GetUserById |
camelCased |
getUserById |
snakeCased |
get_user_by_id |
normalizeStr |
strips leading underscores (_user_id → user_id); keeps underscores before digits (country_iso_2) |
trimPrefix |
strips a given prefix |
templateVar |
looks up a template variable by key (case-insensitive) |
inc |
increments an integer (handy for 1-based indexing) |
normalizeStr vs round-tripping
Since v0.6.1 the bundled Model/Processor templates use {{normalizeStr $property.DbColumnName}} instead of {{snakeCased $property.PropertyName}}. Round-tripping through PascalCase loses information — e.g. country_iso_2 would collapse to country_iso2.
A minimal example¶
// Generated by db-gen {{.BuildInfo.Version}}
public partial class DbContext
{
{{- range .Functions}}
public async Task<{{.ModelName}}> {{.FunctionName}}Async(
{{- range $i, $p := .Parameters}}{{if $i}}, {{end}}{{$p.PropertyType}} {{camelCased $p.PropertyName}}{{end}})
{
// call {{.Schema}}.{{.DbFunctionName}}
}
{{- end}}
}
Per-routine overrides¶
In Generate[].Functions, a function key maps to either a boolean (generate or not) or an override object. The key may be a bare name (my_func) or include a signature (my_func(text,int)).
| Field | Effect |
|---|---|
MappedName |
Override the generated name; model/processor names append Model/Processor. |
DontRetrieveValues |
Disable value selection for a function that has return values (off-only). |
SelectOnlySpecified |
In Model, select only the columns you explicitly list. |
Model |
Object keyed by db column name. false skips it; true or an object selects it. The object may override MappedName, IsNullable, MappedType, MappingFunction. |
Parameters |
Object keyed by parameter name. Values must be objects (not booleans). Override MappedName, MappedType, IsNullable, IsOptional, SecurityLevel. |
{
"Functions": {
"get_report": {
"MappedName": "GetReport",
"Model": {
"total": { "MappedType": "decimal", "IsNullable": true },
"internal_flag": false
}
}
}
}
Type overrides and global lookup
When overriding a column's MappedType only, db-gen looks up the mapping function from the global type mappings. Setting MappingFunction without MappedType does nothing. Leave fields you don't intend to change empty so the global mapping is used.
Overloaded functions¶
Every overloaded function must be given a unique MappedName, because their generated names would otherwise collide. The name must be unique within the schema.
{
"Functions": {
"search(text)": { "MappedName": "SearchByText" },
"search(int)": { "MappedName": "SearchById" }
}
}
Template variables¶
TemplateVariables is a free-form string→string map in the config, passed to every template. It lets one shared template set serve multiple projects that differ only in config — e.g. output namespaces. Read a value with the templateVar function:
Lookup is case-insensitive: config loading lowercases every key, and templateVar lowercases the requested key before matching — author and reference keys in whatever casing reads best (GeneratedNs, generated_ns, …). Values keep their exact case, and a missing key yields an empty string.
{
"TemplateVariables": {
"GeneratedNs": "MyCompany.Data.Generated",
"ContextNs": "MyCompany.Data"
}
}
Parameter security levels¶
Every parameter carries a SecurityLevel describing how sensitive it is to logging. db-gen only resolves and exposes the level — it never renders masking itself. Your template decides what to emit for each level, which keeps db-gen language-agnostic (same philosophy as copy targets).
The four levels:
| Level | Meaning |
|---|---|
none |
Log the value plainly. |
secure |
Log plainly or masked depending on a runtime flag in your code. |
strict |
Always log masked. |
omit |
Never include in any log output. |
Assign levels in config — globally by name via ParameterSecurityMappings, a project-wide default via DefaultParameterSecurityLevel (defaults to secure), or per function via Functions[].Parameters[].SecurityLevel. Resolution precedence: per-function override → global mapping → default. Matching on the db parameter name is case-insensitive.
A template branches on $p.SecurityLevel to render the masking:
{{range $p := .Routine.RegularParameters}}
{{- if ne $p.SecurityLevel "omit"}}
log.Add("{{$p.PropertyName}}",
{{- if eq $p.SecurityLevel "strict"}} "******"
{{- else if eq $p.SecurityLevel "secure"}} InsecureLogging ? {{$p.PropertyName}}.ToString() : "******"
{{- else}} {{$p.PropertyName}}.ToString()
{{- end}});
{{- end}}
{{- end}}