Skip to content

Commit

Permalink
Add Options#enablePrimaryKeyType (fix #77)
Browse files Browse the repository at this point in the history
  • Loading branch information
oyvindberg committed Jan 1, 2024
1 parent fe20e4a commit 5712552
Show file tree
Hide file tree
Showing 48 changed files with 202 additions and 279 deletions.
30 changes: 1 addition & 29 deletions site-in/customization/customize-selected-relations.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,42 +9,14 @@ Maybe you're generating code for just a part of the system, not the whole thing.
Typo has a mechanism by which you can choose which relations to generate code for.

among the arguments to `generateFromDb` is `selector`, which by default picks all relations except those in the postgres schemas.
See [Selector](customization/selector.md)

```scala
import typo.*

generateFromDb(options, selector = Selector.ExcludePostgresInternal)
```

## `Selector`

You can pick relations by expressing with `Selector` what you want:
```scala mdoc:silent
import typo.*

val personAndPet0 = Selector.fullRelationNames("myschema.person", "myschemapet") // picks exactly these tables
val personAndPet = Selector.relationNames("person", "pet") // picks these regardless of schema
val mySchema = Selector.schemas("myschema") // picks all relations in schema

// heaviest syntax, but most flexible
val custom: Selector = relName => relName.schema.exists(_.contains("foo")) && relName.name.contains("bar")

// can also invert the selector
!Selector.schemas("myschema") // matches everything except schema "myschema"
```

Selectors are also composable:

```scala mdoc:silent
// picks relations which are called `person` or `pet` AND are in the `myschema` schema
personAndPet and mySchema

// picks those who are *both* called `person` or `pet` OR are in the `myschema` schema.
// This will typically select more relations
personAndPet or mySchema
```

The and/or names follows boolean logic, and may actually be a bit counter-intuitive in this particular context. Suggestions welcome to improve naming

## Transitive relations

Expand Down
1 change: 1 addition & 0 deletions site-in/customization/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ val options = Options(
| `enableFieldValue` | Controls whether to enable `FieldValue` code generation for specific repositories (default is disabled). |
| `enableStreamingInserts` | Controls whether to enable [streaming inserts](other-features/streaming-inserts.md) |
| `enableTestInserts` | Controls whether to enable [test inserts](other-features/testing-with-random-values.md) for specific repositories (default is none). |
| `enablePrimaryKeyType` | Controls whether to enable [primary key types](type-safety/id-types.md) for specific repositories (default is all). |
| `readonlyRepo` | Specifies whether to generate read-only repositories for specific repositories. Useful when you're working on a part of the system where you only consume certain tables. (default is `false` - all mutable). |
| `enableDsl` | Enables the [SQL DSL](what-is/dsl.md) for code generation (default is `false`). |
| `keepDependencies` | Specifies whether to generate [table dependencies](type-safety/type-flow.md) in generated code even if you didn't select them (default is `false`). |
Expand Down
40 changes: 40 additions & 0 deletions site-in/customization/selector.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
title: Picking subsets of relations with Selector
---

For much of the customization, you select sets of relations, or enable particular pieces of code generation for a set of relations.

In order to make this convenient, there is a `Selector` data type.

## Pick relations by name or by schema
You can pick relations by expressing with `Selector` what you want:

```scala mdoc:silent
import typo.*

val personAndPet0 = Selector.fullRelationNames("myschema.person", "myschemapet") // picks exactly these tables
val personAndPet = Selector.relationNames("person", "pet") // picks these regardless of schema
val mySchema = Selector.schemas("myschema") // picks all relations in schema

// heaviest syntax, but most flexible
val custom: Selector = relName => relName.schema.exists(_.contains("foo")) && relName.name.contains("bar")

```

### Selectors can be inverted
```scala mdoc:silent
!Selector.schemas("myschema") // matches everything except schema "myschema"
```

### Selectors are also composable:

```scala mdoc:silent
// picks relations which are called `person` or `pet` AND are in the `myschema` schema
personAndPet and mySchema

// picks those who are *both* called `person` or `pet` OR are in the `myschema` schema.
// This will typically select more relations
personAndPet or mySchema
```

The and/or names follows boolean logic, and may actually be a bit counter-intuitive in this particular context. Suggestions welcome to improve naming
19 changes: 18 additions & 1 deletion site-in/type-safety/id-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,21 @@ case class EmployeedepartmenthistoryId(
object EmployeedepartmenthistoryId {
// ...instances
}
```
```

## I don't want these

if you have some tables where you don't want the type-safety this brings, you can [customize](customization/overview.md)
code generation by tweaking `Options#enablePrimaryKeyType`:

```scala mdoc:silent
import typo.*

val options = Options(
pkg = "mypkg",
Some(DbLibName.Doobie),
enablePrimaryKeyType = Selector.relationNames("myrelationname"),
)
```

Composite id key types are currently always created.
1 change: 1 addition & 0 deletions site/sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ const sidebars = {
{type: "doc", id: "customization/customize-naming"},
{type: "doc", id: "customization/customize-nullability"},
{type: "doc", id: "customization/customize-types"},
{type: "doc", id: "customization/selector"},
],
},
]
Expand Down
7 changes: 4 additions & 3 deletions typo-scripts/src/scala/scripts/GeneratedAdventureWorks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,11 @@ object GeneratedAdventureWorks {
case (_, "firstname") => "adventureworks.userdefined.FirstName"
case ("sales.creditcard", "creditcardid") => "adventureworks.userdefined.CustomCreditcardId"
},
enableDsl = true,
enableTestInserts = Selector.All,
generateMockRepos = !Selector.relationNames("purchaseorderdetail"),
readonlyRepo = Selector.relationNames("purchaseorderdetail")
enablePrimaryKeyType = !Selector.relationNames("billofmaterials"),
enableTestInserts = Selector.All,
readonlyRepo = Selector.relationNames("purchaseorderdetail"),
enableDsl = true
)
val targetSources = buildDir.resolve(s"$projectPath/generated-and-checked-in")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,14 @@ package bom

