Documentation
¶
Overview ¶
package include defines include specs, which represent a subset of the object graph in the database. They can be used to instruct the code generated by pggen to load child entities attached to a given entity by a 1-1, 1-* or *-* relationship in an efficient way that avoids N+1 queries.
In order to make defining include specs more convenient, they have a simple textual syntax for describing them. The syntax for include specs is reminiscent of dot access syntax, except that multiple tables can be accessed at once. For example, if you had an `foos` table that had a 1-* relationship with a `bars` table, you could use the following to produce an `include.Spec` to efficiently load all the bars attached to a foo:
```go spec := include.Must(include.Parse("foos.bars")) ```
Dot access syntax works well enough when a table has just a single relationship, but it doesn't handle relationships with multiple tables, so include spec syntax allows you to write a list of sub-specs separated by commas and enclosed in a set of curly braces.
For example, if the `foos` table also had a `bazes` attached to it with a 1-* relationship and the `bars` table had a `quxes` table attached to it in the same way, you could use to following to create a spec for loading all the objects attached to a given foo, even transitively.
```go spec := include.Must(include.Parse("foos.{bars.quxes, bazes}")) ```
In order to match the semantics of SQL, include specs allow quoted identifiers, so the spec `"space table".{"how odd", "right?"}` is a valid include spec. Just like in SQL, you can escape a `"` in a quoted identifier with `""`.
If a parent table uses a name besides the name of a child table to refer to it, the include spec must include this information somehow. In order to do this, include specs have rename expressions, which consist of the name used by the parent the '->' operator and the name of the child table. For example if the `sales` table referred to the users table with the name `customer`, an include spec for pulling customer data would look like `sales.customer->users`.
More formally, the grammar for include specs is:
spec ::= id
| id '.' inner_spec | id '.' '{' spec_list '}'
inner_spec ::= id
| rename_or_id '.' inner_spec | rename_or_id '.' '{' spec_list '}'
rename_or_id ::= id '->' id
| id
spec_list ::= inner_spec
| inner_spec ',' inner_spec
Cyclic Include Specs:
The object graph in a database schema might have cyclic references, which don't map the most obviously to the hierarchical representation used by include specs, especially in their textual form. Include specs can still be used to describe cycles though. Each cycle in an include spec has a root node, which is the one closest to the root node of the include spec. Cycles are expressed as the path from the root node back to itself.
For example, if the table `foo` referenced the table `bar` which contained a reference back to `foo`, the include spec `foo.bar.foo` could be used to capture that cycle.
Filling in Parent References:
SQL references are bidirectional, and pggen preserves those semantics in generated code by emitting pointers back to parent records in the model structs that it generates. These can be filled in using include specs, just like ordinary references, and doing so will not hit the database again if the parent record had already been loaded into memory. You do still need to explicitly tell pggen to fill in these references for you, which you can do by adding a sub-spec pointing to the parent. For example if the `bar` table refers to the `foo` table with a foreign key, we would usually think of the `foo` table as the parent and the `bar` table as the child. We have already seen that the include spec `foo.bar` would fill in the references in the generated `Foo` struct with generated `Bar` structs, but that won't fill in the references back to the parent from the `Bar` children. To do that we would need to use an include spec of `foo.bar.foo`.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Spec ¶
type Spec struct { // The name of the table that this is a spec for filling in TableName string // All the child tables to fill in Includes map[string]*Spec }
Spec is the parsed form of an include spec. Specs can be constructed directly, or parsed from a terse string format using the Parse routine.