github.com/Ali-iotechsys/sqlboiler/v4@v4.0.0-20221208124957-6aec9a5f1f71/README.md (about) 1  2 3 [](https://github.com/volatiletech/sqlboiler/blob/master/LICENSE) 4 [](https://pkg.go.dev/mod/github.com/volatiletech/sqlboiler/v4) 5 [](https://sqlboiler.from-the.cloud) 6  7 [](http://goreportcard.com/report/volatiletech/sqlboiler) 8 9 SQLBoiler is a tool to generate a Go ORM tailored to your database schema. 10 11 It is a "database-first" ORM as opposed to "code-first" (like gorm/gorp). 12 That means you must first create your database schema. Please use something 13 like [sql-migrate](https://github.com/rubenv/sql-migrate) 14 or some other migration tool to manage this part of the database's life-cycle. 15 16 # Note on versions 17 18 v1, v2, and v3 are no longer maintained. 19 20 v3 is the last GOPATH-compatible version. 21 22 v4 has no real breaking changes between v3 and itself other than Go modules 23 and is the only maintained version. Note this does not work with GOPATH 24 projects. 25 26 ## Why another ORM 27 28 While attempting to migrate a legacy Rails database, we realized how much ActiveRecord benefited us in terms of development velocity. 29 Coming over to the Go `database/sql` package after using ActiveRecord feels extremely repetitive, super long-winded and down-right boring. 30 Being Go veterans we knew the state of ORMs was shaky, and after a quick review we found what our fears confirmed. Most packages out 31 there are code-first, reflect-based and have a very weak story around relationships between models. So with that we set out with these goals: 32 33 * Work with existing databases: Don't be the tool to define the schema, that's better left to other tools. 34 * ActiveRecord-like productivity: Eliminate all sql boilerplate, have relationships as a first-class concept. 35 * Go-like feel: Work with normal structs, call functions, no hyper-magical struct tags, small interfaces. 36 * Go-like performance: [Benchmark](#benchmarks) and optimize the hot-paths, perform like hand-rolled `sql.DB` code. 37 38 We believe with SQLBoiler and our database-first code-generation approach we've been able to successfully meet all of these goals. On top 39 of that SQLBoiler also confers the following benefits: 40 41 * The models package is type safe. This means no chance of random panics due to passing in the wrong type. No need for interface{}. 42 * Our types closely correlate to your database column types. This is expanded by our extended null package which supports nearly all Go data types. 43 * A system that is easy to debug. Your ORM is tailored to your schema, the code paths should be easy to trace since it's not all buried in reflect. 44 * Auto-completion provides work-flow efficiency gains. 45 46 Table of Contents 47 ================= 48 49 * [SQLBoiler](#sqlboiler) 50 * [Why another ORM](#why-another-orm) 51 * [About SQL Boiler](#about-sql-boiler) 52 * [Features](#features) 53 * [Missing Features](#missing-features) 54 * [Supported Databases](#supported-databases) 55 * [A Small Taste](#a-small-taste) 56 * [Requirements & Pro Tips](#requirements--pro-tips) 57 * [Requirements](#requirements) 58 * [Pro Tips](#pro-tips) 59 * [Getting started](#getting-started) 60 * [Videos](#videos) 61 * [Download](#download) 62 * [Configuration](#configuration) 63 * [Initial Generation](#initial-generation) 64 * [Regeneration](#regeneration) 65 * [Controlling Generation](#controlling-generation) 66 * [Aliases](#aliases) 67 * [Types](#types) 68 * [Imports](#imports) 69 * [Templates](#templates) 70 * [Extending Generated Models](#extending-generated-models) 71 * [Diagnosing Problems](#diagnosing-problems) 72 * [Features & Examples](#features--examples) 73 * [Automatic CreatedAt/UpdatedAt](#automatic-createdatupdatedat) 74 * [Skipping Automatic Timestamps](#skipping-automatic-timestamps) 75 * [Overriding Automatic Timestamps](#overriding-automatic-timestamps) 76 * [Query Building](#query-building) 77 * [Query Mod System](#query-mod-system) 78 * [Function Variations](#function-variations) 79 * [Finishers](#finishers) 80 * [Raw Query](#raw-query) 81 * [Binding](#binding) 82 * [Relationships](#relationships) 83 * [Hooks](#hooks) 84 * [Skipping Hooks](#skipping-hooks) 85 * [Transactions](#transactions) 86 * [Debug Logging](#debug-logging) 87 * [Select](#select) 88 * [Find](#find) 89 * [Insert](#insert) 90 * [Update](#update) 91 * [Delete](#delete) 92 * [Upsert](#upsert) 93 * [Reload](#reload) 94 * [Exists](#exists) 95 * [Enums](#enums) 96 * [Constants](#constants) 97 * [FAQ](#faq) 98 * [Won't compiling models for a huge database be very slow?](#wont-compiling-models-for-a-huge-database-be-very-slow) 99 * [Missing imports for generated package](#missing-imports-for-generated-package) 100 * [How should I handle multiple schemas](#how-should-i-handle-multiple-schemas) 101 * [How do I use the types.BytesArray for Postgres bytea arrays?](#how-do-i-use-typesbytesarray-for-postgres-bytea-arrays) 102 * [Why aren't my time.Time or null.Time fields working in MySQL?](#why-arent-my-timetime-or-nulltime-fields-working-in-mysql) 103 * [Where is the homepage?](#where-is-the-homepage) 104 * [Why are the auto-generated tests failing?](#why-are-the-auto-generated-tests-failing) 105 * [Benchmarks](#benchmarks) 106 107 ## About SQL Boiler 108 109 ### Features 110 111 - Full model generation 112 - Extremely fast code generation 113 - High performance through generation & intelligent caching 114 - Uses boil.Executor (simple interface, sql.DB, sqlx.DB etc. compatible) 115 - Uses context.Context 116 - Easy workflow (models can always be regenerated, full auto-complete) 117 - Strongly typed querying (usually no converting or binding to pointers) 118 - Hooks (Before/After Create/Select/Update/Delete/Upsert) 119 - Automatic CreatedAt/UpdatedAt 120 - Automatic DeletedAt 121 - Table and column whitelist/blacklist 122 - Relationships/Associations 123 - Eager loading (recursive) 124 - Custom struct tags 125 - Transactions 126 - Raw SQL fallback 127 - Compatibility tests (Run against your own DB schema) 128 - Debug logging 129 - Basic multiple schema support (no cross-schema support) 130 - 1d arrays, json, hstore & more 131 - Enum types 132 - Out of band driver support 133 - Support for database views 134 - Supports generated/computed columns 135 136 ### Missing features 137 138 - Multi-column foreign key support 139 - Materialized view support 140 141 ### Supported Databases 142 143 | Database | Driver Location | 144 | ----------------- | --------------- | 145 | PostgreSQL | [https://github.com/volatiletech/sqlboiler/v4/drivers/sqlboiler-psql](drivers/sqlboiler-psql) 146 | MySQL | [https://github.com/volatiletech/sqlboiler/v4/drivers/sqlboiler-mysql](drivers/sqlboiler-mysql) 147 | MSSQLServer 2012+ | [https://github.com/volatiletech/sqlboiler/v4/drivers/sqlboiler-mssql](drivers/sqlboiler-mssql) 148 | SQLite3 | [https://github.com/volatiletech/sqlboiler/v4/drivers/sqlboiler-sqlite3](drivers/sqlboiler-sqlite3) 149 | CockroachDB | https://github.com/glerchundi/sqlboiler-crdb 150 151 **Note:** SQLBoiler supports out of band driver support so you can make your own 152 153 We are seeking contributors for other database engines. 154 155 ### A Small Taste 156 157 For a comprehensive list of available operations and examples please see [Features & Examples](#features--examples). 158 159 ```go 160 import ( 161 // Import this so we don't have to use qm.Limit etc. 162 . "github.com/volatiletech/sqlboiler/v4/queries/qm" 163 ) 164 165 // Open handle to database like normal 166 db, err := sql.Open("postgres", "dbname=fun user=abc") 167 if err != nil { 168 return err 169 } 170 171 // If you don't want to pass in db to all generated methods 172 // you can use boil.SetDB to set it globally, and then use 173 // the G variant methods like so (--add-global-variants to enable) 174 boil.SetDB(db) 175 users, err := models.Users().AllG(ctx) 176 177 // Query all users 178 users, err := models.Users().All(ctx, db) 179 180 // Panic-able if you like to code that way (--add-panic-variants to enable) 181 users := models.Users().AllP(db) 182 183 // More complex query 184 users, err := models.Users(Where("age > ?", 30), Limit(5), Offset(6)).All(ctx, db) 185 186 // Ultra complex query 187 users, err := models.Users( 188 Select("id", "name"), 189 InnerJoin("credit_cards c on c.user_id = users.id"), 190 Where("age > ?", 30), 191 AndIn("c.kind in ?", "visa", "mastercard"), 192 Or("email like ?", `%aol.com%`), 193 GroupBy("id", "name"), 194 Having("count(c.id) > ?", 2), 195 Limit(5), 196 Offset(6), 197 ).All(ctx, db) 198 199 // Use any "boil.Executor" implementation (*sql.DB, *sql.Tx, data-dog mock db) 200 // for any query. 201 tx, err := db.BeginTx(ctx, nil) 202 if err != nil { 203 return err 204 } 205 users, err := models.Users().All(ctx, tx) 206 207 // Relationships 208 user, err := models.Users().One(ctx, db) 209 if err != nil { 210 return err 211 } 212 movies, err := user.FavoriteMovies().All(ctx, db) 213 214 // Eager loading 215 users, err := models.Users(Load("FavoriteMovies")).All(ctx, db) 216 if err != nil { 217 return err 218 } 219 fmt.Println(len(users.R.FavoriteMovies)) 220 ``` 221 222 ## Requirements & Pro Tips 223 224 ### Requirements 225 226 * Go 1.13, older Go versions are not supported. 227 * Join tables should use a *composite primary key*. 228 * For join tables to be used transparently for relationships your join table must have 229 a *composite primary key* that encompasses both foreign table foreign keys and 230 no other columns in the table. For example, on a join table named 231 `user_videos` you should have: `primary key(user_id, video_id)`, with both 232 `user_id` and `video_id` being foreign key columns to the users and videos 233 tables respectively and there are no other columns on this table. 234 * MySQL 5.6.30 minimum; ssl-mode option is not supported for earlier versions. 235 * For MySQL if using the `github.com/go-sql-driver/mysql` driver, please activate 236 [time.Time parsing](https://github.com/go-sql-driver/mysql#timetime-support) when making your 237 MySQL database connection. SQLBoiler uses `time.Time` and `null.Time` to represent time in 238 it's models and without this enabled any models with `DATE`/`DATETIME` columns will not work. 239 240 ### Pro Tips 241 242 * SQLBoiler generates type safe identifiers for table names, table column names, 243 a table's relationship names and type-safe where clauses. You should use these 244 instead of strings due to the ability to catch more errors at compile time 245 when your database schema changes. See [Constants](#constants) for details. 246 * It's highly recommended to use transactions where sqlboiler will be doing 247 multiple database calls (relationship setops with insertions for example) for 248 both performance and data integrity. 249 * Foreign key column names should end with `_id`. 250 * Foreign key column names in the format `x_id` will generate clearer method names. 251 It is advisable to use this naming convention whenever it makes sense for your database schema. 252 * If you never plan on using the hooks functionality you can disable generation of this 253 feature using the `--no-hooks` flag. This will save you some binary size. 254 255 ## Getting started 256 257 #### Videos 258 259 If you like learning via a video medium, sqlboiler has a number of screencasts 260 available. 261 262 *NOTE:* These videos predate modules (v4), the installation/import paths will be 263 different though everything else should remain similar. 264 265 [SQLBoiler: Getting Started](https://www.youtube.com/watch?v=y5utRS9axfg) 266 267 [SQLBoiler: What's New in v3](https://www.youtube.com/watch?v=-B-OPsYRZJA) 268 269 [SQLBoiler: Advanced Queries and Relationships](https://www.youtube.com/watch?v=iiJuM9NR8No) 270 271 [Old (v2): SQLBoiler Screencast #1: How to get started](https://www.youtube.com/watch?v=fKmRemtmi0Y) 272 273 #### Download 274 275 First you have to install the code generator binaries. There's the main binary 276 and then a separate driver binary (select the right one for your database). 277 278 Be very careful when installing, there's confusion in the Go ecosystem and 279 knowing what are the right commands to run for which Go version can be tricky. 280 Ensure you don't forget any /v suffixes or you'll end up on an old version. 281 282 ```shell 283 # Go 1.16 and above: 284 go install github.com/volatiletech/sqlboiler/v4@latest 285 go install github.com/volatiletech/sqlboiler/v4/drivers/sqlboiler-psql@latest 286 287 # Go 1.15 and below: 288 # Install sqlboiler v4 and the postgresql driver (mysql, mssql, sqlite3 also available) 289 # NOTE: DO NOT run this inside another Go module (like your project) as it will 290 # pollute your go.mod with a bunch of stuff you don't want and your binary 291 # will not get installed. 292 GO111MODULE=on go get -u -t github.com/volatiletech/sqlboiler/v4 293 GO111MODULE=on go get github.com/volatiletech/sqlboiler/v4/drivers/sqlboiler-psql 294 ``` 295 296 To install `sqlboiler` as a dependency in your project use the commands below 297 inside of your go module's directory tree. This will install the dependencies 298 into your `go.mod` file at the correct version. 299 300 ```shell 301 # Do not forget the trailing /v4 and /v8 in the following commands 302 go get github.com/volatiletech/sqlboiler/v4 303 # Assuming you're going to use the null package for its additional null types 304 go get github.com/volatiletech/null/v8 305 ``` 306 307 #### Configuration 308 309 Create a configuration file. Because the project uses 310 [viper](https://github.com/spf13/viper), TOML, JSON and YAML are all usable 311 but only TOML is supported. Environment variables are also able to be used. 312 313 The configuration file should be named `sqlboiler.toml` and is searched for in 314 the following directories in this order: 315 316 - `./` 317 - `$XDG_CONFIG_HOME/sqlboiler/` 318 - `$HOME/.config/sqlboiler/` 319 320 We will assume TOML for the rest of the documentation. 321 322 ##### Database Driver Configuration 323 324 The configuration for a specific driver (in these examples we'll use `psql`) 325 must all be prefixed by the driver name. You must use a configuration file or 326 environment variables for configuring the database driver; there are no 327 command-line options for providing driver-specific configuration. 328 329 In the configuration file for postgresql for example you would do: 330 331 ```toml 332 [psql] 333 dbname = "your_database_name" 334 ``` 335 336 When you use an environment variable it must also be prefixed by the driver 337 name: 338 339 ```sh 340 PSQL_DBNAME="your_database_name" 341 ``` 342 343 The values that exist for the drivers: 344 345 | Name | Required | Postgres Default | MySQL Default | MSSQL Default | 346 | ---- | -------- | ---------------- | ------------- | ------------- | 347 | schema | no | "public" | none | "dbo" | 348 | dbname | yes | none | none | none | 349 | host | yes | none | none | none | 350 | port | no | 5432 | 3306 | 1433 | 351 | user | yes | none | none | none | 352 | pass | no | none | none | none | 353 | sslmode | no | "require" | "true" | "true" | 354 | whitelist | no | [] | [] | [] | 355 | blacklist | no | [] | [] | [] | 356 357 Example of whitelist/blacklist: 358 359 ```toml 360 [psql] 361 # Removes migrations table, the name column from the addresses table, and 362 # secret_col of any table from being generated. Foreign keys that reference tables 363 # or columns that are no longer generated because of whitelists or blacklists may 364 # cause problems. 365 blacklist = ["migrations", "addresses.name", "*.secret_col"] 366 ``` 367 368 ##### Generic config options 369 370 You can also pass in these top level configuration values if you would prefer 371 not to pass them through the command line or environment variables: 372 373 | Name | Defaults | 374 | ------------------- | --------- | 375 | pkgname | "models" | 376 | output | "models" | 377 | tag | [] | 378 | debug | false | 379 | add-global-variants | false | 380 | add-panic-variants | false | 381 | add-enum-types | false | 382 | enum-null-prefix | "Null" | 383 | no-context | false | 384 | no-hooks | false | 385 | no-tests | false | 386 | no-auto-timestamps | false | 387 | no-rows-affected | false | 388 | no-driver-templates | false | 389 | tag-ignore | [] | 390 391 ##### Full Example 392 393 ```toml 394 output = "my_models" 395 wipe = true 396 no-tests = true 397 add-enum-types = true 398 399 [psql] 400 dbname = "dbname" 401 host = "localhost" 402 port = 5432 403 user = "dbusername" 404 pass = "dbpassword" 405 schema = "myschema" 406 blacklist = ["migrations", "other"] 407 408 [mysql] 409 dbname = "dbname" 410 host = "localhost" 411 port = 3306 412 user = "dbusername" 413 pass = "dbpassword" 414 sslmode = "false" 415 416 [mssql] 417 dbname = "dbname" 418 host = "localhost" 419 port = 1433 420 user = "dbusername" 421 pass = "dbpassword" 422 sslmode = "disable" 423 schema = "notdbo" 424 ``` 425 426 #### Initial Generation 427 428 After creating a configuration file that points at the database we want to 429 generate models for, we can invoke the sqlboiler command line utility. 430 431 ```text 432 SQL Boiler generates a Go ORM from template files, tailored to your database schema. 433 Complete documentation is available at http://github.com/volatiletech/sqlboiler 434 435 Usage: 436 sqlboiler [flags] <driver> 437 438 Examples: 439 sqlboiler psql 440 441 Flags: 442 --add-global-variants Enable generation for global variants 443 --add-panic-variants Enable generation for panic variants 444 --add-soft-deletes Enable soft deletion by updating deleted_at timestamp 445 --add-enum-types Enable generation of types for enums 446 --enum-null-prefix Name prefix of nullable enum types (default "Null") 447 -c, --config string Filename of config file to override default lookup 448 -d, --debug Debug mode prints stack traces on error 449 -h, --help help for sqlboiler 450 --no-auto-timestamps Disable automatic timestamps for created_at/updated_at 451 --no-back-referencing Disable back referencing in the loaded relationship structs 452 --no-context Disable context.Context usage in the generated code 453 --no-driver-templates Disable parsing of templates defined by the database driver 454 --no-hooks Disable hooks feature for your models 455 --no-rows-affected Disable rows affected in the generated API 456 --no-tests Disable generated go test files 457 -o, --output string The name of the folder to output to (default "models") 458 -p, --pkgname string The name you wish to assign to your generated package (default "models") 459 --struct-tag-casing string Decides the casing for go structure tag names. camel, title, alias or snake (default "snake") 460 -t, --tag strings Struct tags to be included on your models in addition to json, yaml, toml 461 --tag-ignore strings List of column names that should have tags values set to '-' (ignored during parsing) 462 --templates strings A templates directory, overrides the embedded template folders in sqlboiler 463 --version Print the version 464 --wipe Delete the output folder (rm -rf) before generation to ensure sanity 465 ``` 466 467 Follow the steps below to do some basic model generation. Once you've generated 468 your models, you can run the compatibility tests which will exercise the entirety 469 of the generated code. This way you can ensure that your database is compatible 470 with SQLBoiler. If you find there are some failing tests, please check the 471 [Diagnosing Problems](#diagnosing-problems) section. 472 473 ```sh 474 # Generate our models and exclude the migrations table 475 # When passing 'psql' here, it looks for a binary called 476 # 'sqlboiler-psql' in your CWD and PATH. You can also pass 477 # an absolute path to a driver if you desire. 478 sqlboiler psql 479 480 # Run the generated tests 481 go test ./models 482 ``` 483 484 *Note: No `mysqldump` or `pg_dump` equivalent for Microsoft SQL Server, so generated tests must be supplemented by `tables_schema.sql` with `CREATE TABLE ...` queries* 485 486 You can use `go generate` for SQLBoiler if you want to to make it easy to 487 run the command for your application: 488 489 ```go 490 //go:generate sqlboiler --flags-go-here psql 491 ``` 492 493 It's important to not modify anything in the output folder, which brings us to 494 the next topic: regeneration. 495 496 #### Regeneration 497 498 When regenerating the models it's recommended that you completely delete the 499 generated directory in a build script or use the `--wipe` flag in SQLBoiler. 500 The reasons for this are that sqlboiler doesn't try to diff your files in any 501 smart way, it simply writes the files it's going to write whether they're there 502 or not and doesn't delete any files that were added by you or previous runs of 503 SQLBoiler. In the best case this can cause compilation errors, in the worst case 504 this may leave extraneous and unusable code that was generated against tables 505 that are no longer in the database. 506 507 The bottom line is that this tool should always produce the same result from 508 the same source. And the intention is to always regenerate from a pure state. 509 The only reason the `--wipe` flag isn't defaulted to on is because we don't 510 like programs that `rm -rf` things on the filesystem without being asked to. 511 512 #### Controlling Generation 513 514 The templates get executed in a specific way each time. There's a variety of 515 configuration options on the command line/config file that can control what 516 features are turned on or off. 517 518 In addition to the command line flags there are a few features that are only 519 available via the config file and can use some explanation. 520 521 ##### Aliases 522 523 In sqlboiler, names are automatically generated for you. If you name your 524 database entities properly you will likely have descriptive names generated in 525 the end. However in the case where the names in your database are bad AND 526 unchangeable, or sqlboiler's inference doesn't understand the names you do have 527 (even though they are good and correct) you can use aliases to change the name 528 of your tables, columns and relationships in the generated Go code. 529 530 *Note: It is not required to provide all parts of all names. Anything left out 531 will be inferred as it was in the past.* 532 533 ```toml 534 # Although team_names works fine without configuration, we use it here for illustrative purposes 535 [aliases.tables.team_names] 536 up_plural = "TeamNames" 537 up_singular = "TeamName" 538 down_plural = "teamNames" 539 down_singular = "teamName" 540 541 # Columns can also be aliased. 542 [aliases.tables.team_names.columns] 543 team_name = "OurTeamName" 544 ``` 545 546 When creating aliases for relationships, it's important to know how sqlboiler 547 names relationships. For a given table the foreign key name is used as a unique 548 identifier to refer to a given relationship. If you are going to be aliasing 549 relationships it's **highly recommended** that you name your foreign keys 550 explicitly in your database or the auto-generated names could one day 551 change/break your aliases. 552 553 Each relationship has a **local** and a **foreign** function name. The function name will 554 be inserted into your generated code as a function to retrieve relationship data as 555 well as refer to the relationship in a few other places. **local** means "the function name 556 that refers to the table with the foreign key on it" and conversely **foreign** 557 means "the function that refers to the table the foreign key points to". 558 559 For example - let's have a `videos -> users` many to one relationship that looks 560 like this: 561 562 ```text 563 The tables and their columns: 564 565 | videos | users | 566 |---------|-------| 567 | user_id | id | 568 569 Our foreign key: 570 videos_user_id_fkey: videos.user_id -> users.id 571 ``` 572 573 In this example `local` (how we refer to the table with the foreign key) is 574 going to be inferred as `Videos`. We're going to override that below to be 575 `AuthoredVideos`. 576 577 Conversely `foreign` (how we refer to the table the foreign key points to) is 578 going to be inferred as `User`, which we'd like to rename to `Author` to suit 579 our domain language a bit better. 580 581 With the configuration snippet below we can use the following relationship 582 helper functions off of the respective models: `video.Author` and 583 `user.AuthoredVideos` which make a bit more sense than the inferred names when 584 we see it in the code for our domain. Note the use of the foreign key name to 585 refer to the relationship in the configuration key. 586 587 ```toml 588 [aliases.tables.videos.relationships.videos_author_id_fkey] 589 # The local side would originally be inferred as AuthorVideos, which 590 # is probably good enough to not want to mess around with this feature, avoid it where possible. 591 local = "AuthoredVideos" 592 # Even if left unspecified, the foreign side would have been inferred correctly 593 # due to the proper naming of the foreign key column. 594 foreign = "Author" 595 ``` 596 597 In a many-to-many relationship it's a bit more complicated. Let's look at an 598 example relationship between `videos <-> tags` with a join table in the middle. 599 Imagine if the join table didn't exist, and instead both of the id columns in 600 the join table were slapped on to the tables themselves. You'd have 601 `videos.tag_id` and `tags.video_id`. Using a similar method to the above (local 602 is the name with which we refer to the side that has the foreign key) 603 we can rename the relationships. To change `Videos.Tags` to `Videos.Rags` 604 we can use the example below. 605 606 Keep in mind that naming ONE side of the many-to-many relationship is sufficient 607 as the other side will be automatically mirrored, though you can specify both if 608 you so choose. 609 610 ```toml 611 [aliases.tables.video_tags.relationships.fk_video_id] 612 local = "Rags" 613 foreign = "Videos" 614 ``` 615 616 The above definition will specify `Rags` as the name of the property with which 617 a given `Video` entity will be able to access all of it's tags. If we look the 618 other way around - a single `Tag` entity will refer to all videos that have that 619 specific tag with the `Videos` property. 620 621 There is an alternative syntax available for those who are challenged by the key 622 syntax of toml or challenged by viper lowercasing all of your keys. Instead of 623 using a regular table in toml, use an array of tables, and add a name field to 624 each object. The only one that changes past that is columns, which now has to 625 have a new field called `alias`. 626 627 ```toml 628 [[aliases.tables]] 629 name = "team_names" 630 up_plural = "TeamNames" 631 up_singular = "TeamName" 632 down_plural = "teamNames" 633 down_singular = "teamName" 634 635 [[aliases.tables.columns]] 636 name = "team_name" 637 alias = "OurTeamName" 638 639 [[aliases.tables.relationships]] 640 name = "fk_video_id" 641 local = "Rags" 642 foreign = "Videos" 643 ``` 644 645 ##### Inflections 646 647 With inflections, you can control the rules sqlboiler uses to generates singular/plural variants. This is useful if a certain word or suffix is used multiple times and you do not wnat to create aliases for every instance. 648 649 ```toml 650 [inflections.plural] 651 # Rules to convert a suffix to its plural form 652 ium = "ia" 653 654 [inflections.plural_exact] 655 # Rules to convert an exact word to its plural form 656 stadium = "stadia" 657 658 [inflections.singular] 659 # Rules to convert a suffix to its singular form 660 ia = "ium" 661 662 [inflections.singular_exact] 663 # Rules to convert an exact word to its singular form 664 stadia = "stadium" 665 666 [inflections.irregular] 667 # The singular -> plural mapping of an exact word that doen't follow conventional rules 668 radius = "radii" 669 ``` 670 671 ##### Types 672 673 There exists the ability to override types that the driver has inferred. 674 The way to accomplish this is through the config file. 675 676 ```toml 677 [[types]] 678 # The match is a drivers.Column struct, and matches on almost all fields. 679 # Notable exception for the unique bool. Matches are done 680 # with "logical and" meaning it must match all specified matchers. 681 # Boolean values are only checked if all the string specifiers match first, 682 # and they must always match. 683 # 684 # Not shown here: db_type is the database type and a very useful matcher 685 # We can also whitelist tables for this replace by adding to the types.match: 686 # tables = ['users', 'videos'] 687 # 688 # Note there is precedence for types.match, more specific things should appear 689 # further down in the config as once a matching rule is found it is executed 690 # immediately. 691 [types.match] 692 type = "null.String" 693 nullable = true 694 695 # The replace is what we replace the strings with. You cannot modify any 696 # boolean values in here. But we could change the Go type (the most useful thing) 697 # or the DBType or FullDBType etc. if for some reason we needed to. 698 [types.replace] 699 type = "mynull.String" 700 701 # These imports specified here overwrite the definition of the type's "based_on_type" 702 # list. The type entry that is replaced is the replaced type's "type" field. 703 # In the above example it would add an entry for mynull.String, if we did not 704 # change the type in our replacement, it would overwrite the null.String entry. 705 [types.imports] 706 third_party = ['"github.com/me/mynull"'] 707 ``` 708 709 ##### Imports 710 711 Imports are overridable by the user. This can be used in conjunction with 712 replacing the templates for extreme cases. Typically this should be avoided. 713 714 Note that specifying any section of the imports completely overwrites that 715 section. It's also true that the driver can still specify imports and those 716 will be merged in to what is provided here. 717 718 ```toml 719 [imports.all] 720 standard = ['"context"'] 721 third_party = ['"github.com/my/package"'] 722 723 # Changes imports for the boil_queries file 724 [imports.singleton."boil_queries"] 725 standard = ['"context"'] 726 third_party = ['"github.com/my/package"'] 727 728 # Same syntax as all 729 [imports.test] 730 731 # Same syntax as singleton 732 [imports.test_singleton] 733 734 # Changes imports when a model contains null.Int32 735 [imports.based_on_type.string] 736 standard = ['"context"'] 737 third_party = ['"github.com/my/package"'] 738 ``` 739 740 When defining maps it's possible to use an alternative syntax since 741 viper automatically lowercases all configuration keys (same as aliases). 742 743 ```toml 744 [[imports.singleton]] 745 name = "boil_queries" 746 third_party = ['"github.com/my/package"'] 747 748 [[imports.based_on_type]] 749 name = "null.Int64" 750 third_party = ['"github.com/my/int64"'] 751 ``` 752 753 ##### Templates 754 755 In advanced scenarios it may be desirable to generate additional files that are not go code. 756 You can accomplish this by using the `--templates` flag to specify **all** the directories you 757 wish to generate code for. With this flag you specify root directories, that is top-level container 758 directories. 759 760 If root directories have a `_test` suffix in the name, this folder is considered a folder 761 full of templates for testing only and will be omitted when `--no-tests` is specified and 762 its templates will be generated into files with a `_test` suffix. 763 764 Each root directory is recursively walked. Each template found will be merged into table_name.ext 765 where ext is defined by the shared extension of the templates. The directory structure is preserved 766 with the exception of singletons. 767 768 For files that should not be generated for each model, you can use a `singleton` directory inside 769 the directory where the singleton file should be generated. This will make sure that the file is 770 only generated once. 771 772 Here's an example: 773 774 ```text 775 templates/ 776 ├── 00_struct.go.tpl # Merged into output_dir/table_name.go 777 ├── 00_struct.js.tpl # Merged into output_dir/table_name.js 778 ├── singleton 779 │ └── boil_queries.go.tpl # Rendered as output_dir/boil_queries.go 780 └── js 781 ├── jsmodel.js.tpl # Merged into output_dir/js/table_name.js 782 └── singleton 783 └── jssingle.js.tpl # Merged into output_dir/js/jssingle.js 784 ``` 785 786 The output files of which would be: 787 ``` 788 output_dir/ 789 ├── boil_queries.go 790 ├── table_name.go 791 ├── table_name.js 792 └── js 793 ├── table_name.js 794 └── jssingle.js 795 ``` 796 797 **Note**: Because the `--templates` flag overrides the embedded templates of `sqlboiler`, if you still 798 wish to generate the default templates it's recommended that you include the path to sqlboiler's templates 799 as well. 800 801 ```toml 802 templates = [ 803 "/path/to/sqlboiler/templates", 804 "/path/to/sqlboiler/templates_test", 805 "/path/to/your_project/more_templates" 806 ] 807 ``` 808 809 #### Extending generated models 810 811 There will probably come a time when you want to extend the generated models 812 with some kinds of helper functions. A general guideline is to put your 813 extension functions into a separate package so that your functions aren't 814 accidentally deleted when regenerating. Past that there are 3 main ways to 815 extend the models, the first way is the most desirable: 816 817 **Method 1: Simple Functions** 818 819 ```go 820 // Package modext is for SQLBoiler helper methods 821 package modext 822 823 // UserFirstTimeSetup is an extension of the user model. 824 func UserFirstTimeSetup(ctx context.Context, db *sql.DB, u *models.User) error { ... } 825 ``` 826 827 Code organization is accomplished by using multiple files, and everything 828 is passed as a parameter so these kinds of methods are very easy to test. 829 830 Calling code is also very straightforward: 831 832 ```go 833 user, err := Users().One(ctx, db) 834 // elided error check 835 836 err = modext.UserFirstTimeSetup(ctx, db, user) 837 // elided error check 838 ``` 839 840 **Method 2: Empty struct methods** 841 842 The above is the best way to code extensions for SQLBoiler, however there may 843 be times when the number of methods grows too large and code completion is 844 not as helpful anymore. In these cases you may consider structuring the code 845 like this: 846 847 ```go 848 // Package modext is for SQLBoiler helper methods 849 package modext 850 851 type users struct {} 852 853 var Users = users{} 854 855 // FirstTimeSetup is an extension of the user model. 856 func (users) FirstTimeSetup(ctx context.Context, db *sql.DB, u *models.User) error { ... } 857 ``` 858 859 Calling code then looks a little bit different: 860 861 ```go 862 user, err := Users().One(ctx, db) 863 // elided error check 864 865 err = modext.Users.FirstTimeSetup(ctx, db, user) 866 // elided error check 867 ``` 868 869 This is almost identical to the method above, but gives slight amounts more 870 organization at virtually no cost at runtime. It is however not as desirable 871 as the first method since it does have some runtime cost and doesn't offer that 872 much benefit over it. 873 874 **Method 3: Embedding** 875 876 This pattern is not for the faint of heart, what it provides in benefits it 877 more than makes up for in downsides. It's possible to embed the SQLBoiler 878 structs inside your own to enhance them. However it's subject to easy breakages 879 and a dependency on these additional objects. It can also introduce 880 inconsistencies as some objects may have no extended functionality and therefore 881 have no reason to be embedded so you either have to have a struct for each 882 generated struct even if it's empty, or have inconsistencies, some places where 883 you use the enhanced model, and some where you do not. 884 885 ```go 886 user, err := Users().One(ctx, db) 887 // elided error check 888 889 enhUser := modext.User{user} 890 err = ehnUser.FirstTimeSetup(ctx, db) 891 // elided error check 892 ``` 893 894 I don't recommend this pattern, but included it so that people know it's an 895 option and also know the problems with it. 896 897 ## Diagnosing Problems 898 899 The most common causes of problems and panics are: 900 901 - Forgetting to exclude tables you do not want included in your generation, like migration tables. 902 - Tables without a primary key. All tables require one. 903 - Forgetting to put foreign key constraints on your columns that reference other tables. 904 - The compatibility tests require privileges to create a database for testing purposes, ensure the user 905 supplied in your `sqlboiler.toml` config has adequate privileges. 906 - A nil or closed database handle. Ensure your passed in `boil.Executor` is not nil. 907 - If you decide to use the `G` variant of functions instead, make sure you've initialized your 908 global database handle using `boil.SetDB()`. 909 - Naming collisions, if the code fails to compile because there are naming collisions, look at the 910 [aliasing](#aliases) feature. 911 - Race conditions in tests or when using global variable models and using 912 relationship set helpers in multiple goroutines. Note that Set/Add/Remove 913 relationship helpers modify their input parameters to maintain parity between 914 the `.R` struct relationships and the database foreign keys but this can 915 produce subtle race conditions. Test for this using the `-race` flag on the 916 go tool. 917 - A field not being inserted (usually a default true boolean), `boil.Infer` looks at the zero 918 value of your Go type (it doesn't care what the default value in the database is) to determine 919 if it should insert your field or not. In the case of a default true boolean value, when you 920 want to set it to false; you set that in the struct but that's the zero value for the bool 921 field in Go so sqlboiler assumes you do not want to insert that field and you want the default 922 value from the database. Use a whitelist/greylist to add that field to the list of fields 923 to insert. 924 - decimal library showing errors like: `pq: encode: unknown type types.NullDecimal` 925 is a result of a too-new and broken version of the github.com/ericlargergren/decimal 926 package, use the following version in your go.mod: 927 github.com/ericlagergren/decimal v0.0.0-20181231230500-73749d4874d5 928 929 For errors with other causes, it may be simple to debug yourself by looking at the generated code. 930 Setting `boil.DebugMode` to `true` can help with this. You can change the output using `boil.DebugWriter` (defaults to `os.Stdout`). 931 932 If you're still stuck and/or you think you've found a bug, feel free to leave an issue and we'll do our best to help you. 933 934 ## Features & Examples 935 936 Most examples in this section will be demonstrated using the following Postgres schema, structs and variables: 937 938 ```sql 939 CREATE TABLE pilots ( 940 id integer NOT NULL, 941 name text NOT NULL 942 ); 943 944 ALTER TABLE pilots ADD CONSTRAINT pilot_pkey PRIMARY KEY (id); 945 946 CREATE TABLE jets ( 947 id integer NOT NULL, 948 pilot_id integer NOT NULL, 949 age integer NOT NULL, 950 name text NOT NULL, 951 color text NOT NULL 952 ); 953 954 ALTER TABLE jets ADD CONSTRAINT jet_pkey PRIMARY KEY (id); 955 ALTER TABLE jets ADD CONSTRAINT jet_pilots_fkey FOREIGN KEY (pilot_id) REFERENCES pilots(id); 956 957 CREATE TABLE languages ( 958 id integer NOT NULL, 959 language text NOT NULL 960 ); 961 962 ALTER TABLE languages ADD CONSTRAINT language_pkey PRIMARY KEY (id); 963 964 -- Join table 965 CREATE TABLE pilot_languages ( 966 pilot_id integer NOT NULL, 967 language_id integer NOT NULL 968 ); 969 970 -- Composite primary key 971 ALTER TABLE pilot_languages ADD CONSTRAINT pilot_language_pkey PRIMARY KEY (pilot_id, language_id); 972 ALTER TABLE pilot_languages ADD CONSTRAINT pilot_language_pilots_fkey FOREIGN KEY (pilot_id) REFERENCES pilots(id); 973 ALTER TABLE pilot_languages ADD CONSTRAINT pilot_language_languages_fkey FOREIGN KEY (language_id) REFERENCES languages(id); 974 ``` 975 976 The generated model structs for this schema look like the following. Note that we've included the relationship 977 structs as well so you can see how it all pieces together: 978 979 ```go 980 type Pilot struct { 981 ID int `boil:"id" json:"id" toml:"id" yaml:"id"` 982 Name string `boil:"name" json:"name" toml:"name" yaml:"name"` 983 984 R *pilotR `boil:"-" json:"-" toml:"-" yaml:"-"` 985 L pilotR `boil:"-" json:"-" toml:"-" yaml:"-"` 986 } 987 988 type pilotR struct { 989 Languages LanguageSlice 990 Jets JetSlice 991 } 992 993 type Jet struct { 994 ID int `boil:"id" json:"id" toml:"id" yaml:"id"` 995 PilotID int `boil:"pilot_id" json:"pilot_id" toml:"pilot_id" yaml:"pilot_id"` 996 Age int `boil:"age" json:"age" toml:"age" yaml:"age"` 997 Name string `boil:"name" json:"name" toml:"name" yaml:"name"` 998 Color string `boil:"color" json:"color" toml:"color" yaml:"color"` 999 1000 R *jetR `boil:"-" json:"-" toml:"-" yaml:"-"` 1001 L jetR `boil:"-" json:"-" toml:"-" yaml:"-"` 1002 } 1003 1004 type jetR struct { 1005 Pilot *Pilot 1006 } 1007 1008 type Language struct { 1009 ID int `boil:"id" json:"id" toml:"id" yaml:"id"` 1010 Language string `boil:"language" json:"language" toml:"language" yaml:"language"` 1011 1012 R *languageR `boil:"-" json:"-" toml:"-" yaml:"-"` 1013 L languageR `boil:"-" json:"-" toml:"-" yaml:"-"` 1014 } 1015 1016 type languageR struct { 1017 Pilots PilotSlice 1018 } 1019 ``` 1020 1021 ```go 1022 // Open handle to database like normal 1023 db, err := sql.Open("postgres", "dbname=fun user=abc") 1024 if err != nil { 1025 return err 1026 } 1027 ``` 1028 1029 ### Automatic CreatedAt/UpdatedAt 1030 1031 If your generated SQLBoiler models package can find columns with the 1032 names `created_at` or `updated_at` it will automatically set them 1033 to `time.Now()` in your database, and update your object appropriately. 1034 To disable this feature use `--no-auto-timestamps`. 1035 1036 Note: You can set the timezone for this feature by calling `boil.SetLocation()` 1037 1038 #### Customizing the timestamp columns 1039 1040 Set the `auto-columns` map in your configuration file 1041 1042 ```toml 1043 [auto-columns] 1044 created = "createdAt" 1045 updated = "updatedAt" 1046 ``` 1047 1048 #### Skipping Automatic Timestamps 1049 1050 If for a given query you do not want timestamp columns to be re-computed prior 1051 to an insert or update then you can use `boil.SkipTimestamps` on the context you 1052 pass in to the query to prevent them from being updated. 1053 1054 Keep in mind this has no effect on whether or not the column is included in the 1055 insert/update, it simply stops them from being set to `time.Now()` in the struct 1056 before being sent to the database (if they were going to be sent). 1057 1058 #### Overriding Automatic Timestamps 1059 1060 * **Insert** 1061 * Timestamps for both `updated_at` and `created_at` that are zero values will be set automatically. 1062 * To set the timestamp to null, set `Valid` to false and `Time` to a non-zero value. 1063 This is somewhat of a work around until we can devise a better solution in a later version. 1064 * **Update** 1065 * The `updated_at` column will always be set to `time.Now()`. If you need to override 1066 this value you will need to fall back to another method in the meantime: `queries.Raw()`, 1067 overriding `updated_at` in all of your objects using a hook, or create your own wrapper. 1068 * **Upsert** 1069 * `created_at` will be set automatically if it is a zero value, otherwise your supplied value 1070 will be used. To set `created_at` to `null`, set `Valid` to false and `Time` to a non-zero value. 1071 * The `updated_at` column will always be set to `time.Now()`. 1072 1073 ### Automatic DeletedAt (Soft Delete) 1074 1075 Soft deletes are a way of deleting records in a database for the average query 1076 without actually removing the data. This type of thing is important in certain 1077 scenarios where data retention is important. It is typically done by adding a 1078 `deleted` bool or a `deleted_at` timestamp to each table in the database 1079 that can be soft deleted and subsequent queries on that table should always 1080 make sure that `deleted != true` or `deleted_at is null` to prevent showing 1081 "deleted" data. 1082 1083 SQLBoiler uses the `deleted_at` variant to provide this functionality. If your 1084 table has a nullable timestamp field named `deleted_at` it will be a candidate 1085 for soft-deletion. 1086 1087 *NOTE*: As of writing soft-delete is opt-in via `--add-soft-deletes` and is 1088 liable to change in future versions. 1089 1090 *NOTE*: There is a query mod to bypass soft delete for a specific query by using 1091 `qm.WithDeleted`, note that there is no way to do this for Exists/Find helpers 1092 yet. 1093 1094 *NOTE*: The `Delete` helpers will _not_ set `updated_at` currently. The current 1095 philosophy is that deleting the object is simply metadata and since it returns 1096 in no queries (other than raw ones) the updated_at will no longer be relevant. 1097 This could change in future versions if people disagree with this but it is 1098 the current behavior. 1099 1100 ### Query Building 1101 1102 We generate "Starter" methods for you. These methods are named as the plural versions of your model, 1103 for example: `models.Jets()`. Starter methods are used to build queries using our 1104 [Query Mod System](#query-mod-system). They take a slice of [Query Mods](#query-mod-system) 1105 as parameters, and end with a call to a [Finisher](#finishers) method. 1106 1107 Here are a few examples: 1108 1109 ```go 1110 // SELECT COUNT(*) FROM pilots; 1111 count, err := models.Pilots().Count(ctx, db) 1112 1113 // SELECT * FROM "pilots" LIMIT 5; 1114 pilots, err := models.Pilots(qm.Limit(5)).All(ctx, db) 1115 1116 // DELETE FROM "pilots" WHERE "id"=$1; 1117 err := models.Pilots(qm.Where("id=?", 1)).DeleteAll(ctx, db) 1118 // type safe version of above 1119 err := models.Pilots(models.PilotWhere.ID.EQ(1)).DeleteAll(ctx, db) 1120 ``` 1121 1122 In the event that you would like to build a query and specify the table yourself, you 1123 can do so using `models.NewQuery()`: 1124 1125 ```go 1126 // Select all rows from the pilots table by using the From query mod. 1127 err := models.NewQuery(db, qm.From("pilots")).All(ctx, db) 1128 ``` 1129 1130 As you can see, [Query Mods](#query-mod-system) allow you to modify your 1131 queries, and [Finishers](#finishers) allow you to execute the final action. 1132 1133 We also generate query building helper methods for your relationships as well. Take a look at our 1134 [Relationships Query Building](#relationships) section for some additional query building information. 1135 1136 ### Query Mod System 1137 1138 The query mod system allows you to modify queries created with 1139 [Starter](#query-building) methods when performing query building. 1140 See examples below. 1141 1142 **NOTE:** SQLBoiler generates type-safe identifiers based on your database 1143 tables, columns and relationships. Using these is a bit more verbose, but is 1144 especially safe since when the names change in the database the generated 1145 code will be different causing compilation failures instead of runtime 1146 errors. It is highly recommended you use these instead of regular strings. 1147 See [Constants](#constants) for more details. 1148 1149 **NOTE:** You will notice that there is printf used below mixed with SQL 1150 statements. This is normally NOT OK if the user is able to supply any of 1151 the sql string, but here we always use a `?` placeholder and pass arguments 1152 so that the only thing that's being printf'd are constants which makes it 1153 safe, but be careful! 1154 1155 ```go 1156 // Dot import so we can access query mods directly instead of prefixing with "qm." 1157 import . "github.com/volatiletech/sqlboiler/v4/queries/qm" 1158 1159 // Use a raw query against a generated struct (Pilot in this example) 1160 // If this query mod exists in your call, it will override the others. 1161 // "?" placeholders are not supported here, use "$1, $2" etc. 1162 SQL("select * from pilots where id=$1", 10) 1163 models.Pilots(SQL("select * from pilots where id=$1", 10)).All() 1164 1165 Select("id", "name") // Select specific columns. 1166 Select(models.PilotColumns.ID, models.PilotColumns.Name) 1167 From("pilots as p") // Specify the FROM table manually, can be useful for doing complex queries. 1168 From(models.TableNames.Pilots + " as p") 1169 1170 // WHERE clause building 1171 Where("name=?", "John") 1172 models.PilotWhere.Name.EQ("John") 1173 And("age=?", 24) 1174 // No equivalent type safe query yet 1175 Or("height=?", 183) 1176 // No equivalent type safe query yet 1177 1178 Where("(name=? and age=?) or (age=?)", "John", 5, 6) 1179 // Expr allows manual grouping of statements 1180 Where( 1181 Expr( 1182 models.PilotWhere.Name.EQ("John"), 1183 Or2(models.PilotWhere.Age.EQ(5)), 1184 ), 1185 Or2(models.PilotAge), 1186 ) 1187 1188 // WHERE IN clause building 1189 WhereIn("name, age in ?", "John", 24, "Tim", 33) // Generates: WHERE ("name","age") IN (($1,$2),($3,$4)) 1190 WhereIn(fmt.Sprintf("%s, %s in ?", models.PilotColumns.Name, models.PilotColumns.Age, "John", 24, "Tim", 33)) 1191 AndIn("weight in ?", 84) 1192 AndIn(models.PilotColumns.Weight + " in ?", 84) 1193 OrIn("height in ?", 183, 177, 204) 1194 OrIn(models.PilotColumns.Height + " in ?", 183, 177, 204) 1195 1196 InnerJoin("pilots p on jets.pilot_id=?", 10) 1197 InnerJoin(models.TableNames.Pilots + " p on " + models.TableNames.Jets + "." + models.JetColumns.PilotID + "=?", 10) 1198 1199 GroupBy("name") 1200 GroupBy("name like ? DESC, name", "John") 1201 GroupBy(models.PilotColumns.Name) 1202 OrderBy("age, height") 1203 OrderBy(models.PilotColumns.Age, models.PilotColumns.Height) 1204 1205 Having("count(jets) > 2") 1206 Having(fmt.Sprintf("count(%s) > 2", models.TableNames.Jets) 1207 1208 Limit(15) 1209 Offset(5) 1210 1211 // Explicit locking 1212 For("update nowait") 1213 1214 // Common Table Expressions 1215 With("cte_0 AS (SELECT * FROM table_0 WHERE thing=$1 AND stuff=$2)") 1216 1217 // Eager Loading -- Load takes the relationship name, ie the struct field name of the 1218 // Relationship struct field you want to load. Optionally also takes query mods to filter on that query. 1219 Load("Languages", Where(...)) // If it's a ToOne relationship it's in singular form, ToMany is plural. 1220 Load(models.PilotRels.Languages, Where(...)) 1221 ``` 1222 1223 Note: We don't force you to break queries apart like this if you don't want to, the following 1224 is also valid and supported by query mods that take a clause: 1225 1226 ```go 1227 Where("(name=? OR age=?) AND height=?", "John", 24, 183) 1228 ``` 1229 1230 ### Function Variations 1231 1232 Functions can have variations generated for them by using the flags 1233 `--add-global-variants` and `--add-panic-variants`. Once you've used these 1234 flags or set the appropriate values in your configuration file extra method 1235 overloads will be generated. We've used the `Delete` method to demonstrate: 1236 1237 ```go 1238 // Set the global db handle for G method variants. 1239 boil.SetDB(db) 1240 1241 pilot, _ := models.FindPilot(ctx, db, 1) 1242 1243 err := pilot.Delete(ctx, db) // Regular variant, takes a db handle (boil.Executor interface). 1244 pilot.DeleteP(ctx, db) // Panic variant, takes a db handle and panics on error. 1245 err := pilot.DeleteG(ctx) // Global variant, uses the globally set db handle (boil.SetDB()). 1246 pilot.DeleteGP(ctx) // Global&Panic variant, combines the global db handle and panic on error. 1247 1248 db.Begin() // Normal sql package way of creating a transaction 1249 boil.BeginTx(ctx, nil) // Uses the global database handle set by boil.SetDB() (doesn't require flag) 1250 ``` 1251 1252 Note that it's slightly different for query building. 1253 1254 ### Finishers 1255 1256 Here are a list of all of the finishers that can be used in combination with 1257 [Query Building](#query-building). 1258 1259 Finishers all have `P` (panic) [method variations](#function-variations). To specify 1260 your db handle use the `G` or regular variation of the [Starter](#query-building) method. 1261 1262 ```go 1263 // These are called like the following: 1264 models.Pilots().All(ctx, db) 1265 1266 One() // Retrieve one row as object (same as LIMIT(1)) 1267 All() // Retrieve all rows as objects (same as SELECT * FROM) 1268 Count() // Number of rows (same as COUNT(*)) 1269 UpdateAll(models.M{"name": "John", "age": 23}) // Update all rows matching the built query. 1270 DeleteAll() // Delete all rows matching the built query. 1271 Exists() // Returns a bool indicating whether the row(s) for the built query exists. 1272 Bind(&myObj) // Bind the results of a query to your own struct object. 1273 Exec() // Execute an SQL query that does not require any rows returned. 1274 QueryRow() // Execute an SQL query expected to return only a single row. 1275 Query() // Execute an SQL query expected to return multiple rows. 1276 ``` 1277 1278 ### Raw Query 1279 1280 We provide `queries.Raw()` for executing raw queries. Generally you will want to use `Bind()` with 1281 this, like the following: 1282 1283 ```go 1284 err := queries.Raw("select * from pilots where id=$1", 5).Bind(ctx, db, &obj) 1285 ``` 1286 1287 You can use your own structs or a generated struct as a parameter to Bind. Bind supports both 1288 a single object for single row queries and a slice of objects for multiple row queries. 1289 1290 `queries.Raw()` also has a method that can execute a query without binding to an object, if required. 1291 1292 You also have `models.NewQuery()` at your disposal if you would still like to use [Query Building](#query-building) 1293 in combination with your own custom, non-generated model. 1294 1295 ### Binding 1296 1297 For a comprehensive ruleset for `Bind()` you can refer to our [pkg.go.dev](https://pkg.go.dev/github.com/volatiletech/sqlboiler/v4/queries#Bind). 1298 1299 The `Bind()` [Finisher](#finisher) allows the results of a query built with 1300 the [Raw SQL](#raw-query) method or the [Query Builder](#query-building) methods to be bound 1301 to your generated struct objects, or your own custom struct objects. 1302 1303 This can be useful for complex queries, queries that only require a small subset of data 1304 and have no need for the rest of the object variables, or custom join struct objects like 1305 the following: 1306 1307 ```go 1308 // Custom struct using two generated structs 1309 type PilotAndJet struct { 1310 models.Pilot `boil:",bind"` 1311 models.Jet `boil:",bind"` 1312 } 1313 1314 var paj PilotAndJet 1315 // Use a raw query 1316 err := queries.Raw(` 1317 select pilots.id as "pilots.id", pilots.name as "pilots.name", 1318 jets.id as "jets.id", jets.pilot_id as "jets.pilot_id", 1319 jets.age as "jets.age", jets.name as "jets.name", jets.color as "jets.color" 1320 from pilots inner join jets on jets.pilot_id=?`, 23, 1321 ).Bind(ctx, db, &paj) 1322 1323 // Use query building 1324 err := models.NewQuery( 1325 Select("pilots.id", "pilots.name", "jets.id", "jets.pilot_id", "jets.age", "jets.name", "jets.color"), 1326 From("pilots"), 1327 InnerJoin("jets on jets.pilot_id = pilots.id"), 1328 ).Bind(ctx, db, &paj) 1329 ``` 1330 1331 ```go 1332 // Custom struct for selecting a subset of data 1333 type JetInfo struct { 1334 AgeSum int `boil:"age_sum"` 1335 Count int `boil:"juicy_count"` 1336 } 1337 1338 var info JetInfo 1339 1340 // Use query building 1341 err := models.NewQuery(Select("sum(age) as age_sum", "count(*) as juicy_count", From("jets"))).Bind(ctx, db, &info) 1342 1343 // Use a raw query 1344 err := queries.Raw(`select sum(age) as "age_sum", count(*) as "juicy_count" from jets`).Bind(ctx, db, &info) 1345 ``` 1346 1347 We support the following struct tag modes for `Bind()` control: 1348 1349 ```go 1350 type CoolObject struct { 1351 // Don't specify a name, Bind will TitleCase the column 1352 // name, and try to match against this. 1353 Frog int 1354 1355 // Specify an alternative name for the column, it will 1356 // be titlecased for matching, can be whatever you like. 1357 Cat int `boil:"kitten"` 1358 1359 // Ignore this struct field, do not attempt to bind it. 1360 Pig int `boil:"-"` 1361 1362 // Instead of binding to this as a regular struct field 1363 // (like other sql-able structs eg. time.Time) 1364 // Recursively search inside the Dog struct for field names from the query. 1365 Dog `boil:",bind"` 1366 1367 // Same as the above, except specify a different table name 1368 Mouse `boil:"rodent,bind"` 1369 1370 // Ignore this struct field, do not attempt to bind it. 1371 Bird `boil:"-"` 1372 } 1373 ``` 1374 1375 ### Relationships 1376 1377 Helper methods will be generated for every to one and to many relationship structure 1378 you have defined in your database by using foreign keys. 1379 1380 We attach these helpers directly to your model struct, for example: 1381 1382 ```go 1383 jet, _ := models.FindJet(ctx, db, 1) 1384 1385 // "to one" relationship helper method. 1386 // This will retrieve the pilot for the jet. 1387 pilot, err := jet.Pilot().One(ctx, db) 1388 1389 // "to many" relationship helper method. 1390 // This will retrieve all languages for the pilot. 1391 languages, err := pilot.Languages().All(ctx, db) 1392 ``` 1393 1394 If your relationship involves a join table SQLBoiler will figure it out for you transparently. 1395 1396 It is important to note that you should use `Eager Loading` if you plan 1397 on loading large collections of rows, to avoid N+1 performance problems. 1398 1399 For example, take the following: 1400 1401 ```go 1402 // Avoid this loop query pattern, it is slow. 1403 jets, _ := models.Jets().All(ctx, db) 1404 pilots := make([]models.Pilot, len(jets)) 1405 for i := 0; i < len(jets); i++ { 1406 pilots[i] = jets[i].Pilot().OneP(ctx, db) 1407 } 1408 1409 // Instead, use Eager Loading! 1410 jets, _ := models.Jets(Load("Pilot")).All(ctx, db) 1411 // Type safe relationship names exist too: 1412 jets, _ := models.Jets(Load(models.JetRels.Pilot)).All(ctx, db) 1413 1414 // Then access the loaded structs using the special Relation field 1415 for _, j := range jets { 1416 _ = j.R.Pilot 1417 } 1418 ``` 1419 1420 Eager loading can be combined with other query mods, and it can also eager load recursively. 1421 1422 ```go 1423 // Example of a nested load. 1424 // Each jet will have its pilot loaded, and each pilot will have its languages loaded. 1425 jets, _ := models.Jets(Load("Pilot.Languages")).All(ctx, db) 1426 // Note that each level of a nested Load call will be loaded. No need to call Load() multiple times. 1427 1428 // Type safe queries exist for this too! 1429 jets, _ := models.Jets(Load(Rels(models.JetRels.Pilot, models.PilotRels.Languages))).All(ctx, db) 1430 1431 // A larger example. In the below scenario, Pets will only be queried one time, despite 1432 // showing up twice because they're the same query (the user's pets) 1433 users, _ := models.Users( 1434 Load("Pets.Vets"), 1435 // the query mods passed in below only affect the query for Toys 1436 // to use query mods against Pets itself, you must declare it separately 1437 Load("Pets.Toys", Where("toys.deleted = ?", isDeleted)), 1438 Load("Property"), 1439 Where("age > ?", 23), 1440 ).All(ctx, db) 1441 ``` 1442 1443 We provide the following methods for managing relationships on objects: 1444 1445 **To One** 1446 - `SetX()`: Set the foreign key to point to something else: jet.SetPilot(...) 1447 - `RemoveX()`: Null out the foreign key, effectively removing the relationship between these two objects: jet.RemovePilot(...) 1448 1449 **To Many** 1450 - `AddX()`: Add more relationships to the existing set of related Xs: pilot.AddLanguages(...) 1451 - `SetX()`: Remove all existing relationships, and replace them with the provided set: pilot.SetLanguages(...) 1452 - `RemoveX()`: Remove all provided relationships: pilot.RemoveLanguages(...) 1453 1454 **Important**: Remember to use transactions around these set helpers for performance 1455 and data integrity. SQLBoiler does not do this automatically due to it's transparent API which allows 1456 you to batch any number of calls in a transaction without spawning subtransactions you don't know 1457 about or are not supported by your database. 1458 1459 **To One** code examples: 1460 1461 ```go 1462 jet, _ := models.FindJet(ctx, db, 1) 1463 pilot, _ := models.FindPilot(ctx, db, 1) 1464 1465 // Set the pilot to an existing jet 1466 err := jet.SetPilot(ctx, db, false, &pilot) 1467 1468 pilot = models.Pilot{ 1469 Name: "Erlich", 1470 } 1471 1472 // Insert the pilot into the database and assign it to a jet 1473 err := jet.SetPilot(ctx, db, true, &pilot) 1474 1475 // Remove a relationship. This method only exists for foreign keys that can be NULL. 1476 err := jet.RemovePilot(ctx, db, &pilot) 1477 ``` 1478 1479 **To Many** code examples: 1480 1481 ```go 1482 pilots, _ := models.Pilots().All(ctx, db) 1483 languages, _ := models.Languages().All(ctx, db) 1484 1485 // Set a group of language relationships 1486 err := pilots.SetLanguages(db, false, &languages) 1487 1488 languages := []*models.Language{ 1489 {Language: "Strayan"}, 1490 {Language: "Yupik"}, 1491 {Language: "Pawnee"}, 1492 } 1493 1494 // Insert new a group of languages and assign them to a pilot 1495 err := pilots.SetLanguages(ctx, db, true, languages...) 1496 1497 // Add another language relationship to the existing set of relationships 1498 err := pilots.AddLanguages(ctx, db, false, &someOtherLanguage) 1499 1500 anotherLanguage := models.Language{Language: "Archi"} 1501 1502 // Insert and then add another language relationship 1503 err := pilots.AddLanguages(ctx, db, true, &anotherLanguage) 1504 1505 // Remove a group of relationships 1506 err := pilots.RemoveLanguages(ctx, db, languages...) 1507 ``` 1508 1509 ### Hooks 1510 1511 Before and After hooks are available for most operations. If you don't need them you can 1512 shrink the size of the generated code by disabling them with the `--no-hooks` flag. 1513 1514 Every generated package that includes hooks has the following `HookPoints` defined: 1515 1516 ```go 1517 const ( 1518 BeforeInsertHook HookPoint = iota + 1 1519 BeforeUpdateHook 1520 BeforeDeleteHook 1521 BeforeUpsertHook 1522 AfterInsertHook 1523 AfterSelectHook 1524 AfterUpdateHook 1525 AfterDeleteHook 1526 AfterUpsertHook 1527 ) 1528 ``` 1529 1530 To register a hook for your model you will need to create the hook function, and attach 1531 it with the `AddModelHook` method. Here is an example of a before insert hook: 1532 1533 ```go 1534 // Define my hook function 1535 func myHook(ctx context.Context, exec boil.ContextExecutor, p *Pilot) error { 1536 // Do stuff 1537 return nil 1538 } 1539 1540 // Register my before insert hook for pilots 1541 models.AddPilotHook(boil.BeforeInsertHook, myHook) 1542 ``` 1543 1544 Your `ModelHook` will always be defined as `func(context.Context, boil.ContextExecutor, *Model) error` if context is not turned off. 1545 1546 #### Skipping Hooks 1547 1548 You can skip hooks by using the `boil.SkipHooks` on the context you pass in 1549 to a given query. 1550 1551 ### Transactions 1552 1553 The `boil.Executor` and `boil.ContextExecutor` interface powers all of SQLBoiler. This means 1554 anything that conforms to the three `Exec/Query/QueryRow` methods (and their context-aware variants) 1555 can be used to execute queries. `sql.DB`, `sql.Tx` as well as other 1556 libraries (`sqlx`) conform to this interface, and therefore any of these things may be 1557 used as an executor for any query in the system. This makes using transactions very simple: 1558 1559 ```go 1560 tx, err := db.BeginTx(ctx, nil) 1561 if err != nil { 1562 return err 1563 } 1564 1565 users, _ := models.Pilots().All(ctx, tx) 1566 users.DeleteAll(ctx, tx) 1567 1568 // Rollback or commit 1569 tx.Commit() 1570 tx.Rollback() 1571 ``` 1572 1573 It's also worth noting that there's a way to take advantage of `boil.SetDB()` 1574 by using the 1575 [boil.BeginTx()](https://pkg.go.dev/github.com/volatiletech/sqlboiler/v4/boil#BeginTx) 1576 function. This opens a transaction using the globally stored database. 1577 1578 ### Debug Logging 1579 1580 Debug logging will print your generated SQL statement and the arguments it is using. 1581 Debug logging can be toggled on globally by setting the following global variable to `true`: 1582 1583 ```go 1584 boil.DebugMode = true 1585 1586 // Optionally set the writer as well. Defaults to os.Stdout 1587 fh, _ := os.Open("debug.txt") 1588 boil.DebugWriter = fh 1589 ``` 1590 1591 Note: Debug output is messy at the moment. This is something we would like addressed. 1592 1593 ### Select 1594 1595 Select is done through [Query Building](#query-building) and [Find](#find). Here's a short example: 1596 1597 ```go 1598 // Select one pilot 1599 pilot, err := models.Pilots(qm.Where("name=?", "Tim")).One(ctx, db) 1600 // Type safe variant 1601 pilot, err := models.Pilots(models.PilotWhere.Name.EQ("Tim")).One(ctx, db) 1602 1603 // Select specific columns of many jets 1604 jets, err := models.Jets(qm.Select("age", "name")).All(ctx, db) 1605 // Type safe variant 1606 jets, err := models.Jets(qm.Select(models.JetColumns.Age, models.JetColumns.Name)).All(ctx, db) 1607 ``` 1608 1609 ### Find 1610 1611 Find is used to find a single row by primary key: 1612 1613 ```go 1614 // Retrieve pilot with all columns filled 1615 pilot, err := models.FindPilot(ctx, db, 1) 1616 1617 // Retrieve a subset of column values 1618 jet, err := models.FindJet(ctx, db, 1, "name", "color") 1619 ``` 1620 1621 ### Insert 1622 1623 The main thing to be aware of with `Insert` is how the `columns` argument 1624 operates. You can supply one of the following column lists: 1625 `boil.Infer`, `boil.Whitelist`, `boil.Blacklist`, or `boil.Greylist`. 1626 1627 These lists control what fields are inserted into the database, and what values 1628 are returned to your struct from the database (default, auto incrementing, 1629 trigger-based columns are candidates for this). Your struct will have those 1630 values after the insert is complete. 1631 1632 When you use inference `sqlboiler` looks at your Go struct field values and if 1633 the field value is the Go zero value and that field has a default value in the 1634 database it will not insert that field, instead it will get the value from the 1635 database. Keep in mind `sqlboiler` cannot read or understand your default 1636 values set in the database, so the Go zero value is what's important here (this 1637 can be especially troubling for default true bool fields). Use a whitelist or 1638 greylist in cases where you want to insert a Go zero value. 1639 1640 | Column List | Behavior | 1641 | ----------- | -------- | 1642 | Infer | Infer the column list using "smart" rules 1643 | Whitelist | Insert only the columns specified in this list 1644 | Blacklist | Infer the column list, but ensure these columns are not inserted 1645 | Greylist | Infer the column list, but ensure these columns are inserted 1646 1647 **NOTE:** CreatedAt/UpdatedAt are not included in `Whitelist` automatically. 1648 1649 See the documentation for 1650 [boil.Columns.InsertColumnSet](https://pkg.go.dev/github.com/volatiletech/sqlboiler/v4/boil/#Columns.InsertColumnSet) 1651 for more details. 1652 1653 ```go 1654 var p1 models.Pilot 1655 p1.Name = "Larry" 1656 err := p1.Insert(ctx, db, boil.Infer()) // Insert the first pilot with name "Larry" 1657 // p1 now has an ID field set to 1 1658 1659 var p2 models.Pilot 1660 p2.Name = "Boris" 1661 err := p2.Insert(ctx, db, boil.Infer()) // Insert the second pilot with name "Boris" 1662 // p2 now has an ID field set to 2 1663 1664 var p3 models.Pilot 1665 p3.ID = 25 1666 p3.Name = "Rupert" 1667 err := p3.Insert(ctx, db, boil.Infer()) // Insert the third pilot with a specific ID 1668 // The id for this row was inserted as 25 in the database. 1669 1670 var p4 models.Pilot 1671 p4.ID = 0 1672 p4.Name = "Nigel" 1673 err := p4.Insert(ctx, db, boil.Whitelist("id", "name")) // Insert the fourth pilot with a zero value ID 1674 // The id for this row was inserted as 0 in the database. 1675 // Note: We had to use the whitelist for this, otherwise 1676 // SQLBoiler would presume you wanted to auto-increment 1677 ``` 1678 1679 ### Update 1680 `Update` can be performed on a single object, a slice of objects or as a [Finisher](#finishers) 1681 for a collection of rows. 1682 1683 `Update` on a single object optionally takes a `whitelist`. The purpose of the 1684 whitelist is to specify which columns in your object should be updated in the database. 1685 1686 Like `Insert`, this method also takes a `Columns` type, but the behavior is 1687 slightly different. Although the descriptions below look similar the full 1688 documentation reveals the differences. Note that all inference is based on 1689 the Go types zero value and not the database default value, read the `Insert` 1690 documentation above for more details. 1691 1692 | Column List | Behavior | 1693 | ----------- | -------- | 1694 | Infer | Infer the column list using "smart" rules 1695 | Whitelist | Update only the columns specified in this list 1696 | Blacklist | Infer the column list for updating, but ensure these columns are not updated 1697 | Greylist | Infer the column list, but ensure these columns are updated 1698 1699 **NOTE:** CreatedAt/UpdatedAt are not included in `Whitelist` automatically. 1700 1701 See the documentation for 1702 [boil.Columns.UpdateColumnSet](https://pkg.go.dev/github.com/volatiletech/sqlboiler/v4/boil/#Columns.UpdateColumnSet) 1703 for more details. 1704 1705 ```go 1706 // Find a pilot and update his name 1707 pilot, _ := models.FindPilot(ctx, db, 1) 1708 pilot.Name = "Neo" 1709 rowsAff, err := pilot.Update(ctx, db, boil.Infer()) 1710 1711 // Update a slice of pilots to have the name "Smith" 1712 pilots, _ := models.Pilots().All(ctx, db) 1713 rowsAff, err := pilots.UpdateAll(ctx, db, models.M{"name": "Smith"}) 1714 1715 // Update all pilots in the database to to have the name "Smith" 1716 rowsAff, err := models.Pilots().UpdateAll(ctx, db, models.M{"name": "Smith"}) 1717 ``` 1718 1719 ### Delete 1720 1721 Delete a single object, a slice of objects or specific objects through [Query Building](#query-building). 1722 1723 ```go 1724 pilot, _ := models.FindPilot(db, 1) 1725 // Delete the pilot from the database 1726 rowsAff, err := pilot.Delete(ctx, db) 1727 1728 // Delete all pilots from the database 1729 rowsAff, err := models.Pilots().DeleteAll(ctx, db) 1730 1731 // Delete a slice of pilots from the database 1732 pilots, _ := models.Pilots().All(ctx, db) 1733 rowsAff, err := pilots.DeleteAll(ctx, db) 1734 ``` 1735 1736 ### Upsert 1737 1738 [Upsert](https://www.postgresql.org/docs/9.5/static/sql-insert.html) allows you to perform an insert 1739 that optionally performs an update when a conflict is found against existing row values. 1740 1741 The `updateColumns` and `insertColumns` operates in the same fashion that it does for [Update](#update) 1742 and [Insert](#insert). 1743 1744 1745 If an insert is performed, your object will be updated with any missing default values from the database, 1746 such as auto-incrementing column values. 1747 1748 ```go 1749 var p1 models.Pilot 1750 p1.ID = 5 1751 p1.Name = "Gaben" 1752 1753 // INSERT INTO pilots ("id", "name") VALUES($1, $2) 1754 // ON CONFLICT DO NOTHING 1755 err := p1.Upsert(ctx, db, false, nil, boil.Infer()) 1756 1757 // INSERT INTO pilots ("id", "name") VALUES ($1, $2) 1758 // ON CONFLICT ("id") DO UPDATE SET "name" = EXCLUDED."name" 1759 err := p1.Upsert(ctx, db, true, []string{"id"}, boil.Whitelist("name"), boil.Infer()) 1760 1761 // Set p1.ID to a zero value. We will have to use the whitelist now. 1762 p1.ID = 0 1763 p1.Name = "Hogan" 1764 1765 // INSERT INTO pilots ("id", "name") VALUES ($1, $2) 1766 // ON CONFLICT ("id") DO UPDATE SET "name" = EXCLUDED."name" 1767 err := p1.Upsert(ctx, db, true, []string{"id"}, boil.Whitelist("name"), boil.Whitelist("id", "name")) 1768 ``` 1769 1770 * **Postgres** 1771 * The `updateOnConflict` argument allows you to specify whether you would like Postgres 1772 to perform a `DO NOTHING` on conflict, opposed to a `DO UPDATE`. For MySQL and MSSQL, this param will not be generated. 1773 * The `conflictColumns` argument allows you to specify the `ON CONFLICT` columns for Postgres. 1774 For MySQL and MSSQL, this param will not be generated. 1775 * **MySQL and MSSQL** 1776 * Passing `boil.None()` for `updateColumns` allows to perform a `DO NOTHING` on conflict similar to Postgres. 1777 1778 Note: Passing a different set of column values to the update component is not currently supported. 1779 1780 Note: Upsert is now not guaranteed to be provided by SQLBoiler and it's now up to each driver 1781 individually to support it since it's a bit outside of the reach of the sql standard. 1782 1783 ### Reload 1784 In the event that your objects get out of sync with the database for whatever reason, 1785 you can use `Reload` and `ReloadAll` to reload the objects using the primary key values 1786 attached to the objects. 1787 1788 ```go 1789 pilot, _ := models.FindPilot(ctx, db, 1) 1790 1791 // > Object becomes out of sync for some reason, perhaps async processing 1792 1793 // Refresh the object with the latest data from the db 1794 err := pilot.Reload(ctx, db) 1795 1796 // Reload all objects in a slice 1797 pilots, _ := models.Pilots().All(ctx, db) 1798 err := pilots.ReloadAll(ctx, db) 1799 ``` 1800 1801 Note: `Reload` and `ReloadAll` are not recursive, if you need your relationships reloaded 1802 you will need to call the `Reload` methods on those yourself. 1803 1804 ### Exists 1805 1806 ```go 1807 jet, err := models.FindJet(ctx, db, 1) 1808 1809 // Check if the pilot assigned to this jet exists. 1810 exists, err := jet.Pilot().Exists(ctx, db) 1811 1812 // Check if the pilot with ID 5 exists 1813 exists, err := models.Pilots(Where("id=?", 5)).Exists(ctx, db) 1814 ``` 1815 1816 ### Enums 1817 1818 If your MySQL or Postgres tables use enums we will generate constants that hold their values 1819 that you can use in your queries. For example: 1820 1821 ```sql 1822 CREATE TYPE workday AS ENUM('monday', 'tuesday', 'wednesday', 'thursday', 'friday'); 1823 1824 CREATE TABLE event_one ( 1825 id serial PRIMARY KEY NOT NULL, 1826 name VARCHAR(255), 1827 day workday NOT NULL 1828 ); 1829 ``` 1830 1831 An enum type defined like the above, being used by a table, will generate the following enums: 1832 1833 ```go 1834 const ( 1835 WorkdayMonday = "monday" 1836 WorkdayTuesday = "tuesday" 1837 WorkdayWednesday = "wednesday" 1838 WorkdayThursday = "thursday" 1839 WorkdayFriday = "friday" 1840 ) 1841 ``` 1842 1843 For Postgres we use `enum type name + title cased` value to generate the const variable name. 1844 For MySQL we use `table name + column name + title cased value` to generate the const variable name. 1845 1846 Note: If your enum holds a value we cannot parse correctly due, to non-alphabet characters for example, 1847 it may not be generated. In this event, you will receive errors in your generated tests because 1848 the value randomizer in the test suite does not know how to generate valid enum values. You will 1849 still be able to use your generated library, and it will still work as expected, but the only way 1850 to get the tests to pass in this event is to either use a parsable enum value or use a regular column 1851 instead of an enum. 1852 1853 ### Constants 1854 1855 The models package will also contain some structs that contain all table, 1856 column, relationship names harvested from the database at generation time. Type 1857 safe where query mods are also generated. 1858 1859 There are type safe identifiers at: 1860 * models.TableNames.TableName 1861 * models.ModelColumns.ColumnName 1862 * models.ModelWhere.ColumnName.Operator 1863 * models.ModelRels.ForeignTableName 1864 1865 For table names they're generated under `models.TableNames`: 1866 1867 ```go 1868 // Generated code from models package 1869 var TableNames = struct { 1870 Messages string 1871 Purchases string 1872 }{ 1873 Messages: "messages", 1874 Purchases: "purchases", 1875 } 1876 1877 // Usage example: 1878 fmt.Println(models.TableNames.Messages) 1879 ``` 1880 1881 For column names they're generated under `models.{Model}Columns`: 1882 ```go 1883 // Generated code from models package 1884 var MessageColumns = struct { 1885 ID string 1886 PurchaseID string 1887 }{ 1888 ID: "id", 1889 PurchaseID: "purchase_id", 1890 } 1891 1892 // Usage example: 1893 fmt.Println(models.MessageColumns.ID) 1894 ``` 1895 1896 For where clauses they're generated under `models.{Model}Where.{Column}.{Operator}`: 1897 ```go 1898 var MessageWhere = struct { 1899 ID whereHelperint 1900 Text whereHelperstring 1901 }{ 1902 ID: whereHelperint{field: `id`}, 1903 PurchaseID: whereHelperstring{field: `purchase_id`}, 1904 } 1905 1906 // Usage example: 1907 models.Messages(models.MessageWhere.PurchaseID.EQ("hello")) 1908 ``` 1909 1910 For eager loading relationships ther're generated under `models.{Model}Rels`: 1911 ```go 1912 // Generated code from models package 1913 var MessageRels = struct { 1914 Purchase string 1915 }{ 1916 Purchase: "Purchase", 1917 } 1918 1919 // Usage example: 1920 fmt.Println(models.MessageRels.Purchase) 1921 ``` 1922 1923 **NOTE:** You can also assign the ModelWhere or ColumnNames to a variable and 1924 although you probably pay some performance penalty with it sometimes the 1925 readability increase is worth it: 1926 1927 ```go 1928 cols := &models.UserColumns 1929 where := &models.UserWhere 1930 1931 u, err := models.Users(where.Name.EQ("hello"), qm.Or(cols.Age + "=?", 5)) 1932 ``` 1933 1934 ## FAQ 1935 1936 #### Won't compiling models for a huge database be very slow? 1937 1938 No, because Go's toolchain - unlike traditional toolchains - makes the compiler do most of the work 1939 instead of the linker. This means that when the first `go install` is done it can take 1940 a little bit of time because there is a lot of code that is generated. However, because of this 1941 work balance between the compiler and linker in Go, linking to that code afterwards in the subsequent 1942 compiles is extremely fast. 1943 1944 #### Missing imports for generated package 1945 1946 The generated models might import a couple of packages that are not on your system already, so 1947 `cd` into your generated models directory and type `go get -u -t` to fetch them. You will only need 1948 to run this command once, not per generation. 1949 1950 #### How should I handle multiple schemas? 1951 1952 If your database uses multiple schemas you should generate a new package for each of your schemas. 1953 Note that this only applies to databases that use real, SQL standard schemas (like PostgreSQL), not 1954 fake schemas (like MySQL). 1955 1956 #### How do I use types.BytesArray for Postgres bytea arrays? 1957 1958 Only "escaped format" is supported for types.BytesArray. This means that your byte slice needs to have 1959 a format of "\\x00" (4 bytes per byte) opposed to "\x00" (1 byte per byte). This is to maintain compatibility 1960 with all Postgres drivers. Example: 1961 1962 `x := types.BytesArray{0: []byte("\\x68\\x69")}` 1963 1964 Please note that multi-dimensional Postgres ARRAY types are not supported at this time. 1965 1966 #### Why aren't my time.Time or null.Time fields working in MySQL? 1967 1968 You *must* use a DSN flag in MySQL connections, see: [Requirements](#requirements) 1969 1970 #### Where is the homepage? 1971 1972 The homepage for the [SQLBoiler](https://github.com/volatiletech/sqlboiler) [Golang ORM](https://github.com/volatiletech/sqlboiler) 1973 generator is located at: https://github.com/volatiletech/sqlboiler 1974 1975 #### Why are the auto-generated tests failing? 1976 1977 The tests generated for your models package with sqlboiler are fairly 1978 error-prone. They are usually broken by constraints in the database 1979 that sqlboiler can't hope to understand. 1980 1981 During regular run-time this isn't an issue because your code will throw errors 1982 and you will fix it however the auto-generated tests can only report those 1983 errors and it seems like something is wrong when in reality the only issue is 1984 that the auto generated tests can't understand that your `text` column is 1985 validated by a regex that says it must be composed solely of the 'b' character 1986 repeated 342 times. 1987 1988 These tests are broken especially by foreign key constraints because of the 1989 parallelism we use. There's also no understanding in the tests of dependencies 1990 based on these foreign keys. As such there is a process that removes the foreign 1991 keys from your schema when they are run, if this process messes up you will get 1992 errors relating to foreign key constraints. 1993 1994 ## Benchmarks 1995 1996 If you'd like to run the benchmarks yourself check out our [boilbench](https://github.com/volatiletech/boilbench) repo. 1997 1998 ```bash 1999 go test -bench . -benchmem 2000 ``` 2001 2002 ### Results (lower is better) 2003 2004 Test machine: 2005 ```text 2006 OS: Ubuntu 16.04 2007 CPU: Intel(R) Core(TM) i7-4771 CPU @ 3.50GHz 2008 Mem: 16GB 2009 Go: go version go1.8.1 linux/amd64 2010 ``` 2011 2012 The graphs below have many runs like this as input to calculate errors. Here 2013 is a sample run: 2014 2015 ```text 2016 BenchmarkGORMSelectAll/gorm-8 20000 66500 ns/op 28998 B/op 455 allocs/op 2017 BenchmarkGORPSelectAll/gorp-8 50000 31305 ns/op 9141 B/op 318 allocs/op 2018 BenchmarkXORMSelectAll/xorm-8 20000 66074 ns/op 16317 B/op 417 allocs/op 2019 BenchmarkKallaxSelectAll/kallax-8 100000 18278 ns/op 7428 B/op 145 allocs/op 2020 BenchmarkBoilSelectAll/boil-8 100000 12759 ns/op 3145 B/op 67 allocs/op 2021 2022 BenchmarkGORMSelectSubset/gorm-8 20000 69469 ns/op 30008 B/op 462 allocs/op 2023 BenchmarkGORPSelectSubset/gorp-8 50000 31102 ns/op 9141 B/op 318 allocs/op 2024 BenchmarkXORMSelectSubset/xorm-8 20000 64151 ns/op 15933 B/op 414 allocs/op 2025 BenchmarkKallaxSelectSubset/kallax-8 100000 16996 ns/op 6499 B/op 132 allocs/op 2026 BenchmarkBoilSelectSubset/boil-8 100000 13579 ns/op 3281 B/op 71 allocs/op 2027 2028 BenchmarkGORMSelectComplex/gorm-8 20000 76284 ns/op 34566 B/op 521 allocs/op 2029 BenchmarkGORPSelectComplex/gorp-8 50000 31886 ns/op 9501 B/op 328 allocs/op 2030 BenchmarkXORMSelectComplex/xorm-8 20000 68430 ns/op 17694 B/op 464 allocs/op 2031 BenchmarkKallaxSelectComplex/kallax-8 50000 26095 ns/op 10293 B/op 212 allocs/op 2032 BenchmarkBoilSelectComplex/boil-8 100000 16403 ns/op 4205 B/op 102 allocs/op 2033 2034 BenchmarkGORMDelete/gorm-8 200000 10356 ns/op 5059 B/op 98 allocs/op 2035 BenchmarkGORPDelete/gorp-8 1000000 1335 ns/op 352 B/op 13 allocs/op 2036 BenchmarkXORMDelete/xorm-8 200000 10796 ns/op 4146 B/op 122 allocs/op 2037 BenchmarkKallaxDelete/kallax-8 300000 5141 ns/op 2241 B/op 48 allocs/op 2038 BenchmarkBoilDelete/boil-8 2000000 796 ns/op 168 B/op 8 allocs/op 2039 2040 BenchmarkGORMInsert/gorm-8 100000 15238 ns/op 8278 B/op 150 allocs/op 2041 BenchmarkGORPInsert/gorp-8 300000 4648 ns/op 1616 B/op 38 allocs/op 2042 BenchmarkXORMInsert/xorm-8 100000 12600 ns/op 6092 B/op 138 allocs/op 2043 BenchmarkKallaxInsert/kallax-8 100000 15115 ns/op 6003 B/op 126 allocs/op 2044 BenchmarkBoilInsert/boil-8 1000000 2249 ns/op 984 B/op 23 allocs/op 2045 2046 BenchmarkGORMUpdate/gorm-8 100000 18609 ns/op 9389 B/op 174 allocs/op 2047 BenchmarkGORPUpdate/gorp-8 500000 3180 ns/op 1536 B/op 35 allocs/op 2048 BenchmarkXORMUpdate/xorm-8 100000 13149 ns/op 5098 B/op 149 allocs/op 2049 BenchmarkKallaxUpdate/kallax-8 100000 22880 ns/op 11366 B/op 219 allocs/op 2050 BenchmarkBoilUpdate/boil-8 1000000 1810 ns/op 936 B/op 18 allocs/op 2051 2052 BenchmarkGORMRawBind/gorm-8 20000 65821 ns/op 30502 B/op 444 allocs/op 2053 BenchmarkGORPRawBind/gorp-8 50000 31300 ns/op 9141 B/op 318 allocs/op 2054 BenchmarkXORMRawBind/xorm-8 20000 62024 ns/op 15588 B/op 403 allocs/op 2055 BenchmarkKallaxRawBind/kallax-8 200000 7843 ns/op 4380 B/op 46 allocs/op 2056 BenchmarkSQLXRawBind/sqlx-8 100000 13056 ns/op 4572 B/op 55 allocs/op 2057 BenchmarkBoilRawBind/boil-8 200000 11519 ns/op 4638 B/op 55 allocs/op 2058 ``` 2059 2060 <img src="http://i.imgur.com/SltE8UQ.png"/><img src="http://i.imgur.com/lzvM5jJ.png"/><img src="http://i.imgur.com/SS0zNd2.png"/> 2061 2062 <img src="http://i.imgur.com/Kk0IM0J.png"/><img src="http://i.imgur.com/1IFtpdP.png"/><img src="http://i.imgur.com/t6Usecx.png"/> 2063 2064 <img src="http://i.imgur.com/98DOzcr.png"/><img src="http://i.imgur.com/NSp5r4Q.png"/><img src="http://i.imgur.com/dEGlOgI.png"/> 2065 2066 <img src="http://i.imgur.com/W0zhuGb.png"/><img src="http://i.imgur.com/YIvDuFv.png"/><img src="http://i.imgur.com/sKwuMaU.png"/> 2067 2068 <img src="http://i.imgur.com/ZUMYVmw.png"/><img src="http://i.imgur.com/T61rH3K.png"/><img src="http://i.imgur.com/lDr0xhY.png"/> 2069 2070 <img src="http://i.imgur.com/LWo10M9.png"/><img src="http://i.imgur.com/Td15owT.png"/><img src="http://i.imgur.com/45XXw4K.png"/> 2071 2072 <img src="http://i.imgur.com/lpP8qds.png"/><img src="http://i.imgur.com/hLyH3jQ.png"/><img src="http://i.imgur.com/C2v10t3.png"/>