Skip to content

Type Mapping

db-gen maps each PostgreSQL type to a target-language type. Because a type can appear as a non-null return, a nullable return, a nullable parameter, or an optional (DEFAULT) parameter — each potentially needing a different target type — db-gen uses a three-tier mapping system.

Defining mappings

Mappings is an array; each entry covers one or more PostgreSQL udt_names:

{
  "Mappings": [
    {
      "DatabaseTypes": ["int4"],
      "MappedType": "int",
      "MappingFunction": "GetInt32",
      "NullableReturnType": "int?",
      "NullableParameterType": "int?",
      "OptionalParameterType": "Optional<int>"
    },
    {
      "DatabaseTypes": ["text", "varchar"],
      "MappedType": "string",
      "MappingFunction": "GetString",
      "NullableReturnType": "string?"
    },
    {
      "DatabaseTypes": ["*"],
      "MappedType": "object",
      "MappingFunction": "GetValue"
    }
  ]
}

Catch-all fallback

Add a "*" entry as a fallback for unmapped types. Without it, an unmapped type stops generation with an error. If a type appears in multiple entries, the last one wins.

The four target types

Field Used for Example
MappedType base — non-nullable, non-optional int
NullableReturnType a nullable return value / model property int?
NullableParameterType a nullable parameter without a DEFAULT int?
OptionalParameterType a parameter with a DEFAULT Optional<int>

Resolution rules

For parameters:

flowchart TD
    A[Parameter] --> B{Optional?<br/>has DEFAULT}
    B -->|yes, and OptionalParameterType set| C[OptionalParameterType]
    B -->|no| D{Nullable?<br/>accepts NULL}
    D -->|yes, and NullableParameterType set| E[NullableParameterType]
    D -->|no| F[MappedType]

For return / model columns: nullable → NullableReturnType if set; otherwise MappedType.

Nullable vs optional

This distinction is central:

Meaning Passed to DB? Type
Nullable no DEFAULT, accepts NULL always (may be null) T?
Optional has a DEFAULT may be omitted entirely Optional<T>

In templates, check $parameter.Optional to decide between "omit if absent" and "always pass":

{{- if $param.Optional}}
    {{$param.PropertyName}}.ToObjectOptional()
{{- else}}
    {{$param.PropertyName}}
{{- end}}

Why nullable parameters use T?, not Optional<T>

A nullable parameter must always be sent to the database (it can legitimately be null). If it were typed Optional<T>, an absent value could be dropped from the call entirely, changing behavior. Only parameters with a DEFAULT use the optional type.

Per-function overrides

You can override types for a single function's parameters or model columns via Generate[].Functions. See Templating → per-routine overrides.

{
  "Functions": {
    "get_report": {
      "Model": { "total": { "MappedType": "decimal", "IsNullable": true } },
      "Parameters": { "page_size": { "MappedType": "int", "IsOptional": true } }
    }
  }
}

When you set only MappedType, db-gen looks up the matching MappingFunction from the global mappings (and errors if none exists).