Skip to content

Commit 2ac6dcb

Browse files
authored
Merge pull request #1665 from breml/refactor-generate-database-types
Replace ast.Package with types.Package
2 parents c1533dd + 2982872 commit 2ac6dcb

27 files changed

+680
-752
lines changed

.golangci.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ linters:
99
- revive
1010
issues:
1111
exclude-use-default: false
12+
exclude-rules:
13+
- linters:
14+
- revive
15+
source: "^//generate-database:mapper "
1216
linters-settings:
1317
gci:
1418
sections:

cmd/generate-database/README.md

Lines changed: 65 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,42 +5,64 @@
55
`generate-database` is a database statement and associated `go` function generator
66
for Incus and related projects. `generate-database` utilizes `go`'s code generation
77
directives (`//go:generate ...`) alongside go's [ast](https://pkg.go.dev/go/ast)
8-
package for parsing the syntax tree for go structs and variables. We use
9-
`generate-database` for the majority of our SQL statements and database interactions
10-
on the `go` side for consistency and predictability.
8+
and [types](https://pkg.go.dev/go/types) packages for parsing the syntax tree for
9+
go structs and variables. We use `generate-database` for the majority of our
10+
SQL statements and database interactions on the `go` side for consistency and
11+
predictability.
1112

1213
## Usage
1314

1415
### Initialization
1516

16-
Generally the first thing we will want to do for any newly generated file is to
17-
establish the command, the target file, and ensure the file has been cleared of
18-
content:
17+
#### Package global
1918

20-
```go
21-
//go:generate -command mapper generate-database db mapper -t instances.mapper.go
22-
//go:generate mapper reset -i -b "//go:build linux && cgo && !agent"
19+
Once per package, that uses `generate-database` for generation of database
20+
statements and associated `go` functions, `generate-database` needs to be invoked
21+
using the following `go:generate` instruction:
2322

23+
```go
24+
//go:generate generate-database db mapper generate
2425
```
2526

26-
This will initiate a call to `generate-database db mapper -t instances.mapper.go` on
27-
each call to the go generation directive `mapper`.
27+
This will initiate a call to `generate-database db mapper generate`,
28+
which will then search for `//generate-database:mapper` directives in the same file
29+
and process those.
30+
31+
#### File
32+
33+
Generally the first thing we will want to do for any newly generated file is to
34+
ensure the file has been cleared of content:
35+
36+
```go
37+
//generate-database:mapper target instances.mapper.go
38+
//generate-database:mapper reset -i -b "//go:build linux && cgo && !agent"
39+
```
2840

2941
### Generation Directive Arguments
3042

31-
* `//go:generate mapper stmt -e instance objects table=table_name`
43+
The generation directive aruments have the following form:
3244

33-
The `table` key can be used to override the generated table name for a specified one.
45+
`//generate-database:mapper <command> flags <kind> <args...>`
3446

47+
The following flags are available:
3548

36-
* `//go:generate mapper method -e instance Create references=Config,Device`
49+
* `--build` / `-b`: build comment to include (commands: `reset`)
50+
* `--interface` / `-i`: create interface files (commands: `reset`, `method`)
51+
* `--entity` / `-e`: database entity to generate the method or statement for (commands: `stmt`, `method`)
3752

38-
For some tables (defined below under [Additional Information](#Additional-Information) as [EntityTable](#EntityTable), the `references=<ReferenceEntity>` key can be provided with the name of
39-
a [ReferenceTable](#ReferenceTable) or [MapTable](#MapTable) struct. This directive would produce `CreateInstance` in addition to `CreateInstanceConfig` and `CreateInstanceDevices`
53+
Example:
54+
55+
* `//generate-database:mapper stmt -e instance objects table=table_name`
56+
57+
The `table` key can be used to override the generated table name for a specified one.
58+
59+
* `//generate-database:mapper method -i -e instance Create references=Config,Device`
4060

61+
For some tables (defined below under [Additional Information](#Additional-Information) as [EntityTable](#EntityTable), the `references=<ReferenceEntity>` key can be provided with the name of
62+
a [ReferenceTable](#ReferenceTable) or [MapTable](#MapTable) struct. This directive would produce `CreateInstance` in addition to `CreateInstanceConfig` and `CreateInstanceDevices`:
4163

42-
* //go:generate mapper method -i -e instance_profile Create struct=Instance
43-
* //go:generate mapper method -i -e instance_profile Create struct=Profile
64+
* `//generate-database:mapper method -i -e instance_profile Create struct=Instance`
65+
* `//generate-database:mapper method -i -e instance_profile Create struct=Profile`
4466

4567
For some tables (defined below under [Additional Information](#Additional-Information) as [AssociationTable](#AssociationTable), `method` declarations must
4668
include a `struct=<Entity>` to indicate the directionality of the function. An invocation can be called for each direction.
@@ -49,10 +71,11 @@ This would produce `CreateInstanceProfiles` and `CreateProfileInstances` respect
4971
### SQL Statement Generation
5072

5173
SQL generation supports the following SQL statement types:
74+
5275
Type | Description
5376
:--- | :----
5477
`objects` | Creates a basic SELECT statement of the form `SELECT <columns> FROM <table> ORDER BY <columns>`.
55-
`objects-by-<FIELD>-and-<FIELD>...` | Parses a pre-existing SELECT statement variable declaration of the form produced by`objects`, and appends a `WHERE` clause with the given fields located in the associated struct. Specifically looks for a variable declaration of the form 'var <entity>Objects = RegisterStmt(`SQL String`)'
78+
`objects-by-<FIELD>-and-<FIELD>...` | Parses a pre-existing SELECT statement variable declaration of the form produced by`objects`, and appends a `WHERE` clause with the given fields located in the associated struct. Specifically looks for a variable declaration of the form `var <entity>Objects = RegisterStmt("SQL String")`
5679
`create` | Creates a basic INSERT statement of the form `INSERT INTO <table> VALUES`.
5780
`create-or-replace` | Creates a basic INSERT statement of the form `INSERT OR REPLACE INTO <table> VALUES`.
5881
`delete-by-<FIELD>-and-<FIELD>...` | Creates a DELETE statement of the form `DELETE FROM <table> WHERE <constraint>` where the constraint is based on the given fields of the associated struct.
@@ -63,11 +86,11 @@ Type | Description
6386
#### Examples
6487

6588
```go
66-
//go:generate mapper stmt -e instance objects
67-
//go:generate mapper stmt -e instance objects-by-Name-and-Project
68-
//go:generate mapper stmt -e instance create
69-
//go:generate mapper stmt -e instance update
70-
//go:generate mapper stmt -e instance delete-by-Name-and-Project
89+
//generate-database:mapper stmt -e instance objects
90+
//generate-database:mapper stmt -e instance objects-by-Name-and-Project
91+
//generate-database:mapper stmt -e instance create
92+
//generate-database:mapper stmt -e instance update
93+
//generate-database:mapper stmt -e instance delete-by-Name-and-Project
7194
```
7295

7396
#### Statement Related Go Tags
@@ -90,6 +113,7 @@ Tag | Description
90113
### Go Function Generation
91114

92115
Go function generation supports the following types:
116+
93117
Type | Description
94118
:--- | :----
95119
`GetMany` | Return a slice of structs for all rows in a table matching the filter.
@@ -103,16 +127,15 @@ Type | Description
103127
`DeleteOne` | Delete exactly one row from the table.
104128
`DeleteMany` | Delete one or more rows from the table.
105129

106-
107130
```go
108-
//go:generate mapper method -i -e instance GetMany
109-
//go:generate mapper method -i -e instance GetOne
110-
//go:generate mapper method -i -e instance ID
111-
//go:generate mapper method -i -e instance Exist
112-
//go:generate mapper method -i -e instance Create
113-
//go:generate mapper method -i -e instance Update
114-
//go:generate mapper method -i -e instance DeleteOne-by-Project-and-Name
115-
//go:generate mapper method -i -e instance DeleteMany-by-Name
131+
//generate-database:mapper method -i -e instance GetMany
132+
//generate-database:mapper method -i -e instance GetOne
133+
//generate-database:mapper method -i -e instance ID
134+
//generate-database:mapper method -i -e instance Exist
135+
//generate-database:mapper method -i -e instance Create
136+
//generate-database:mapper method -i -e instance Update
137+
//generate-database:mapper method -i -e instance DeleteOne-by-Project-and-Name
138+
//generate-database:mapper method -i -e instance DeleteMany-by-Name
116139
```
117140

118141
### Additional Information
@@ -161,8 +184,8 @@ Real world invocation of these statements and functions should be done through a
161184
Example:
162185

163186
```go
164-
//go:generate mapper stmt -e device create
165-
//go:generate mapper method -e device Create
187+
//generate-database:mapper stmt -e device create
188+
//generate-database:mapper method -e device Create
166189

167190
type Device struct {
168191
ID int
@@ -172,7 +195,7 @@ type Device struct {
172195
}
173196

174197
//...
175-
//go:generate mapper method -e instance Create references=Device
198+
//generate-database:mapper method -e instance Create references=Device
176199
// This will produce a function called `CreateInstanceDevices`.
177200
```
178201

@@ -184,8 +207,8 @@ On the SQL side, this is treated exactly like a `ReferenceTable`, but on the `go
184207
Example:
185208

186209
```go
187-
//go:generate mapper stmt -e config create
188-
//go:generate mapper method -e config Create
210+
//generate-database:mapper stmt -e config create
211+
//generate-database:mapper method -e config Create
189212

190213
type Config struct {
191214
ID int
@@ -195,11 +218,12 @@ type Config struct {
195218
}
196219

197220
//...
198-
//go:generate mapper method -e instance Create references=Config
221+
//generate-database:mapper method -e instance Create references=Config
199222
// This will produce a function called `CreateInstanceConfig`, which will return a `map[string]string`.
200223
```
201224

202225
### AssociationTable
226+
203227
This is a special type of table that contains two fields of the form `<Entity>ID`, where `<Entity>` corresponds to two other structs present in the same package.
204228
This will generate code for compound tables of the form `<entity1>_<entity2>` that are generally used to associate two tables together by their IDs.
205229

@@ -209,9 +233,8 @@ An invocation can be called for each direction.
209233
Example:
210234

211235
```go
212-
213-
//go:generate mapper method -i -e instance_profile Create struct=Instance
214-
//go:generate mapper method -i -e instance_profile Create struct=Profile
236+
//generate-database:mapper method -i -e instance_profile Create struct=Instance
237+
//generate-database:mapper method -i -e instance_profile Create struct=Profile
215238

216239
type InstanceProfile struct {
217240
InstanceID int

0 commit comments

Comments
 (0)