import adventureworks.customtypes.TypoLocalDateTime
import adventureworks.customtypes.TypoShort
import adventureworks.production.billofmaterials.BillofmaterialsId
import adventureworks.production.product.ProductId
import adventureworks.production.unitmeasure.UnitmeasureId
import typo.dsl.SqlExpr.Field
import typo.dsl.SqlExpr.OptField

trait BomViewFields[Row] {
val id: Field[BillofmaterialsId, Row]
val billofmaterialsid: Field[BillofmaterialsId, Row]
val id: Field[Int, Row]
val billofmaterialsid: Field[Int, Row]
val productassemblyid: OptField[ProductId, Row]
val componentid: Field[ProductId, Row]
val startdate: Field[TypoLocalDateTime, Row]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ package bom

import adventureworks.customtypes.TypoLocalDateTime
import adventureworks.customtypes.TypoShort
import adventureworks.production.billofmaterials.BillofmaterialsId
import adventureworks.production.product.ProductId
import adventureworks.production.unitmeasure.UnitmeasureId
import anorm.Column
Expand All @@ -26,9 +25,9 @@ import scala.util.Try

case class BomViewRow(
/** Points to [[production.billofmaterials.BillofmaterialsRow.billofmaterialsid]] */
id: BillofmaterialsId,
id: Int,
/** Points to [[production.billofmaterials.BillofmaterialsRow.billofmaterialsid]] */
billofmaterialsid: BillofmaterialsId,
billofmaterialsid: Int,
/** Points to [[production.billofmaterials.BillofmaterialsRow.productassemblyid]] */
productassemblyid: Option[ProductId],
/** Points to [[production.billofmaterials.BillofmaterialsRow.componentid]] */
Expand All @@ -51,8 +50,8 @@ object BomViewRow {
implicit lazy val reads: Reads[BomViewRow] = Reads[BomViewRow](json => JsResult.fromTry(
Try(
BomViewRow(
id = json.\("id").as(BillofmaterialsId.reads),
billofmaterialsid = json.\("billofmaterialsid").as(BillofmaterialsId.reads),
id = json.\("id").as(Reads.IntReads),
billofmaterialsid = json.\("billofmaterialsid").as(Reads.IntReads),
productassemblyid = json.\("productassemblyid").toOption.map(_.as(ProductId.reads)),
componentid = json.\("componentid").as(ProductId.reads),
startdate = json.\("startdate").as(TypoLocalDateTime.reads),
Expand All @@ -68,8 +67,8 @@ object BomViewRow {
def rowParser(idx: Int): RowParser[BomViewRow] = RowParser[BomViewRow] { row =>
Success(
BomViewRow(
id = row(idx + 0)(BillofmaterialsId.column),
billofmaterialsid = row(idx + 1)(BillofmaterialsId.column),
id = row(idx + 0)(Column.columnToInt),
billofmaterialsid = row(idx + 1)(Column.columnToInt),
productassemblyid = row(idx + 2)(Column.columnToOption(ProductId.column)),
componentid = row(idx + 3)(ProductId.column),
startdate = row(idx + 4)(TypoLocalDateTime.column),
Expand All @@ -83,8 +82,8 @@ object BomViewRow {
}
implicit lazy val writes: OWrites[BomViewRow] = OWrites[BomViewRow](o =>
new JsObject(ListMap[String, JsValue](
"id" -> BillofmaterialsId.writes.writes(o.id),
"billofmaterialsid" -> BillofmaterialsId.writes.writes(o.billofmaterialsid),
"id" -> Writes.IntWrites.writes(o.id),
"billofmaterialsid" -> Writes.IntWrites.writes(o.billofmaterialsid),
"productassemblyid" -> Writes.OptionWrites(ProductId.writes).writes(o.productassemblyid),
"componentid" -> ProductId.writes.writes(o.componentid),
"startdate" -> TypoLocalDateTime.writes.writes(o.startdate),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ package bom

import adventureworks.customtypes.TypoLocalDateTime
import adventureworks.customtypes.TypoShort
import adventureworks.production.billofmaterials.BillofmaterialsId
import adventureworks.production.product.ProductId
import adventureworks.production.unitmeasure.UnitmeasureId
import typo.dsl.SqlExpr.Field
Expand All @@ -21,8 +20,8 @@ class BomViewStructure[Row](val prefix: Option[String], val extract: Row => BomV
extends Relation[BomViewFields, BomViewRow, Row]
with BomViewFields[Row] { outer =>

override val id = new Field[BillofmaterialsId, Row](prefix, "id", None, None)(x => extract(x).id, (row, value) => merge(row, extract(row).copy(id = value)))
override val billofmaterialsid = new Field[BillofmaterialsId, Row](prefix, "billofmaterialsid", None, None)(x => extract(x).billofmaterialsid, (row, value) => merge(row, extract(row).copy(billofmaterialsid = value)))
override val id = new Field[Int, Row](prefix, "id", None, None)(x => extract(x).id, (row, value) => merge(row, extract(row).copy(id = value)))
override val billofmaterialsid = new Field[Int, Row](prefix, "billofmaterialsid", None, None)(x => extract(x).billofmaterialsid, (row, value) => merge(row, extract(row).copy(billofmaterialsid = value)))
override val productassemblyid = new OptField[ProductId, Row](prefix, "productassemblyid", None, None)(x => extract(x).productassemblyid, (row, value) => merge(row, extract(row).copy(productassemblyid = value)))
override val componentid = new Field[ProductId, Row](prefix, "componentid", None, None)(x => extract(x).componentid, (row, value) => merge(row, extract(row).copy(componentid = value)))
override val startdate = new Field[TypoLocalDateTime, Row](prefix, "startdate", Some("text"), None)(x => extract(x).startdate, (row, value) => merge(row, extract(row).copy(startdate = value)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import typo.dsl.SqlExpr.IdField
import typo.dsl.SqlExpr.OptField

trait BillofmaterialsFields[Row] {
val billofmaterialsid: IdField[BillofmaterialsId, Row]
val billofmaterialsid: IdField[Int, Row]
val productassemblyid: OptField[ProductId, Row]
val componentid: Field[ProductId, Row]
val startdate: Field[TypoLocalDateTime, Row]
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import typo.dsl.SelectBuilder
import typo.dsl.UpdateBuilder

trait BillofmaterialsRepo {
def delete(billofmaterialsid: BillofmaterialsId)(implicit c: Connection): Boolean
def delete(billofmaterialsid: Int)(implicit c: Connection): Boolean
def delete: DeleteBuilder[BillofmaterialsFields, BillofmaterialsRow]
def insert(unsaved: BillofmaterialsRow)(implicit c: Connection): BillofmaterialsRow
def insertStreaming(unsaved: Iterator[BillofmaterialsRow], batchSize: Int)(implicit c: Connection): Long
Expand All @@ -22,8 +22,8 @@ trait BillofmaterialsRepo {
def insertUnsavedStreaming(unsaved: Iterator[BillofmaterialsRowUnsaved], batchSize: Int)(implicit c: Connection): Long
def select: SelectBuilder[BillofmaterialsFields, BillofmaterialsRow]
def selectAll(implicit c: Connection): List[BillofmaterialsRow]
def selectById(billofmaterialsid: BillofmaterialsId)(implicit c: Connection): Option[BillofmaterialsRow]
def selectByIds(billofmaterialsids: Array[BillofmaterialsId])(implicit c: Connection): List[BillofmaterialsRow]
def selectById(billofmaterialsid: Int)(implicit c: Connection): Option[BillofmaterialsRow]
def selectByIds(billofmaterialsids: Array[Int])(implicit c: Connection): List[BillofmaterialsRow]
def update(row: BillofmaterialsRow)(implicit c: Connection): Boolean
def update: UpdateBuilder[BillofmaterialsFields, BillofmaterialsRow]
def upsert(unsaved: BillofmaterialsRow)(implicit c: Connection): BillofmaterialsRow
Expand Down
Loading

0 comments on commit 5712552

Please sign in to comment.